aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc/mm/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arc/mm/cache.c')
-rw-r--r--arch/arc/mm/cache.c12
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,
468noinline void slc_op(unsigned long paddr, unsigned long sz, const int op) 468noinline 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