ARM: 6784/1: errata: no automatic Store Buffer drain on Cortex-A9
authorWill Deacon <will.deacon@arm.com>
Fri, 4 Mar 2011 11:38:54 +0000 (12:38 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 9 Mar 2011 21:40:18 +0000 (21:40 +0000)
On revisions of the Cortex-A9 prior to r2p0, the Store Buffer does not
have any automatic draining mechanism and therefore a livelock may occur
if an external agent continuously polls a memory location waiting to
observe an update.

This workaround defines cpu_relax() as smp_mb(), preventing correctly
written polling loops from denying visibility of updates to memory.

Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/Kconfig
arch/arm/include/asm/processor.h

index ec0f658..d3f2de3 100644 (file)
@@ -1213,6 +1213,17 @@ config ARM_ERRATA_754322
          the new ASID. This workaround places two dsb instructions in the mm
          switching code so that no page table walks can cross the ASID switch.
 
+config ARM_ERRATA_754327
+       bool "ARM errata: no automatic Store Buffer drain"
+       depends on CPU_V7 && SMP
+       help
+         This option enables the workaround for the 754327 Cortex-A9 (prior to
+         r2p0) erratum. The Store Buffer does not have any automatic draining
+         mechanism and therefore a livelock may occur if an external agent
+         continuously polls a memory location waiting to observe an update.
+         This workaround defines cpu_relax() as smp_mb(), preventing correctly
+         written polling loops from denying visibility of updates to memory.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
index 67357ba..7a1f03c 100644 (file)
@@ -95,7 +95,7 @@ extern void release_thread(struct task_struct *);
 
 unsigned long get_wchan(struct task_struct *p);
 
-#if __LINUX_ARM_ARCH__ == 6
+#if __LINUX_ARM_ARCH__ == 6 || defined(CONFIG_ARM_ERRATA_754327)
 #define cpu_relax()                    smp_mb()
 #else
 #define cpu_relax()                    barrier()