aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2012-07-26 14:08:42 +0100
committerJon Medhurst <tixy@linaro.org>2012-07-26 19:14:54 +0100
commitbf536fe80cd7bcb7e72dfc807e3760cd8552398a (patch)
tree683cd02ea5de2f62fa125c19d3268b7743710d38
parent4b4fc27ea224acef8bb49773671f0288888a10f0 (diff)
ARM: vexpress: fix CPU idle C1 state enablementtracking-tracking-armlt-tc2-pm-ll-20120727.0
This patch defines C1 as disabled by default on TC2. If the state is later enabled but deep shutdown states are required to be enabled on a cluster basis, a coupled barrier must be added to the coupled enter function so that coupled CPUs cannot exit the polling C1 state while other ones are still entering. This patch fixes a race in C1 code where one CPU exits a coupled C-state while another one, part of the coupled mask is still selecting the coupled C-state value. This can cause some CPUs to select the -1 state index which triggers an undefined instruction fault. The added coupled C-state barrier fixes the issue by forcing coupled C-states to be entered and exited at the same time by all CPUs even if cluster shutdown is disabled. Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-rw-r--r--arch/arm/mach-vexpress/cpuidle-tc2.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/arch/arm/mach-vexpress/cpuidle-tc2.c b/arch/arm/mach-vexpress/cpuidle-tc2.c
index 11030b5c0ec4..cb9c64695b3c 100644
--- a/arch/arm/mach-vexpress/cpuidle-tc2.c
+++ b/arch/arm/mach-vexpress/cpuidle-tc2.c
@@ -72,6 +72,7 @@ static struct cpuidle_state tc2_cpuidle_set[] __initdata = {
CPUIDLE_FLAG_COUPLED,
.name = "C1",
.desc = "ARM power down",
+ .disable = 1,
},
};
@@ -138,8 +139,11 @@ static int tc2_enter_coupled(struct cpuidle_device *dev,
/* Used to keep track of the total time in idle */
getnstimeofday(&ts_preidle);
- if (!cpu_isset(cluster, cluster_mask))
+ if (!cpu_isset(cluster, cluster_mask)) {
+ cpuidle_coupled_parallel_barrier(dev,
+ &abort_barrier[cluster]);
goto shallow_out;
+ }
BUG_ON(!irqs_disabled());