Commit b681286917eecf9320ca71310aee093c11afd910

Authored by Dave Gerlach
Committed by Tero Kristo
1 parent fd6b279841

ARM: OMAP2: pm33xx: Fix race condition between cpuidle and suspend

CPUIdle does not get disabled until noirq suspend, but am33xx_pm_enter
is called early in the suspend sequence, which configures the wkup_m3
for deep sleep before waiting for the m3_irq2 interrupt. On AM43xx, this
interrupt is triggerred by a WFI instruction with MPU clockdomain set to
HW_AUTO and SCU set to low power state, which is the same condition present
in cpuidle state.

If system attempts to enter cpuidle c-state during
suspend path (happens very rarely) the system will hang because it will
gate the MPU clock and pass control to wkup_m3 which attempts to put
system in DeepSleep when it is not actually prepared.

By using cpu_idle_poll_ctrl we can prevent cpuidle from entering
c-states during the suspend path and prevent this hang. Also useful on
AM33xx to prevent suspend from failing without a hang due to cpuidle
reconfiguring the wkup_m3 during suspend for mpu pll bypass only rather
than deep sleep.

Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

Showing 1 changed file with 3 additions and 0 deletions Side-by-side Diff

arch/arm/mach-omap2/pm33xx.c
... ... @@ -333,6 +333,7 @@
333 333 {
334 334 int i;
335 335  
  336 + cpu_idle_poll_ctrl(true);
336 337  
337 338 switch (state) {
338 339 case PM_SUSPEND_MEM:
... ... @@ -372,6 +373,8 @@
372 373 if (retrigger_irq)
373 374 writel_relaxed(1 << (retrigger_irq & 31),
374 375 gic_dist_base + 0x200 + retrigger_irq / 32 * 4);
  376 +
  377 + cpu_idle_poll_ctrl(false);
375 378 }
376 379  
377 380 static int am33xx_pm_valid(suspend_state_t state)