diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2018-05-25 17:54:41 +0200 | 
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2018-05-27 11:55:02 +0200 | 
| commit | c1a957d17086d20d52d7f9c8dffaeac2ee09d6f9 (patch) | |
| tree | 55fd308201993a3caf2b2df2bf23ab9ef2ed5718 /kernel/power/hibernate.c | |
| parent | 771c577c23bac90597c685971d7297ea00f99d11 (diff) | |
PM / suspend: Prevent might sleep splats
timekeeping suspend/resume calls read_persistent_clock() which takes
rtc_lock. That results in might sleep warnings because at that point
we run with interrupts disabled.
We cannot convert rtc_lock to a raw spinlock as that would trigger
other might sleep warnings.
As a workaround we disable the might sleep warnings by setting
system_state to SYSTEM_SUSPEND before calling sysdev_suspend() and
restoring it to SYSTEM_RUNNING afer sysdev_resume(). There is no lock
contention because hibernate / suspend to RAM is single-CPU at this
point.
In s2idle's case the system_state is set to SYSTEM_SUSPEND before
timekeeping_suspend() which is invoked by the last CPU. In the resume
case it set back to SYSTEM_RUNNING after timekeeping_resume() which is
invoked by the first CPU in the resume case. The other CPUs will block
on tick_freeze_lock.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[bigeasy: cover s2idle in tick_freeze() / tick_unfreeze()]
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'kernel/power/hibernate.c')
| -rw-r--r-- | kernel/power/hibernate.c | 7 | 
1 files changed, 7 insertions, 0 deletions
| diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 5454cc639a8d..9c85c7822383 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -287,6 +287,8 @@ static int create_image(int platform_mode)  	local_irq_disable(); +	system_state = SYSTEM_SUSPEND; +  	error = syscore_suspend();  	if (error) {  		pr_err("Some system devices failed to power down, aborting hibernation\n"); @@ -317,6 +319,7 @@ static int create_image(int platform_mode)  	syscore_resume();   Enable_irqs: +	system_state = SYSTEM_RUNNING;  	local_irq_enable();   Enable_cpus: @@ -445,6 +448,7 @@ static int resume_target_kernel(bool platform_mode)  		goto Enable_cpus;  	local_irq_disable(); +	system_state = SYSTEM_SUSPEND;  	error = syscore_suspend();  	if (error) @@ -478,6 +482,7 @@ static int resume_target_kernel(bool platform_mode)  	syscore_resume();   Enable_irqs: +	system_state = SYSTEM_RUNNING;  	local_irq_enable();   Enable_cpus: @@ -563,6 +568,7 @@ int hibernation_platform_enter(void)  		goto Enable_cpus;  	local_irq_disable(); +	system_state = SYSTEM_SUSPEND;  	syscore_suspend();  	if (pm_wakeup_pending()) {  		error = -EAGAIN; @@ -575,6 +581,7 @@ int hibernation_platform_enter(void)   Power_up:  	syscore_resume(); +	system_state = SYSTEM_RUNNING;  	local_irq_enable();   Enable_cpus: | 
