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

PM: Add missing syscore_suspend() and syscore_resume() calls

Device suspend/resume infrastructure is used not only by the suspend
and hibernate code in kernel/power, but also by APM, Xen and the
kexec jump feature. However, commit 40dc166cb5dddbd36aa4ad11c03915ea
(PM / Core: Introduce struct syscore_ops for core subsystems PM)
failed to add syscore_suspend() and syscore_resume() calls to that
code, which generally leads to breakage when the features in question
are used.

To fix this problem, add the missing syscore_suspend() and
syscore_resume() calls to arch/x86/kernel/apm_32.c, kernel/kexec.c
and drivers/xen/manage.c.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

+22 -1
+5
arch/x86/kernel/apm_32.c
··· 228 228 #include <linux/kthread.h> 229 229 #include <linux/jiffies.h> 230 230 #include <linux/acpi.h> 231 + #include <linux/syscore_ops.h> 231 232 232 233 #include <asm/system.h> 233 234 #include <asm/uaccess.h> ··· 1239 1238 1240 1239 local_irq_disable(); 1241 1240 sysdev_suspend(PMSG_SUSPEND); 1241 + syscore_suspend(); 1242 1242 1243 1243 local_irq_enable(); 1244 1244 ··· 1257 1255 apm_error("suspend", err); 1258 1256 err = (err == APM_SUCCESS) ? 0 : -EIO; 1259 1257 1258 + syscore_resume(); 1260 1259 sysdev_resume(); 1261 1260 local_irq_enable(); 1262 1261 ··· 1283 1280 1284 1281 local_irq_disable(); 1285 1282 sysdev_suspend(PMSG_SUSPEND); 1283 + syscore_suspend(); 1286 1284 local_irq_enable(); 1287 1285 1288 1286 err = set_system_power_state(APM_STATE_STANDBY); ··· 1291 1287 apm_error("standby", err); 1292 1288 1293 1289 local_irq_disable(); 1290 + syscore_resume(); 1294 1291 sysdev_resume(); 1295 1292 local_irq_enable(); 1296 1293
+2
drivers/base/syscore.c
··· 73 73 74 74 return ret; 75 75 } 76 + EXPORT_SYMBOL_GPL(syscore_suspend); 76 77 77 78 /** 78 79 * syscore_resume - Execute all the registered system core resume callbacks. ··· 96 95 "Interrupts enabled after %pF\n", ops->resume); 97 96 } 98 97 } 98 + EXPORT_SYMBOL_GPL(syscore_resume); 99 99 #endif /* CONFIG_PM_SLEEP */ 100 100 101 101 /**
+8 -1
drivers/xen/manage.c
··· 8 8 #include <linux/sysrq.h> 9 9 #include <linux/stop_machine.h> 10 10 #include <linux/freezer.h> 11 + #include <linux/syscore_ops.h> 11 12 12 13 #include <xen/xen.h> 13 14 #include <xen/xenbus.h> ··· 71 70 BUG_ON(!irqs_disabled()); 72 71 73 72 err = sysdev_suspend(PMSG_FREEZE); 73 + if (!err) { 74 + err = syscore_suspend(); 75 + if (err) 76 + sysdev_resume(); 77 + } 74 78 if (err) { 75 - printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", 79 + printk(KERN_ERR "xen_suspend: system core suspend failed: %d\n", 76 80 err); 77 81 return err; 78 82 } ··· 101 95 xen_timer_resume(); 102 96 } 103 97 98 + syscore_resume(); 104 99 sysdev_resume(); 105 100 106 101 return 0;
+7
kernel/kexec.c
··· 33 33 #include <linux/vmalloc.h> 34 34 #include <linux/swap.h> 35 35 #include <linux/kmsg_dump.h> 36 + #include <linux/syscore_ops.h> 36 37 37 38 #include <asm/page.h> 38 39 #include <asm/uaccess.h> ··· 1533 1532 local_irq_disable(); 1534 1533 /* Suspend system devices */ 1535 1534 error = sysdev_suspend(PMSG_FREEZE); 1535 + if (!error) { 1536 + error = syscore_suspend(); 1537 + if (error) 1538 + sysdev_resume(); 1539 + } 1536 1540 if (error) 1537 1541 goto Enable_irqs; 1538 1542 } else ··· 1552 1546 1553 1547 #ifdef CONFIG_KEXEC_JUMP 1554 1548 if (kexec_image->preserve_context) { 1549 + syscore_resume(); 1555 1550 sysdev_resume(); 1556 1551 Enable_irqs: 1557 1552 local_irq_enable();