From 7bfdd04a081cafd7d631601c3b7dfd47e0845283 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Wed, 14 Mar 2012 17:26:17 -0700 Subject: [PATCH] --- yaml --- r: 321253 b: refs/heads/master c: 5b4d5bcc68940497722d98d99abee72a0ab1d6f1 h: refs/heads/master i: 321251: b84811d96de4c72208ae3cc983e556d45a3f024e v: v3 --- [refs] | 2 +- trunk/arch/arm/mach-omap2/cpuidle44xx.c | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index 0cb7b02cabda..74e4ffdfc8a3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: dd3ad97c5621aa853843dd5e6783ca787466158c +refs/heads/master: 5b4d5bcc68940497722d98d99abee72a0ab1d6f1 diff --git a/trunk/arch/arm/mach-omap2/cpuidle44xx.c b/trunk/arch/arm/mach-omap2/cpuidle44xx.c index 25655eb69408..eb93e45d3271 100644 --- a/trunk/arch/arm/mach-omap2/cpuidle44xx.c +++ b/trunk/arch/arm/mach-omap2/cpuidle44xx.c @@ -53,6 +53,9 @@ static struct omap4_idle_statedata omap4_idle_data[] = { static struct powerdomain *mpu_pd, *cpu_pd[NR_CPUS]; static struct clockdomain *cpu_clkdm[NR_CPUS]; +static atomic_t abort_barrier; +static bool cpu_done[NR_CPUS]; + /** * omap4_enter_idle_coupled_[simple/coupled] - OMAP4 cpuidle entry functions * @dev: cpuidle device @@ -90,8 +93,20 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev, * out of coherency and in OFF mode. */ if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) { - while (pwrdm_read_pwrst(cpu_pd[1]) != PWRDM_POWER_OFF) + while (pwrdm_read_pwrst(cpu_pd[1]) != PWRDM_POWER_OFF) { cpu_relax(); + + /* + * CPU1 could have already entered & exited idle + * without hitting off because of a wakeup + * or a failed attempt to hit off mode. Check for + * that here, otherwise we could spin forever + * waiting for CPU1 off. + */ + if (cpu_done[1]) + goto fail; + + } } clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id); @@ -116,6 +131,7 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev, } omap4_enter_lowpower(dev->cpu, cx->cpu_state); + cpu_done[dev->cpu] = true; /* Wakeup CPU1 only if it is not offlined */ if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) { @@ -138,6 +154,10 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev, clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id); +fail: + cpuidle_coupled_parallel_barrier(dev, &abort_barrier); + cpu_done[dev->cpu] = false; + local_fiq_enable(); return index;