diff options
Diffstat (limited to 'arch/mips/mm/c-sb1.c')
-rw-r--r-- | arch/mips/mm/c-sb1.c | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c index 5537558f19f7..3a8afd47feaa 100644 --- a/arch/mips/mm/c-sb1.c +++ b/arch/mips/mm/c-sb1.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
20 | */ | 20 | */ |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/hardirq.h> | ||
22 | 23 | ||
23 | #include <asm/asm.h> | 24 | #include <asm/asm.h> |
24 | #include <asm/bootinfo.h> | 25 | #include <asm/bootinfo.h> |
@@ -49,6 +50,15 @@ static unsigned short dcache_sets; | |||
49 | static unsigned int icache_range_cutoff; | 50 | static unsigned int icache_range_cutoff; |
50 | static unsigned int dcache_range_cutoff; | 51 | static unsigned int dcache_range_cutoff; |
51 | 52 | ||
53 | static inline void sb1_on_each_cpu(void (*func) (void *info), void *info, | ||
54 | int retry, int wait) | ||
55 | { | ||
56 | preempt_disable(); | ||
57 | smp_call_function(func, info, retry, wait); | ||
58 | func(info); | ||
59 | preempt_enable(); | ||
60 | } | ||
61 | |||
52 | /* | 62 | /* |
53 | * The dcache is fully coherent to the system, with one | 63 | * The dcache is fully coherent to the system, with one |
54 | * big caveat: the instruction stream. In other words, | 64 | * big caveat: the instruction stream. In other words, |
@@ -226,13 +236,32 @@ static void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, | |||
226 | args.vma = vma; | 236 | args.vma = vma; |
227 | args.addr = addr; | 237 | args.addr = addr; |
228 | args.pfn = pfn; | 238 | args.pfn = pfn; |
229 | on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1); | 239 | sb1_on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1); |
230 | } | 240 | } |
231 | #else | 241 | #else |
232 | void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) | 242 | void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) |
233 | __attribute__((alias("local_sb1_flush_cache_page"))); | 243 | __attribute__((alias("local_sb1_flush_cache_page"))); |
234 | #endif | 244 | #endif |
235 | 245 | ||
246 | #ifdef CONFIG_SMP | ||
247 | static void sb1_flush_cache_data_page_ipi(void *info) | ||
248 | { | ||
249 | unsigned long start = (unsigned long)info; | ||
250 | |||
251 | __sb1_writeback_inv_dcache_range(start, start + PAGE_SIZE); | ||
252 | } | ||
253 | |||
254 | static void sb1_flush_cache_data_page(unsigned long addr) | ||
255 | { | ||
256 | if (in_atomic()) | ||
257 | __sb1_writeback_inv_dcache_range(addr, addr + PAGE_SIZE); | ||
258 | else | ||
259 | on_each_cpu(sb1_flush_cache_data_page_ipi, (void *) addr, 1, 1); | ||
260 | } | ||
261 | #else | ||
262 | void sb1_flush_cache_data_page(unsigned long) | ||
263 | __attribute__((alias("local_sb1_flush_cache_data_page"))); | ||
264 | #endif | ||
236 | 265 | ||
237 | /* | 266 | /* |
238 | * Invalidate all caches on this CPU | 267 | * Invalidate all caches on this CPU |
@@ -249,7 +278,7 @@ void sb1___flush_cache_all_ipi(void *ignored) | |||
249 | 278 | ||
250 | static void sb1___flush_cache_all(void) | 279 | static void sb1___flush_cache_all(void) |
251 | { | 280 | { |
252 | on_each_cpu(sb1___flush_cache_all_ipi, 0, 1, 1); | 281 | sb1_on_each_cpu(sb1___flush_cache_all_ipi, 0, 1, 1); |
253 | } | 282 | } |
254 | #else | 283 | #else |
255 | void sb1___flush_cache_all(void) | 284 | void sb1___flush_cache_all(void) |
@@ -299,7 +328,7 @@ void sb1_flush_icache_range(unsigned long start, unsigned long end) | |||
299 | 328 | ||
300 | args.start = start; | 329 | args.start = start; |
301 | args.end = end; | 330 | args.end = end; |
302 | on_each_cpu(sb1_flush_icache_range_ipi, &args, 1, 1); | 331 | sb1_on_each_cpu(sb1_flush_icache_range_ipi, &args, 1, 1); |
303 | } | 332 | } |
304 | #else | 333 | #else |
305 | void sb1_flush_icache_range(unsigned long start, unsigned long end) | 334 | void sb1_flush_icache_range(unsigned long start, unsigned long end) |
@@ -326,7 +355,7 @@ static void sb1_flush_cache_sigtramp_ipi(void *info) | |||
326 | 355 | ||
327 | static void sb1_flush_cache_sigtramp(unsigned long addr) | 356 | static void sb1_flush_cache_sigtramp(unsigned long addr) |
328 | { | 357 | { |
329 | on_each_cpu(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1); | 358 | sb1_on_each_cpu(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1); |
330 | } | 359 | } |
331 | #else | 360 | #else |
332 | void sb1_flush_cache_sigtramp(unsigned long addr) | 361 | void sb1_flush_cache_sigtramp(unsigned long addr) |
@@ -444,7 +473,6 @@ static __init void probe_cache_sizes(void) | |||
444 | void sb1_cache_init(void) | 473 | void sb1_cache_init(void) |
445 | { | 474 | { |
446 | extern char except_vec2_sb1; | 475 | extern char except_vec2_sb1; |
447 | extern char handle_vec2_sb1; | ||
448 | 476 | ||
449 | /* Special cache error handler for SB1 */ | 477 | /* Special cache error handler for SB1 */ |
450 | set_uncached_handler (0x100, &except_vec2_sb1, 0x80); | 478 | set_uncached_handler (0x100, &except_vec2_sb1, 0x80); |
@@ -473,7 +501,7 @@ void sb1_cache_init(void) | |||
473 | 501 | ||
474 | flush_cache_sigtramp = sb1_flush_cache_sigtramp; | 502 | flush_cache_sigtramp = sb1_flush_cache_sigtramp; |
475 | local_flush_data_cache_page = (void *) sb1_nop; | 503 | local_flush_data_cache_page = (void *) sb1_nop; |
476 | flush_data_cache_page = (void *) sb1_nop; | 504 | flush_data_cache_page = sb1_flush_cache_data_page; |
477 | 505 | ||
478 | /* Full flush */ | 506 | /* Full flush */ |
479 | __flush_cache_all = sb1___flush_cache_all; | 507 | __flush_cache_all = sb1___flush_cache_all; |
@@ -497,5 +525,5 @@ void sb1_cache_init(void) | |||
497 | : | 525 | : |
498 | : "memory"); | 526 | : "memory"); |
499 | 527 | ||
500 | flush_cache_all(); | 528 | local_sb1___flush_cache_all(); |
501 | } | 529 | } |