diff options
author | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2012-07-26 14:08:42 +0100 |
---|---|---|
committer | Jon Medhurst <tixy@linaro.org> | 2012-08-07 10:59:31 +0100 |
commit | da2e6d929a6b9b76581a4f5721535a2738be9083 (patch) | |
tree | c0802348c5e2aded60d9cc7fb6babb96ea627cfa | |
parent | 72c03a558df6beb6a34ed2fcd95cb317721b8e4f (diff) |
ARM: vexpress: fix CPU idle C1 state enablementtracking-tracking-armlt-tc2-pm-ll-20120820.0tracking-tracking-armlt-tc2-pm-ll-20120817.2tracking-tracking-armlt-tc2-pm-ll-20120817.1tracking-tracking-armlt-tc2-pm-ll-20120817.0tracking-tracking-armlt-tc2-pm-ll-20120815.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>
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 11030b5c0ec..6205044d531 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()); |