diff options
author | Thomas Bogendoerfer <tsbogend@alpha.franken.de> | 2008-08-04 14:53:57 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2008-09-05 16:24:11 -0400 |
commit | e0cee3eea7875800451739ae38f99edcf11c133d (patch) | |
tree | 411a044d9094582cb26963a6cee72fd4c594e9fb /arch | |
parent | 0510617b85758b6e66f3c602ceccea1826440470 (diff) |
[MIPS] Fix WARNING: at kernel/smp.c:290
trap_init issues flush_icache_range(), which uses ipi functions to
get icache flushing done on all cpus. But this is done before interrupts
are enabled and caused WARN_ON messages. This changeset introduces
a new local_flush_icache_range() and uses it before interrupts (and
additional CPUs) are enabled to avoid this problem.
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/kernel/traps.c | 12 | ||||
-rw-r--r-- | arch/mips/mm/c-r3k.c | 1 | ||||
-rw-r--r-- | arch/mips/mm/c-r4k.c | 18 | ||||
-rw-r--r-- | arch/mips/mm/c-tx39.c | 1 | ||||
-rw-r--r-- | arch/mips/mm/cache.c | 1 | ||||
-rw-r--r-- | arch/mips/mm/tlbex.c | 6 |
6 files changed, 25 insertions, 14 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 1f579a8ea25b..6bee29097a56 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -1200,7 +1200,7 @@ void *set_except_vector(int n, void *addr) | |||
1200 | if (n == 0 && cpu_has_divec) { | 1200 | if (n == 0 && cpu_has_divec) { |
1201 | *(u32 *)(ebase + 0x200) = 0x08000000 | | 1201 | *(u32 *)(ebase + 0x200) = 0x08000000 | |
1202 | (0x03ffffff & (handler >> 2)); | 1202 | (0x03ffffff & (handler >> 2)); |
1203 | flush_icache_range(ebase + 0x200, ebase + 0x204); | 1203 | local_flush_icache_range(ebase + 0x200, ebase + 0x204); |
1204 | } | 1204 | } |
1205 | return (void *)old_handler; | 1205 | return (void *)old_handler; |
1206 | } | 1206 | } |
@@ -1283,7 +1283,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) | |||
1283 | *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff); | 1283 | *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff); |
1284 | w = (u32 *)(b + ori_offset); | 1284 | w = (u32 *)(b + ori_offset); |
1285 | *w = (*w & 0xffff0000) | ((u32)handler & 0xffff); | 1285 | *w = (*w & 0xffff0000) | ((u32)handler & 0xffff); |
1286 | flush_icache_range((unsigned long)b, (unsigned long)(b+handler_len)); | 1286 | local_flush_icache_range((unsigned long)b, |
1287 | (unsigned long)(b+handler_len)); | ||
1287 | } | 1288 | } |
1288 | else { | 1289 | else { |
1289 | /* | 1290 | /* |
@@ -1295,7 +1296,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) | |||
1295 | w = (u32 *)b; | 1296 | w = (u32 *)b; |
1296 | *w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */ | 1297 | *w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */ |
1297 | *w = 0; | 1298 | *w = 0; |
1298 | flush_icache_range((unsigned long)b, (unsigned long)(b+8)); | 1299 | local_flush_icache_range((unsigned long)b, |
1300 | (unsigned long)(b+8)); | ||
1299 | } | 1301 | } |
1300 | 1302 | ||
1301 | return (void *)old_handler; | 1303 | return (void *)old_handler; |
@@ -1515,7 +1517,7 @@ void __cpuinit per_cpu_trap_init(void) | |||
1515 | void __init set_handler(unsigned long offset, void *addr, unsigned long size) | 1517 | void __init set_handler(unsigned long offset, void *addr, unsigned long size) |
1516 | { | 1518 | { |
1517 | memcpy((void *)(ebase + offset), addr, size); | 1519 | memcpy((void *)(ebase + offset), addr, size); |
1518 | flush_icache_range(ebase + offset, ebase + offset + size); | 1520 | local_flush_icache_range(ebase + offset, ebase + offset + size); |
1519 | } | 1521 | } |
1520 | 1522 | ||
1521 | static char panic_null_cerr[] __cpuinitdata = | 1523 | static char panic_null_cerr[] __cpuinitdata = |
@@ -1680,7 +1682,7 @@ void __init trap_init(void) | |||
1680 | signal32_init(); | 1682 | signal32_init(); |
1681 | #endif | 1683 | #endif |
1682 | 1684 | ||
1683 | flush_icache_range(ebase, ebase + 0x400); | 1685 | local_flush_icache_range(ebase, ebase + 0x400); |
1684 | flush_tlb_handlers(); | 1686 | flush_tlb_handlers(); |
1685 | 1687 | ||
1686 | sort_extable(__start___dbe_table, __stop___dbe_table); | 1688 | sort_extable(__start___dbe_table, __stop___dbe_table); |
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index 27a5b466c85c..5500c20c79ae 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c | |||
@@ -320,6 +320,7 @@ void __cpuinit r3k_cache_init(void) | |||
320 | flush_cache_range = r3k_flush_cache_range; | 320 | flush_cache_range = r3k_flush_cache_range; |
321 | flush_cache_page = r3k_flush_cache_page; | 321 | flush_cache_page = r3k_flush_cache_page; |
322 | flush_icache_range = r3k_flush_icache_range; | 322 | flush_icache_range = r3k_flush_icache_range; |
323 | local_flush_icache_range = r3k_flush_icache_range; | ||
323 | 324 | ||
324 | flush_cache_sigtramp = r3k_flush_cache_sigtramp; | 325 | flush_cache_sigtramp = r3k_flush_cache_sigtramp; |
325 | local_flush_data_cache_page = local_r3k_flush_data_cache_page; | 326 | local_flush_data_cache_page = local_r3k_flush_data_cache_page; |
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 71df3390c07b..6e99665ae860 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c | |||
@@ -543,12 +543,8 @@ struct flush_icache_range_args { | |||
543 | unsigned long end; | 543 | unsigned long end; |
544 | }; | 544 | }; |
545 | 545 | ||
546 | static inline void local_r4k_flush_icache_range(void *args) | 546 | static inline void local_r4k_flush_icache_range(unsigned long start, unsigned long end) |
547 | { | 547 | { |
548 | struct flush_icache_range_args *fir_args = args; | ||
549 | unsigned long start = fir_args->start; | ||
550 | unsigned long end = fir_args->end; | ||
551 | |||
552 | if (!cpu_has_ic_fills_f_dc) { | 548 | if (!cpu_has_ic_fills_f_dc) { |
553 | if (end - start >= dcache_size) { | 549 | if (end - start >= dcache_size) { |
554 | r4k_blast_dcache(); | 550 | r4k_blast_dcache(); |
@@ -564,6 +560,15 @@ static inline void local_r4k_flush_icache_range(void *args) | |||
564 | protected_blast_icache_range(start, end); | 560 | protected_blast_icache_range(start, end); |
565 | } | 561 | } |
566 | 562 | ||
563 | static inline void local_r4k_flush_icache_range_ipi(void *args) | ||
564 | { | ||
565 | struct flush_icache_range_args *fir_args = args; | ||
566 | unsigned long start = fir_args->start; | ||
567 | unsigned long end = fir_args->end; | ||
568 | |||
569 | local_r4k_flush_icache_range(start, end); | ||
570 | } | ||
571 | |||
567 | static void r4k_flush_icache_range(unsigned long start, unsigned long end) | 572 | static void r4k_flush_icache_range(unsigned long start, unsigned long end) |
568 | { | 573 | { |
569 | struct flush_icache_range_args args; | 574 | struct flush_icache_range_args args; |
@@ -571,7 +576,7 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end) | |||
571 | args.start = start; | 576 | args.start = start; |
572 | args.end = end; | 577 | args.end = end; |
573 | 578 | ||
574 | r4k_on_each_cpu(local_r4k_flush_icache_range, &args, 1); | 579 | r4k_on_each_cpu(local_r4k_flush_icache_range_ipi, &args, 1); |
575 | instruction_hazard(); | 580 | instruction_hazard(); |
576 | } | 581 | } |
577 | 582 | ||
@@ -1375,6 +1380,7 @@ void __cpuinit r4k_cache_init(void) | |||
1375 | local_flush_data_cache_page = local_r4k_flush_data_cache_page; | 1380 | local_flush_data_cache_page = local_r4k_flush_data_cache_page; |
1376 | flush_data_cache_page = r4k_flush_data_cache_page; | 1381 | flush_data_cache_page = r4k_flush_data_cache_page; |
1377 | flush_icache_range = r4k_flush_icache_range; | 1382 | flush_icache_range = r4k_flush_icache_range; |
1383 | local_flush_icache_range = local_r4k_flush_icache_range; | ||
1378 | 1384 | ||
1379 | #if defined(CONFIG_DMA_NONCOHERENT) | 1385 | #if defined(CONFIG_DMA_NONCOHERENT) |
1380 | if (coherentio) { | 1386 | if (coherentio) { |
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index a9f7f1f5e9b4..39c81820ce82 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c | |||
@@ -362,6 +362,7 @@ void __cpuinit tx39_cache_init(void) | |||
362 | flush_cache_range = (void *) tx39h_flush_icache_all; | 362 | flush_cache_range = (void *) tx39h_flush_icache_all; |
363 | flush_cache_page = (void *) tx39h_flush_icache_all; | 363 | flush_cache_page = (void *) tx39h_flush_icache_all; |
364 | flush_icache_range = (void *) tx39h_flush_icache_all; | 364 | flush_icache_range = (void *) tx39h_flush_icache_all; |
365 | local_flush_icache_range = (void *) tx39h_flush_icache_all; | ||
365 | 366 | ||
366 | flush_cache_sigtramp = (void *) tx39h_flush_icache_all; | 367 | flush_cache_sigtramp = (void *) tx39h_flush_icache_all; |
367 | local_flush_data_cache_page = (void *) tx39h_flush_icache_all; | 368 | local_flush_data_cache_page = (void *) tx39h_flush_icache_all; |
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 034e8506f6ea..1eb7c71e3d6a 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c | |||
@@ -29,6 +29,7 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, | |||
29 | void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, | 29 | void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, |
30 | unsigned long pfn); | 30 | unsigned long pfn); |
31 | void (*flush_icache_range)(unsigned long start, unsigned long end); | 31 | void (*flush_icache_range)(unsigned long start, unsigned long end); |
32 | void (*local_flush_icache_range)(unsigned long start, unsigned long end); | ||
32 | 33 | ||
33 | void (*__flush_cache_vmap)(void); | 34 | void (*__flush_cache_vmap)(void); |
34 | void (*__flush_cache_vunmap)(void); | 35 | void (*__flush_cache_vunmap)(void); |
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 76da73a5ab3c..979cf9197282 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
@@ -1273,10 +1273,10 @@ void __cpuinit build_tlb_refill_handler(void) | |||
1273 | 1273 | ||
1274 | void __cpuinit flush_tlb_handlers(void) | 1274 | void __cpuinit flush_tlb_handlers(void) |
1275 | { | 1275 | { |
1276 | flush_icache_range((unsigned long)handle_tlbl, | 1276 | local_flush_icache_range((unsigned long)handle_tlbl, |
1277 | (unsigned long)handle_tlbl + sizeof(handle_tlbl)); | 1277 | (unsigned long)handle_tlbl + sizeof(handle_tlbl)); |
1278 | flush_icache_range((unsigned long)handle_tlbs, | 1278 | local_flush_icache_range((unsigned long)handle_tlbs, |
1279 | (unsigned long)handle_tlbs + sizeof(handle_tlbs)); | 1279 | (unsigned long)handle_tlbs + sizeof(handle_tlbs)); |
1280 | flush_icache_range((unsigned long)handle_tlbm, | 1280 | local_flush_icache_range((unsigned long)handle_tlbm, |
1281 | (unsigned long)handle_tlbm + sizeof(handle_tlbm)); | 1281 | (unsigned long)handle_tlbm + sizeof(handle_tlbm)); |
1282 | } | 1282 | } |