Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PM: Fix error code paths executed after failing syscore_suspend()

If syscore_suspend() fails in suspend_enter(), create_image() or
resume_target_kernel(), it is necessary to call sysdev_resume(),
because sysdev_suspend() has been called already and succeeded
and we are going to abort the transition.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>

+12 -3
+8 -2
kernel/power/hibernate.c
··· 273 273 local_irq_disable(); 274 274 275 275 error = sysdev_suspend(PMSG_FREEZE); 276 - if (!error) 276 + if (!error) { 277 277 error = syscore_suspend(); 278 + if (error) 279 + sysdev_resume(); 280 + } 278 281 if (error) { 279 282 printk(KERN_ERR "PM: Some system devices failed to power down, " 280 283 "aborting hibernation\n"); ··· 410 407 local_irq_disable(); 411 408 412 409 error = sysdev_suspend(PMSG_QUIESCE); 413 - if (!error) 410 + if (!error) { 414 411 error = syscore_suspend(); 412 + if (error) 413 + sysdev_resume(); 414 + } 415 415 if (error) 416 416 goto Enable_irqs; 417 417
+4 -1
kernel/power/suspend.c
··· 164 164 BUG_ON(!irqs_disabled()); 165 165 166 166 error = sysdev_suspend(PMSG_SUSPEND); 167 - if (!error) 167 + if (!error) { 168 168 error = syscore_suspend(); 169 + if (error) 170 + sysdev_resume(); 171 + } 169 172 if (!error) { 170 173 if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) { 171 174 error = suspend_ops->enter(state);