diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-02-17 05:51:42 -0500 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2014-06-26 02:29:01 -0400 |
commit | 2328af0c9ce89d3ec121ba832c4e6faeff9e70ac (patch) | |
tree | a76007060d64b0f37627e1094bbae30c32657e1c /arch/arc/mm | |
parent | 7e5122190b47c2574eda26aa0bbda693b2821449 (diff) |
ARC: [SMP] Enable icache coherency
icaches are not snooped hence not cohrent in SMP setups which means
kernel has to do cross core calls to ensure the same.
The leaf routine __ic_line_inv_vaddr() now does cross core calls.
__sync_icache_dcache() is affected due to this:
* local dcache line flushed ahead of remote icache inv requests
* can't disable interrupts anymore, since
__ic_line_inv_vaddr()->on_each_cpu() can deadlock.
| WARNING: CPU: 0 PID: 1 at kernel/smp.c:374
| smp_call_function_many+0x25a/0x2c4()
|
| init_kprobes+0x90/0xc8
| register_kprobe+0x1d6/0x510
| __sync_icache_dcache+0x28/0x80
|
| DISABLE IRQ
|
| __ic_line_inv_vaddr
| on_each_cpu
| smp_call_function_many+0x25a/0x2c4 --> WARN
| __ic_line_inv_vaddr_local
| __dc_line_op
* TODO: Needs to use mask of relevant CPUs to avoid broadcasting
Signed-off-by: Noam Camus <noamc@ezchip.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc/mm')
-rw-r--r-- | arch/arc/mm/cache_arc700.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index 1f676c4794e0..353b202c37c9 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c | |||
@@ -389,7 +389,7 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr, | |||
389 | /*********************************************************** | 389 | /*********************************************************** |
390 | * Machine specific helper for per line I-Cache invalidate. | 390 | * Machine specific helper for per line I-Cache invalidate. |
391 | */ | 391 | */ |
392 | static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr, | 392 | static void __ic_line_inv_vaddr_local(unsigned long paddr, unsigned long vaddr, |
393 | unsigned long sz) | 393 | unsigned long sz) |
394 | { | 394 | { |
395 | unsigned long flags; | 395 | unsigned long flags; |
@@ -405,6 +405,23 @@ static inline void __ic_entire_inv(void) | |||
405 | read_aux_reg(ARC_REG_IC_CTRL); /* blocks */ | 405 | read_aux_reg(ARC_REG_IC_CTRL); /* blocks */ |
406 | } | 406 | } |
407 | 407 | ||
408 | struct ic_line_inv_vaddr_ipi { | ||
409 | unsigned long paddr, vaddr; | ||
410 | int sz; | ||
411 | }; | ||
412 | |||
413 | static void __ic_line_inv_vaddr_helper(void *info) | ||
414 | { | ||
415 | struct ic_line_inv_vaddr_ipi *ic_inv = (struct ic_line_inv_vaddr_ipi*) info; | ||
416 | __ic_line_inv_vaddr_local(ic_inv->paddr, ic_inv->vaddr, ic_inv->sz); | ||
417 | } | ||
418 | |||
419 | static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr, | ||
420 | unsigned long sz) | ||
421 | { | ||
422 | struct ic_line_inv_vaddr_ipi ic_inv = { paddr, vaddr , sz}; | ||
423 | on_each_cpu(__ic_line_inv_vaddr_helper, &ic_inv, 1); | ||
424 | } | ||
408 | #else | 425 | #else |
409 | 426 | ||
410 | #define __ic_entire_inv() | 427 | #define __ic_entire_inv() |
@@ -553,12 +570,8 @@ void flush_icache_range(unsigned long kstart, unsigned long kend) | |||
553 | */ | 570 | */ |
554 | void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len) | 571 | void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len) |
555 | { | 572 | { |
556 | unsigned long flags; | ||
557 | |||
558 | local_irq_save(flags); | ||
559 | __ic_line_inv_vaddr(paddr, vaddr, len); | ||
560 | __dc_line_op(paddr, vaddr, len, OP_FLUSH_N_INV); | 573 | __dc_line_op(paddr, vaddr, len, OP_FLUSH_N_INV); |
561 | local_irq_restore(flags); | 574 | __ic_line_inv_vaddr(paddr, vaddr, len); |
562 | } | 575 | } |
563 | 576 | ||
564 | /* wrapper to compile time eliminate alignment checks in flush loop */ | 577 | /* wrapper to compile time eliminate alignment checks in flush loop */ |