diff options
| -rw-r--r-- | arch/arm/mach-omap2/cpuidle44xx.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c index 25655eb69408..eb93e45d3271 100644 --- a/arch/arm/mach-omap2/cpuidle44xx.c +++ b/arch/arm/mach-omap2/cpuidle44xx.c | |||
| @@ -53,6 +53,9 @@ static struct omap4_idle_statedata omap4_idle_data[] = { | |||
| 53 | static struct powerdomain *mpu_pd, *cpu_pd[NR_CPUS]; | 53 | static struct powerdomain *mpu_pd, *cpu_pd[NR_CPUS]; |
| 54 | static struct clockdomain *cpu_clkdm[NR_CPUS]; | 54 | static struct clockdomain *cpu_clkdm[NR_CPUS]; |
| 55 | 55 | ||
| 56 | static atomic_t abort_barrier; | ||
| 57 | static bool cpu_done[NR_CPUS]; | ||
| 58 | |||
| 56 | /** | 59 | /** |
| 57 | * omap4_enter_idle_coupled_[simple/coupled] - OMAP4 cpuidle entry functions | 60 | * omap4_enter_idle_coupled_[simple/coupled] - OMAP4 cpuidle entry functions |
| 58 | * @dev: cpuidle device | 61 | * @dev: cpuidle device |
| @@ -90,8 +93,20 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev, | |||
| 90 | * out of coherency and in OFF mode. | 93 | * out of coherency and in OFF mode. |
| 91 | */ | 94 | */ |
| 92 | if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) { | 95 | if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) { |
| 93 | while (pwrdm_read_pwrst(cpu_pd[1]) != PWRDM_POWER_OFF) | 96 | while (pwrdm_read_pwrst(cpu_pd[1]) != PWRDM_POWER_OFF) { |
| 94 | cpu_relax(); | 97 | cpu_relax(); |
| 98 | |||
| 99 | /* | ||
| 100 | * CPU1 could have already entered & exited idle | ||
| 101 | * without hitting off because of a wakeup | ||
| 102 | * or a failed attempt to hit off mode. Check for | ||
| 103 | * that here, otherwise we could spin forever | ||
| 104 | * waiting for CPU1 off. | ||
| 105 | */ | ||
| 106 | if (cpu_done[1]) | ||
| 107 | goto fail; | ||
| 108 | |||
| 109 | } | ||
| 95 | } | 110 | } |
| 96 | 111 | ||
| 97 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id); | 112 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id); |
| @@ -116,6 +131,7 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev, | |||
| 116 | } | 131 | } |
| 117 | 132 | ||
| 118 | omap4_enter_lowpower(dev->cpu, cx->cpu_state); | 133 | omap4_enter_lowpower(dev->cpu, cx->cpu_state); |
| 134 | cpu_done[dev->cpu] = true; | ||
| 119 | 135 | ||
| 120 | /* Wakeup CPU1 only if it is not offlined */ | 136 | /* Wakeup CPU1 only if it is not offlined */ |
| 121 | if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) { | 137 | 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, | |||
| 138 | 154 | ||
| 139 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id); | 155 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id); |
| 140 | 156 | ||
| 157 | fail: | ||
| 158 | cpuidle_coupled_parallel_barrier(dev, &abort_barrier); | ||
| 159 | cpu_done[dev->cpu] = false; | ||
| 160 | |||
| 141 | local_fiq_enable(); | 161 | local_fiq_enable(); |
| 142 | 162 | ||
| 143 | return index; | 163 | return index; |
