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-08-20 17:31:38 +0100
commit3d93ce8561e78e4fcfbf308d21e302743176d6b5 (patch)
treecaea0254c53d97cbc9f1f7972855a1035ee4f32a
parent17c08359d6f0168ce2e56bef4ea7f31c84e4aed9 (diff)
ARM: vexpress: fix CPU idle C1 state enablementtracking-tracking-armlt-tc2-pm-ll-20120820.1
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> Signed-off-by: Jon Medhurst <tixy@linaro.org>
-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..6205044d531a 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",
+ .disabled = 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());