aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorThomas Bogendoerfer <tsbogend@alpha.franken.de>2008-08-04 14:53:57 -0400
committerRalf Baechle <ralf@linux-mips.org>2008-09-05 16:24:11 -0400
commite0cee3eea7875800451739ae38f99edcf11c133d (patch)
tree411a044d9094582cb26963a6cee72fd4c594e9fb /arch
parent0510617b85758b6e66f3c602ceccea1826440470 (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.c12
-rw-r--r--arch/mips/mm/c-r3k.c1
-rw-r--r--arch/mips/mm/c-r4k.c18
-rw-r--r--arch/mips/mm/c-tx39.c1
-rw-r--r--arch/mips/mm/cache.c1
-rw-r--r--arch/mips/mm/tlbex.c6
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)
1515void __init set_handler(unsigned long offset, void *addr, unsigned long size) 1517void __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
1521static char panic_null_cerr[] __cpuinitdata = 1523static 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
546static inline void local_r4k_flush_icache_range(void *args) 546static 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
563static 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
567static void r4k_flush_icache_range(unsigned long start, unsigned long end) 572static 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,
29void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, 29void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
30 unsigned long pfn); 30 unsigned long pfn);
31void (*flush_icache_range)(unsigned long start, unsigned long end); 31void (*flush_icache_range)(unsigned long start, unsigned long end);
32void (*local_flush_icache_range)(unsigned long start, unsigned long end);
32 33
33void (*__flush_cache_vmap)(void); 34void (*__flush_cache_vmap)(void);
34void (*__flush_cache_vunmap)(void); 35void (*__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
1274void __cpuinit flush_tlb_handlers(void) 1274void __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}