Browse Source

ARM: 7091/1: errata: D-cache line maintenance operation by MVA may not succeed

This patch implements a workaround for erratum 764369 affecting
Cortex-A9 MPCore with two or more processors (all current revisions).
Under certain timing circumstances, a data cache line maintenance
operation by MVA targeting an Inner Shareable memory region may fail to
proceed up to either the Point of Coherency or to the Point of
Unification of the system. This workaround adds a DSB instruction before
the relevant cache maintenance functions and sets a specific bit in the
diagnostic control register of the SCU.

Cc: <stable@kernel.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Will Deacon 13 năm trước cách đây
mục cha
commit
f630c1bdfb
3 tập tin đã thay đổi với 44 bổ sung0 xóa
  1. 14 0
      arch/arm/Kconfig
  2. 10 0
      arch/arm/kernel/smp_scu.c
  3. 20 0
      arch/arm/mm/cache-v7.S

+ 14 - 0
arch/arm/Kconfig

@@ -1283,6 +1283,20 @@ config ARM_ERRATA_364296
 	  processor into full low interrupt latency mode. ARM11MPCore
 	  processor into full low interrupt latency mode. ARM11MPCore
 	  is not affected.
 	  is not affected.
 
 
+config ARM_ERRATA_764369
+	bool "ARM errata: Data cache line maintenance operation by MVA may not succeed"
+	depends on CPU_V7 && SMP
+	help
+	  This option enables the workaround for erratum 764369
+	  affecting Cortex-A9 MPCore with two or more processors (all
+	  current revisions). Under certain timing circumstances, a data
+	  cache line maintenance operation by MVA targeting an Inner
+	  Shareable memory region may fail to proceed up to either the
+	  Point of Coherency or to the Point of Unification of the
+	  system. This workaround adds a DSB instruction before the
+	  relevant cache maintenance functions and sets a specific bit
+	  in the diagnostic control register of the SCU.
+
 endmenu
 endmenu
 
 
 source "arch/arm/common/Kconfig"
 source "arch/arm/common/Kconfig"

+ 10 - 0
arch/arm/kernel/smp_scu.c

@@ -13,6 +13,7 @@
 
 
 #include <asm/smp_scu.h>
 #include <asm/smp_scu.h>
 #include <asm/cacheflush.h>
 #include <asm/cacheflush.h>
+#include <asm/cputype.h>
 
 
 #define SCU_CTRL		0x00
 #define SCU_CTRL		0x00
 #define SCU_CONFIG		0x04
 #define SCU_CONFIG		0x04
@@ -37,6 +38,15 @@ void __init scu_enable(void __iomem *scu_base)
 {
 {
 	u32 scu_ctrl;
 	u32 scu_ctrl;
 
 
+#ifdef CONFIG_ARM_ERRATA_764369
+	/* Cortex-A9 only */
+	if ((read_cpuid(CPUID_ID) & 0xff0ffff0) == 0x410fc090) {
+		scu_ctrl = __raw_readl(scu_base + 0x30);
+		if (!(scu_ctrl & 1))
+			__raw_writel(scu_ctrl | 0x1, scu_base + 0x30);
+	}
+#endif
+
 	scu_ctrl = __raw_readl(scu_base + SCU_CTRL);
 	scu_ctrl = __raw_readl(scu_base + SCU_CTRL);
 	/* already enabled? */
 	/* already enabled? */
 	if (scu_ctrl & 1)
 	if (scu_ctrl & 1)

+ 20 - 0
arch/arm/mm/cache-v7.S

@@ -174,6 +174,10 @@ ENTRY(v7_coherent_user_range)
 	dcache_line_size r2, r3
 	dcache_line_size r2, r3
 	sub	r3, r2, #1
 	sub	r3, r2, #1
 	bic	r12, r0, r3
 	bic	r12, r0, r3
+#ifdef CONFIG_ARM_ERRATA_764369
+	ALT_SMP(W(dsb))
+	ALT_UP(W(nop))
+#endif
 1:
 1:
  USER(	mcr	p15, 0, r12, c7, c11, 1	)	@ clean D line to the point of unification
  USER(	mcr	p15, 0, r12, c7, c11, 1	)	@ clean D line to the point of unification
 	add	r12, r12, r2
 	add	r12, r12, r2
@@ -223,6 +227,10 @@ ENTRY(v7_flush_kern_dcache_area)
 	add	r1, r0, r1
 	add	r1, r0, r1
 	sub	r3, r2, #1
 	sub	r3, r2, #1
 	bic	r0, r0, r3
 	bic	r0, r0, r3
+#ifdef CONFIG_ARM_ERRATA_764369
+	ALT_SMP(W(dsb))
+	ALT_UP(W(nop))
+#endif
 1:
 1:
 	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D line / unified line
 	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D line / unified line
 	add	r0, r0, r2
 	add	r0, r0, r2
@@ -247,6 +255,10 @@ v7_dma_inv_range:
 	sub	r3, r2, #1
 	sub	r3, r2, #1
 	tst	r0, r3
 	tst	r0, r3
 	bic	r0, r0, r3
 	bic	r0, r0, r3
+#ifdef CONFIG_ARM_ERRATA_764369
+	ALT_SMP(W(dsb))
+	ALT_UP(W(nop))
+#endif
 	mcrne	p15, 0, r0, c7, c14, 1		@ clean & invalidate D / U line
 	mcrne	p15, 0, r0, c7, c14, 1		@ clean & invalidate D / U line
 
 
 	tst	r1, r3
 	tst	r1, r3
@@ -270,6 +282,10 @@ v7_dma_clean_range:
 	dcache_line_size r2, r3
 	dcache_line_size r2, r3
 	sub	r3, r2, #1
 	sub	r3, r2, #1
 	bic	r0, r0, r3
 	bic	r0, r0, r3
+#ifdef CONFIG_ARM_ERRATA_764369
+	ALT_SMP(W(dsb))
+	ALT_UP(W(nop))
+#endif
 1:
 1:
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D / U line
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D / U line
 	add	r0, r0, r2
 	add	r0, r0, r2
@@ -288,6 +304,10 @@ ENTRY(v7_dma_flush_range)
 	dcache_line_size r2, r3
 	dcache_line_size r2, r3
 	sub	r3, r2, #1
 	sub	r3, r2, #1
 	bic	r0, r0, r3
 	bic	r0, r0, r3
+#ifdef CONFIG_ARM_ERRATA_764369
+	ALT_SMP(W(dsb))
+	ALT_UP(W(nop))
+#endif
 1:
 1:
 	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D / U line
 	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D / U line
 	add	r0, r0, r2
 	add	r0, r0, r2