Loading arch/arc/include/asm/cache.h +2 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,8 @@ extern unsigned long perip_base, perip_end; #define ARC_REG_SLC_CTRL 0x903 #define ARC_REG_SLC_FLUSH 0x904 #define ARC_REG_SLC_INVALIDATE 0x905 #define ARC_AUX_SLC_IVDL 0x910 #define ARC_AUX_SLC_FLDL 0x912 #define ARC_REG_SLC_RGN_START 0x914 #define ARC_REG_SLC_RGN_START1 0x915 #define ARC_REG_SLC_RGN_END 0x916 Loading arch/arc/mm/cache.c +53 −1 Original line number Diff line number Diff line Loading @@ -652,7 +652,7 @@ static void __ic_line_inv_vaddr(phys_addr_t paddr, unsigned long vaddr, #endif /* CONFIG_ARC_HAS_ICACHE */ noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op) noinline void slc_op_rgn(phys_addr_t paddr, unsigned long sz, const int op) { #ifdef CONFIG_ISA_ARCV2 /* Loading Loading @@ -715,6 +715,58 @@ noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op) #endif } noinline void slc_op_line(phys_addr_t paddr, unsigned long sz, const int op) { #ifdef CONFIG_ISA_ARCV2 /* * SLC is shared between all cores and concurrent aux operations from * multiple cores need to be serialized using a spinlock * A concurrent operation can be silently ignored and/or the old/new * operation can remain incomplete forever (lockup in SLC_CTRL_BUSY loop * below) */ static DEFINE_SPINLOCK(lock); const unsigned long SLC_LINE_MASK = ~(l2_line_sz - 1); unsigned int ctrl, cmd; unsigned long flags; int num_lines; spin_lock_irqsave(&lock, flags); ctrl = read_aux_reg(ARC_REG_SLC_CTRL); /* Don't rely on default value of IM bit */ if (!(op & OP_FLUSH)) /* i.e. OP_INV */ ctrl &= ~SLC_CTRL_IM; /* clear IM: Disable flush before Inv */ else ctrl |= SLC_CTRL_IM; write_aux_reg(ARC_REG_SLC_CTRL, ctrl); cmd = op & OP_INV ? ARC_AUX_SLC_IVDL : ARC_AUX_SLC_FLDL; sz += paddr & ~SLC_LINE_MASK; paddr &= SLC_LINE_MASK; num_lines = DIV_ROUND_UP(sz, l2_line_sz); while (num_lines-- > 0) { write_aux_reg(cmd, paddr); paddr += l2_line_sz; } /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */ read_aux_reg(ARC_REG_SLC_CTRL); while (read_aux_reg(ARC_REG_SLC_CTRL) & SLC_CTRL_BUSY); spin_unlock_irqrestore(&lock, flags); #endif } #define slc_op(paddr, sz, op) slc_op_rgn(paddr, sz, op) noinline static void slc_entire_op(const int op) { unsigned int ctrl, r = ARC_REG_SLC_CTRL; Loading Loading
arch/arc/include/asm/cache.h +2 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,8 @@ extern unsigned long perip_base, perip_end; #define ARC_REG_SLC_CTRL 0x903 #define ARC_REG_SLC_FLUSH 0x904 #define ARC_REG_SLC_INVALIDATE 0x905 #define ARC_AUX_SLC_IVDL 0x910 #define ARC_AUX_SLC_FLDL 0x912 #define ARC_REG_SLC_RGN_START 0x914 #define ARC_REG_SLC_RGN_START1 0x915 #define ARC_REG_SLC_RGN_END 0x916 Loading
arch/arc/mm/cache.c +53 −1 Original line number Diff line number Diff line Loading @@ -652,7 +652,7 @@ static void __ic_line_inv_vaddr(phys_addr_t paddr, unsigned long vaddr, #endif /* CONFIG_ARC_HAS_ICACHE */ noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op) noinline void slc_op_rgn(phys_addr_t paddr, unsigned long sz, const int op) { #ifdef CONFIG_ISA_ARCV2 /* Loading Loading @@ -715,6 +715,58 @@ noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op) #endif } noinline void slc_op_line(phys_addr_t paddr, unsigned long sz, const int op) { #ifdef CONFIG_ISA_ARCV2 /* * SLC is shared between all cores and concurrent aux operations from * multiple cores need to be serialized using a spinlock * A concurrent operation can be silently ignored and/or the old/new * operation can remain incomplete forever (lockup in SLC_CTRL_BUSY loop * below) */ static DEFINE_SPINLOCK(lock); const unsigned long SLC_LINE_MASK = ~(l2_line_sz - 1); unsigned int ctrl, cmd; unsigned long flags; int num_lines; spin_lock_irqsave(&lock, flags); ctrl = read_aux_reg(ARC_REG_SLC_CTRL); /* Don't rely on default value of IM bit */ if (!(op & OP_FLUSH)) /* i.e. OP_INV */ ctrl &= ~SLC_CTRL_IM; /* clear IM: Disable flush before Inv */ else ctrl |= SLC_CTRL_IM; write_aux_reg(ARC_REG_SLC_CTRL, ctrl); cmd = op & OP_INV ? ARC_AUX_SLC_IVDL : ARC_AUX_SLC_FLDL; sz += paddr & ~SLC_LINE_MASK; paddr &= SLC_LINE_MASK; num_lines = DIV_ROUND_UP(sz, l2_line_sz); while (num_lines-- > 0) { write_aux_reg(cmd, paddr); paddr += l2_line_sz; } /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */ read_aux_reg(ARC_REG_SLC_CTRL); while (read_aux_reg(ARC_REG_SLC_CTRL) & SLC_CTRL_BUSY); spin_unlock_irqrestore(&lock, flags); #endif } #define slc_op(paddr, sz, op) slc_op_rgn(paddr, sz, op) noinline static void slc_entire_op(const int op) { unsigned int ctrl, r = ARC_REG_SLC_CTRL; Loading