diff options
author | Paul Mundt <lethal@linux-sh.org> | 2009-08-21 04:23:14 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-08-21 04:23:14 -0400 |
commit | f26b2a562b46ab186c8383993ab1332673ac4a47 (patch) | |
tree | 5cf52089da5ca762c07cf6c1364a6aa411fb3038 /arch/sh/mm/cache-sh7705.c | |
parent | f9bd71f255b4349c4f9f596863161fd5182f67fa (diff) |
sh: Make cache flushers SMP-aware.
This does a bit of rework for making the cache flushers SMP-aware. The
function pointer-based flushers are renamed to local variants with the
exported interface being commonly implemented and wrapping as necessary.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/mm/cache-sh7705.c')
-rw-r--r-- | arch/sh/mm/cache-sh7705.c | 67 |
1 files changed, 22 insertions, 45 deletions
diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c index f1d5c803c04b..6293f57fa888 100644 --- a/arch/sh/mm/cache-sh7705.c +++ b/arch/sh/mm/cache-sh7705.c | |||
@@ -64,8 +64,14 @@ static inline void cache_wback_all(void) | |||
64 | * | 64 | * |
65 | * Called from kernel/module.c:sys_init_module and routine for a.out format. | 65 | * Called from kernel/module.c:sys_init_module and routine for a.out format. |
66 | */ | 66 | */ |
67 | static void sh7705_flush_icache_range(unsigned long start, unsigned long end) | 67 | static void sh7705_flush_icache_range(void *args) |
68 | { | 68 | { |
69 | struct flusher_data *data = args; | ||
70 | unsigned long start, end; | ||
71 | |||
72 | start = data->addr1; | ||
73 | end = data->addr2; | ||
74 | |||
69 | __flush_wback_region((void *)start, end - start); | 75 | __flush_wback_region((void *)start, end - start); |
70 | } | 76 | } |
71 | 77 | ||
@@ -127,7 +133,7 @@ static void __flush_dcache_page(unsigned long phys) | |||
127 | * Write back & invalidate the D-cache of the page. | 133 | * Write back & invalidate the D-cache of the page. |
128 | * (To avoid "alias" issues) | 134 | * (To avoid "alias" issues) |
129 | */ | 135 | */ |
130 | static void sh7705_flush_dcache_page(struct page *page) | 136 | static void sh7705_flush_dcache_page(void *page) |
131 | { | 137 | { |
132 | struct address_space *mapping = page_mapping(page); | 138 | struct address_space *mapping = page_mapping(page); |
133 | 139 | ||
@@ -137,7 +143,7 @@ static void sh7705_flush_dcache_page(struct page *page) | |||
137 | __flush_dcache_page(PHYSADDR(page_address(page))); | 143 | __flush_dcache_page(PHYSADDR(page_address(page))); |
138 | } | 144 | } |
139 | 145 | ||
140 | static void sh7705_flush_cache_all(void) | 146 | static void sh7705_flush_cache_all(void *args) |
141 | { | 147 | { |
142 | unsigned long flags; | 148 | unsigned long flags; |
143 | 149 | ||
@@ -149,44 +155,16 @@ static void sh7705_flush_cache_all(void) | |||
149 | local_irq_restore(flags); | 155 | local_irq_restore(flags); |
150 | } | 156 | } |
151 | 157 | ||
152 | static void sh7705_flush_cache_mm(struct mm_struct *mm) | ||
153 | { | ||
154 | /* Is there any good way? */ | ||
155 | /* XXX: possibly call flush_cache_range for each vm area */ | ||
156 | flush_cache_all(); | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * Write back and invalidate D-caches. | ||
161 | * | ||
162 | * START, END: Virtual Address (U0 address) | ||
163 | * | ||
164 | * NOTE: We need to flush the _physical_ page entry. | ||
165 | * Flushing the cache lines for U0 only isn't enough. | ||
166 | * We need to flush for P1 too, which may contain aliases. | ||
167 | */ | ||
168 | static void sh7705_flush_cache_range(struct vm_area_struct *vma, | ||
169 | unsigned long start, unsigned long end) | ||
170 | { | ||
171 | |||
172 | /* | ||
173 | * We could call flush_cache_page for the pages of these range, | ||
174 | * but it's not efficient (scan the caches all the time...). | ||
175 | * | ||
176 | * We can't use A-bit magic, as there's the case we don't have | ||
177 | * valid entry on TLB. | ||
178 | */ | ||
179 | flush_cache_all(); | ||
180 | } | ||
181 | |||
182 | /* | 158 | /* |
183 | * Write back and invalidate I/D-caches for the page. | 159 | * Write back and invalidate I/D-caches for the page. |
184 | * | 160 | * |
185 | * ADDRESS: Virtual Address (U0 address) | 161 | * ADDRESS: Virtual Address (U0 address) |
186 | */ | 162 | */ |
187 | static void sh7705_flush_cache_page(struct vm_area_struct *vma, | 163 | static void sh7705_flush_cache_page(void *args) |
188 | unsigned long address, unsigned long pfn) | ||
189 | { | 164 | { |
165 | struct flusher_data *data = args; | ||
166 | unsigned long pfn = data->addr2; | ||
167 | |||
190 | __flush_dcache_page(pfn << PAGE_SHIFT); | 168 | __flush_dcache_page(pfn << PAGE_SHIFT); |
191 | } | 169 | } |
192 | 170 | ||
@@ -198,20 +176,19 @@ static void sh7705_flush_cache_page(struct vm_area_struct *vma, | |||
198 | * Not entirely sure why this is necessary on SH3 with 32K cache but | 176 | * Not entirely sure why this is necessary on SH3 with 32K cache but |
199 | * without it we get occasional "Memory fault" when loading a program. | 177 | * without it we get occasional "Memory fault" when loading a program. |
200 | */ | 178 | */ |
201 | static void sh7705_flush_icache_page(struct vm_area_struct *vma, | 179 | static void sh7705_flush_icache_page(void *page) |
202 | struct page *page) | ||
203 | { | 180 | { |
204 | __flush_purge_region(page_address(page), PAGE_SIZE); | 181 | __flush_purge_region(page_address(page), PAGE_SIZE); |
205 | } | 182 | } |
206 | 183 | ||
207 | void __init sh7705_cache_init(void) | 184 | void __init sh7705_cache_init(void) |
208 | { | 185 | { |
209 | flush_icache_range = sh7705_flush_icache_range; | 186 | local_flush_icache_range = sh7705_flush_icache_range; |
210 | flush_dcache_page = sh7705_flush_dcache_page; | 187 | local_flush_dcache_page = sh7705_flush_dcache_page; |
211 | flush_cache_all = sh7705_flush_cache_all; | 188 | local_flush_cache_all = sh7705_flush_cache_all; |
212 | flush_cache_mm = sh7705_flush_cache_mm; | 189 | local_flush_cache_mm = sh7705_flush_cache_all; |
213 | flush_cache_dup_mm = sh7705_flush_cache_mm; | 190 | local_flush_cache_dup_mm = sh7705_flush_cache_all; |
214 | flush_cache_range = sh7705_flush_cache_range; | 191 | local_flush_cache_range = sh7705_flush_cache_all; |
215 | flush_cache_page = sh7705_flush_cache_page; | 192 | local_flush_cache_page = sh7705_flush_cache_page; |
216 | flush_icache_page = sh7705_flush_icache_page; | 193 | local_flush_icache_page = sh7705_flush_icache_page; |
217 | } | 194 | } |