Skip to content

Commit

Permalink
ARM: OMAP2+: Handle errors for cpu_pm
Browse files Browse the repository at this point in the history
[ Upstream commit 55be2f5 ]

We need to check for errors when calling cpu_pm_enter() and
cpu_cluster_pm_enter(). And we need to bail out on errors as
otherwise we can enter a deeper idle state when not desired.

I'm not aware of the lack of error handling causing issues yet,
but we need this at least for blocking deeper idle states when
a GPIO instance has pending interrupts.

Cc: Dave Gerlach <[email protected]>
Cc: Grygorii Strashko <[email protected]>
Cc: Keerthy <[email protected]>
Cc: Ladislav Michl <[email protected]>
Cc: Russell King <[email protected]>
Cc: Tero Kristo <[email protected]>
Signed-off-by: Tony Lindgren <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Linus Walleij <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
  • Loading branch information
tmlind authored and gregkh committed Oct 1, 2020
1 parent d1a749c commit 10a144b
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 13 deletions.
9 changes: 7 additions & 2 deletions arch/arm/mach-omap2/cpuidle34xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
int index)
{
struct omap3_idle_statedata *cx = &omap3_idle_data[index];
int error;

if (omap_irq_pending() || need_resched())
goto return_sleep_time;
Expand All @@ -125,8 +126,11 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
* Call idle CPU PM enter notifier chain so that
* VFP context is saved.
*/
if (cx->mpu_state == PWRDM_POWER_OFF)
cpu_pm_enter();
if (cx->mpu_state == PWRDM_POWER_OFF) {
error = cpu_pm_enter();
if (error)
goto out_clkdm_set;
}

/* Execute ARM wfi */
omap_sram_idle();
Expand All @@ -139,6 +143,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF)
cpu_pm_exit();

out_clkdm_set:
/* Re-allow idle for C1 */
if (cx->flags & OMAP_CPUIDLE_CX_NO_CLKDM_IDLE)
clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]);
Expand Down
26 changes: 17 additions & 9 deletions arch/arm/mach-omap2/cpuidle44xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
{
struct idle_statedata *cx = state_ptr + index;
u32 mpuss_can_lose_context = 0;
int error;

/*
* CPU0 has to wait and stay ON until CPU1 is OFF state.
Expand Down Expand Up @@ -159,7 +160,9 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
* Call idle CPU PM enter notifier chain so that
* VFP and per CPU interrupt context is saved.
*/
cpu_pm_enter();
error = cpu_pm_enter();
if (error)
goto cpu_pm_out;

if (dev->cpu == 0) {
pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
Expand All @@ -169,13 +172,17 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
* Call idle CPU cluster PM enter notifier chain
* to save GIC and wakeupgen context.
*/
if (mpuss_can_lose_context)
cpu_cluster_pm_enter();
if (mpuss_can_lose_context) {
error = cpu_cluster_pm_enter();
if (error)
goto cpu_cluster_pm_out;
}
}

omap4_enter_lowpower(dev->cpu, cx->cpu_state);
cpu_done[dev->cpu] = true;

cpu_cluster_pm_out:
/* Wakeup CPU1 only if it is not offlined */
if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) {

Expand All @@ -197,19 +204,20 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
}
}

/*
* Call idle CPU PM exit notifier chain to restore
* VFP and per CPU IRQ context.
*/
cpu_pm_exit();

/*
* Call idle CPU cluster PM exit notifier chain
* to restore GIC and wakeupgen context.
*/
if (dev->cpu == 0 && mpuss_can_lose_context)
cpu_cluster_pm_exit();

/*
* Call idle CPU PM exit notifier chain to restore
* VFP and per CPU IRQ context.
*/
cpu_pm_exit();

cpu_pm_out:
tick_broadcast_exit();

fail:
Expand Down
8 changes: 6 additions & 2 deletions arch/arm/mach-omap2/pm34xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ void omap_sram_idle(void)
int per_next_state = PWRDM_POWER_ON;
int core_next_state = PWRDM_POWER_ON;
u32 sdrc_pwr = 0;
int error;

mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
switch (mpu_next_state) {
Expand Down Expand Up @@ -222,8 +223,11 @@ void omap_sram_idle(void)
pwrdm_pre_transition(NULL);

/* PER */
if (per_next_state == PWRDM_POWER_OFF)
cpu_cluster_pm_enter();
if (per_next_state == PWRDM_POWER_OFF) {
error = cpu_cluster_pm_enter();
if (error)
return;
}

/* CORE */
if (core_next_state < PWRDM_POWER_ON) {
Expand Down

0 comments on commit 10a144b

Please sign in to comment.