diff options
author | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2012-07-26 14:08:42 +0100 |
---|---|---|
committer | Jon Medhurst <tixy@linaro.org> | 2012-08-20 17:31:38 +0100 |
commit | 3d93ce8561e78e4fcfbf308d21e302743176d6b5 (patch) | |
tree | caea0254c53d97cbc9f1f7972855a1035ee4f32a | |
parent | 17c08359d6f0168ce2e56bef4ea7f31c84e4aed9 (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.c | 6 |
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()); |