Skip to content

Commit 23f62d7

Browse files
committed
PM: sleep: Pause cpuidle later and resume it earlier during system transitions
Commit 8651f97 ("PM / cpuidle: System resume hang fix with cpuidle") that introduced cpuidle pausing during system suspend did that to work around a platform firmware issue causing systems to hang during resume if CPUs were allowed to enter idle states in the system suspend and resume code paths. However, pausing cpuidle before the last phase of suspending devices is the source of an otherwise arbitrary difference between the suspend-to-idle path and other system suspend variants, so it is cleaner to do that later, before taking secondary CPUs offline (it is still safer to take secondary CPUs offline with cpuidle paused, though). Modify the code accordingly, but in order to avoid code duplication, introduce new wrapper functions, pm_sleep_disable_secondary_cpus() and pm_sleep_enable_secondary_cpus(), to combine cpuidle_pause() and cpuidle_resume(), respectively, with the handling of secondary CPUs during system-wide transitions to sleep states. Signed-off-by: Rafael J. Wysocki <[email protected]> Reviewed-by: Ulf Hansson <[email protected]> Tested-by: Ulf Hansson <[email protected]>
1 parent 8d89835 commit 23f62d7

File tree

4 files changed

+24
-20
lines changed

4 files changed

+24
-20
lines changed

drivers/base/power/main.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
#include <linux/suspend.h>
3333
#include <trace/events/power.h>
3434
#include <linux/cpufreq.h>
35-
#include <linux/cpuidle.h>
3635
#include <linux/devfreq.h>
3736
#include <linux/timer.h>
3837

@@ -879,7 +878,6 @@ void dpm_resume_early(pm_message_t state)
879878
void dpm_resume_start(pm_message_t state)
880879
{
881880
dpm_resume_noirq(state);
882-
cpuidle_resume();
883881
dpm_resume_early(state);
884882
}
885883
EXPORT_SYMBOL_GPL(dpm_resume_start);
@@ -1519,13 +1517,9 @@ int dpm_suspend_end(pm_message_t state)
15191517
if (error)
15201518
goto out;
15211519

1522-
cpuidle_pause();
1523-
15241520
error = dpm_suspend_noirq(state);
1525-
if (error) {
1526-
cpuidle_resume();
1521+
if (error)
15271522
dpm_resume_early(resume_event(state));
1528-
}
15291523

15301524
out:
15311525
dpm_show_time(starttime, state, error, "end");

kernel/power/hibernate.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ static int create_image(int platform_mode)
300300
if (error || hibernation_test(TEST_PLATFORM))
301301
goto Platform_finish;
302302

303-
error = suspend_disable_secondary_cpus();
303+
error = pm_sleep_disable_secondary_cpus();
304304
if (error || hibernation_test(TEST_CPUS))
305305
goto Enable_cpus;
306306

@@ -342,7 +342,7 @@ static int create_image(int platform_mode)
342342
local_irq_enable();
343343

344344
Enable_cpus:
345-
suspend_enable_secondary_cpus();
345+
pm_sleep_enable_secondary_cpus();
346346

347347
/* Allow architectures to do nosmt-specific post-resume dances */
348348
if (!in_suspend)
@@ -466,6 +466,8 @@ static int resume_target_kernel(bool platform_mode)
466466
if (error)
467467
goto Cleanup;
468468

469+
cpuidle_pause();
470+
469471
error = hibernate_resume_nonboot_cpu_disable();
470472
if (error)
471473
goto Enable_cpus;
@@ -509,7 +511,7 @@ static int resume_target_kernel(bool platform_mode)
509511
local_irq_enable();
510512

511513
Enable_cpus:
512-
suspend_enable_secondary_cpus();
514+
pm_sleep_enable_secondary_cpus();
513515

514516
Cleanup:
515517
platform_restore_cleanup(platform_mode);
@@ -587,7 +589,7 @@ int hibernation_platform_enter(void)
587589
if (error)
588590
goto Platform_finish;
589591

590-
error = suspend_disable_secondary_cpus();
592+
error = pm_sleep_disable_secondary_cpus();
591593
if (error)
592594
goto Enable_cpus;
593595

@@ -609,7 +611,7 @@ int hibernation_platform_enter(void)
609611
local_irq_enable();
610612

611613
Enable_cpus:
612-
suspend_enable_secondary_cpus();
614+
pm_sleep_enable_secondary_cpus();
613615

614616
Platform_finish:
615617
hibernation_ops->finish();

kernel/power/power.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <linux/utsname.h>
55
#include <linux/freezer.h>
66
#include <linux/compiler.h>
7+
#include <linux/cpu.h>
8+
#include <linux/cpuidle.h>
79

810
struct swsusp_info {
911
struct new_utsname uts;
@@ -310,3 +312,15 @@ extern int pm_wake_lock(const char *buf);
310312
extern int pm_wake_unlock(const char *buf);
311313

312314
#endif /* !CONFIG_PM_WAKELOCKS */
315+
316+
static inline int pm_sleep_disable_secondary_cpus(void)
317+
{
318+
cpuidle_pause();
319+
return suspend_disable_secondary_cpus();
320+
}
321+
322+
static inline void pm_sleep_enable_secondary_cpus(void)
323+
{
324+
suspend_enable_secondary_cpus();
325+
cpuidle_resume();
326+
}

kernel/power/suspend.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -403,9 +403,6 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
403403
if (error)
404404
goto Devices_early_resume;
405405

406-
if (state != PM_SUSPEND_TO_IDLE)
407-
cpuidle_pause();
408-
409406
error = dpm_suspend_noirq(PMSG_SUSPEND);
410407
if (error) {
411408
pr_err("noirq suspend of devices failed\n");
@@ -423,7 +420,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
423420
goto Platform_wake;
424421
}
425422

426-
error = suspend_disable_secondary_cpus();
423+
error = pm_sleep_disable_secondary_cpus();
427424
if (error || suspend_test(TEST_CPUS))
428425
goto Enable_cpus;
429426

@@ -453,16 +450,13 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
453450
BUG_ON(irqs_disabled());
454451

455452
Enable_cpus:
456-
suspend_enable_secondary_cpus();
453+
pm_sleep_enable_secondary_cpus();
457454

458455
Platform_wake:
459456
platform_resume_noirq(state);
460457
dpm_resume_noirq(PMSG_RESUME);
461458

462459
Platform_early_resume:
463-
if (state != PM_SUSPEND_TO_IDLE)
464-
cpuidle_resume();
465-
466460
platform_resume_early(state);
467461

468462
Devices_early_resume:

0 commit comments

Comments
 (0)