diff options
Diffstat (limited to 'arch/arc/mm/cache.c')
-rw-r--r-- | arch/arc/mm/cache.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c index b29d62ed4f7e..1cd6695b6ab5 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c | |||
@@ -468,10 +468,18 @@ static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr, | |||
468 | noinline void slc_op(unsigned long paddr, unsigned long sz, const int op) | 468 | noinline void slc_op(unsigned long paddr, unsigned long sz, const int op) |
469 | { | 469 | { |
470 | #ifdef CONFIG_ISA_ARCV2 | 470 | #ifdef CONFIG_ISA_ARCV2 |
471 | /* | ||
472 | * SLC is shared between all cores and concurrent aux operations from | ||
473 | * multiple cores need to be serialized using a spinlock | ||
474 | * A concurrent operation can be silently ignored and/or the old/new | ||
475 | * operation can remain incomplete forever (lockup in SLC_CTRL_BUSY loop | ||
476 | * below) | ||
477 | */ | ||
478 | static DEFINE_SPINLOCK(lock); | ||
471 | unsigned long flags; | 479 | unsigned long flags; |
472 | unsigned int ctrl; | 480 | unsigned int ctrl; |
473 | 481 | ||
474 | local_irq_save(flags); | 482 | spin_lock_irqsave(&lock, flags); |
475 | 483 | ||
476 | /* | 484 | /* |
477 | * The Region Flush operation is specified by CTRL.RGN_OP[11..9] | 485 | * The Region Flush operation is specified by CTRL.RGN_OP[11..9] |
@@ -504,7 +512,7 @@ noinline void slc_op(unsigned long paddr, unsigned long sz, const int op) | |||
504 | 512 | ||
505 | while (read_aux_reg(ARC_REG_SLC_CTRL) & SLC_CTRL_BUSY); | 513 | while (read_aux_reg(ARC_REG_SLC_CTRL) & SLC_CTRL_BUSY); |
506 | 514 | ||
507 | local_irq_restore(flags); | 515 | spin_unlock_irqrestore(&lock, flags); |
508 | #endif | 516 | #endif |
509 | } | 517 | } |
510 | 518 | ||