diff options
Diffstat (limited to 'arch/mn10300/mm/cache-flush-icache.c')
-rw-r--r-- | arch/mn10300/mm/cache-flush-icache.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/arch/mn10300/mm/cache-flush-icache.c b/arch/mn10300/mm/cache-flush-icache.c index 0e471e1cb2da..fdb1a9db20f0 100644 --- a/arch/mn10300/mm/cache-flush-icache.c +++ b/arch/mn10300/mm/cache-flush-icache.c | |||
@@ -11,6 +11,9 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
13 | #include <asm/cacheflush.h> | 13 | #include <asm/cacheflush.h> |
14 | #include <asm/smp.h> | ||
15 | #include "cache-smp.h" | ||
16 | |||
14 | /** | 17 | /** |
15 | * flush_icache_page - Flush a page from the dcache and invalidate the icache | 18 | * flush_icache_page - Flush a page from the dcache and invalidate the icache |
16 | * @vma: The VMA the page is part of. | 19 | * @vma: The VMA the page is part of. |
@@ -22,9 +25,15 @@ | |||
22 | void flush_icache_page(struct vm_area_struct *vma, struct page *page) | 25 | void flush_icache_page(struct vm_area_struct *vma, struct page *page) |
23 | { | 26 | { |
24 | unsigned long start = page_to_phys(page); | 27 | unsigned long start = page_to_phys(page); |
28 | unsigned long flags; | ||
29 | |||
30 | flags = smp_lock_cache(); | ||
31 | |||
32 | mn10300_local_dcache_flush_page(start); | ||
33 | mn10300_local_icache_inv_page(start); | ||
25 | 34 | ||
26 | mn10300_dcache_flush_page(start); | 35 | smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start, start + PAGE_SIZE); |
27 | mn10300_icache_inv_page(start); | 36 | smp_unlock_cache(flags); |
28 | } | 37 | } |
29 | EXPORT_SYMBOL(flush_icache_page); | 38 | EXPORT_SYMBOL(flush_icache_page); |
30 | 39 | ||
@@ -82,8 +91,9 @@ static void flush_icache_page_range(unsigned long start, unsigned long end) | |||
82 | 91 | ||
83 | /* flush the dcache and invalidate the icache coverage on that | 92 | /* flush the dcache and invalidate the icache coverage on that |
84 | * region */ | 93 | * region */ |
85 | mn10300_dcache_flush_range2(addr + off, size); | 94 | mn10300_local_dcache_flush_range2(addr + off, size); |
86 | mn10300_icache_inv_range2(addr + off, size); | 95 | mn10300_local_icache_inv_range2(addr + off, size); |
96 | smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start, end); | ||
87 | } | 97 | } |
88 | 98 | ||
89 | /** | 99 | /** |
@@ -98,28 +108,32 @@ static void flush_icache_page_range(unsigned long start, unsigned long end) | |||
98 | void flush_icache_range(unsigned long start, unsigned long end) | 108 | void flush_icache_range(unsigned long start, unsigned long end) |
99 | { | 109 | { |
100 | unsigned long start_page, end_page; | 110 | unsigned long start_page, end_page; |
111 | unsigned long flags; | ||
112 | |||
113 | flags = smp_lock_cache(); | ||
101 | 114 | ||
102 | if (end > 0x80000000UL) { | 115 | if (end > 0x80000000UL) { |
103 | /* addresses above 0xa0000000 do not go through the cache */ | 116 | /* addresses above 0xa0000000 do not go through the cache */ |
104 | if (end > 0xa0000000UL) { | 117 | if (end > 0xa0000000UL) { |
105 | end = 0xa0000000UL; | 118 | end = 0xa0000000UL; |
106 | if (start >= end) | 119 | if (start >= end) |
107 | return; | 120 | goto done; |
108 | } | 121 | } |
109 | 122 | ||
110 | /* kernel addresses between 0x80000000 and 0x9fffffff do not | 123 | /* kernel addresses between 0x80000000 and 0x9fffffff do not |
111 | * require page tables, so we just map such addresses | 124 | * require page tables, so we just map such addresses |
112 | * directly */ | 125 | * directly */ |
113 | start_page = (start >= 0x80000000UL) ? start : 0x80000000UL; | 126 | start_page = (start >= 0x80000000UL) ? start : 0x80000000UL; |
114 | mn10300_dcache_flush_range(start_page, end); | 127 | mn10300_local_dcache_flush_range(start_page, end); |
115 | mn10300_icache_inv_range(start_page, end); | 128 | mn10300_local_icache_inv_range(start_page, end); |
129 | smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start_page, end); | ||
116 | if (start_page == start) | 130 | if (start_page == start) |
117 | return; | 131 | goto done; |
118 | end = start_page; | 132 | end = start_page; |
119 | } | 133 | } |
120 | 134 | ||
121 | start_page = start & PAGE_MASK; | 135 | start_page = start & PAGE_MASK; |
122 | end_page = end & PAGE_MASK; | 136 | end_page = (end - 1) & PAGE_MASK; |
123 | 137 | ||
124 | if (start_page == end_page) { | 138 | if (start_page == end_page) { |
125 | /* the first and last bytes are on the same page */ | 139 | /* the first and last bytes are on the same page */ |
@@ -132,6 +146,10 @@ void flush_icache_range(unsigned long start, unsigned long end) | |||
132 | /* more than 2 pages; just flush the entire cache */ | 146 | /* more than 2 pages; just flush the entire cache */ |
133 | mn10300_dcache_flush(); | 147 | mn10300_dcache_flush(); |
134 | mn10300_icache_inv(); | 148 | mn10300_icache_inv(); |
149 | smp_cache_call(SMP_IDCACHE_INV_FLUSH, 0, 0); | ||
135 | } | 150 | } |
151 | |||
152 | done: | ||
153 | smp_unlock_cache(flags); | ||
136 | } | 154 | } |
137 | EXPORT_SYMBOL(flush_icache_range); | 155 | EXPORT_SYMBOL(flush_icache_range); |