diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2011-04-19 18:36:11 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rjw@sisk.pl> | 2011-04-19 18:36:11 -0400 |
| commit | 19234c0819da0e043a02710488dfd9b242b42eba (patch) | |
| tree | c55331dd010e5fe257e001261f1a31f53f62dff4 | |
| parent | 2ca6f62f595c01f689b269db6736de5544da7667 (diff) | |
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>
| -rw-r--r-- | arch/x86/kernel/apm_32.c | 5 | ||||
| -rw-r--r-- | drivers/base/syscore.c | 2 | ||||
| -rw-r--r-- | drivers/xen/manage.c | 9 | ||||
| -rw-r--r-- | kernel/kexec.c | 7 |
4 files changed, 22 insertions, 1 deletions
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 0b4be431c620..adee12e0da1f 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c | |||
| @@ -228,6 +228,7 @@ | |||
| 228 | #include <linux/kthread.h> | 228 | #include <linux/kthread.h> |
| 229 | #include <linux/jiffies.h> | 229 | #include <linux/jiffies.h> |
| 230 | #include <linux/acpi.h> | 230 | #include <linux/acpi.h> |
| 231 | #include <linux/syscore_ops.h> | ||
| 231 | 232 | ||
| 232 | #include <asm/system.h> | 233 | #include <asm/system.h> |
| 233 | #include <asm/uaccess.h> | 234 | #include <asm/uaccess.h> |
| @@ -1238,6 +1239,7 @@ static int suspend(int vetoable) | |||
| 1238 | 1239 | ||
| 1239 | local_irq_disable(); | 1240 | local_irq_disable(); |
| 1240 | sysdev_suspend(PMSG_SUSPEND); | 1241 | sysdev_suspend(PMSG_SUSPEND); |
| 1242 | syscore_suspend(); | ||
| 1241 | 1243 | ||
| 1242 | local_irq_enable(); | 1244 | local_irq_enable(); |
| 1243 | 1245 | ||
| @@ -1255,6 +1257,7 @@ static int suspend(int vetoable) | |||
| 1255 | apm_error("suspend", err); | 1257 | apm_error("suspend", err); |
| 1256 | err = (err == APM_SUCCESS) ? 0 : -EIO; | 1258 | err = (err == APM_SUCCESS) ? 0 : -EIO; |
| 1257 | 1259 | ||
| 1260 | syscore_resume(); | ||
| 1258 | sysdev_resume(); | 1261 | sysdev_resume(); |
| 1259 | local_irq_enable(); | 1262 | local_irq_enable(); |
| 1260 | 1263 | ||
| @@ -1280,6 +1283,7 @@ static void standby(void) | |||
| 1280 | 1283 | ||
| 1281 | local_irq_disable(); | 1284 | local_irq_disable(); |
| 1282 | sysdev_suspend(PMSG_SUSPEND); | 1285 | sysdev_suspend(PMSG_SUSPEND); |
| 1286 | syscore_suspend(); | ||
| 1283 | local_irq_enable(); | 1287 | local_irq_enable(); |
| 1284 | 1288 | ||
| 1285 | err = set_system_power_state(APM_STATE_STANDBY); | 1289 | err = set_system_power_state(APM_STATE_STANDBY); |
| @@ -1287,6 +1291,7 @@ static void standby(void) | |||
| 1287 | apm_error("standby", err); | 1291 | apm_error("standby", err); |
| 1288 | 1292 | ||
| 1289 | local_irq_disable(); | 1293 | local_irq_disable(); |
| 1294 | syscore_resume(); | ||
| 1290 | sysdev_resume(); | 1295 | sysdev_resume(); |
| 1291 | local_irq_enable(); | 1296 | local_irq_enable(); |
| 1292 | 1297 | ||
diff --git a/drivers/base/syscore.c b/drivers/base/syscore.c index 90af2943f9e4..c126db3cb7d1 100644 --- a/drivers/base/syscore.c +++ b/drivers/base/syscore.c | |||
| @@ -73,6 +73,7 @@ int syscore_suspend(void) | |||
| 73 | 73 | ||
| 74 | return ret; | 74 | return ret; |
| 75 | } | 75 | } |
| 76 | EXPORT_SYMBOL_GPL(syscore_suspend); | ||
| 76 | 77 | ||
| 77 | /** | 78 | /** |
| 78 | * syscore_resume - Execute all the registered system core resume callbacks. | 79 | * syscore_resume - Execute all the registered system core resume callbacks. |
| @@ -95,6 +96,7 @@ void syscore_resume(void) | |||
| 95 | "Interrupts enabled after %pF\n", ops->resume); | 96 | "Interrupts enabled after %pF\n", ops->resume); |
| 96 | } | 97 | } |
| 97 | } | 98 | } |
| 99 | EXPORT_SYMBOL_GPL(syscore_resume); | ||
| 98 | #endif /* CONFIG_PM_SLEEP */ | 100 | #endif /* CONFIG_PM_SLEEP */ |
| 99 | 101 | ||
| 100 | /** | 102 | /** |
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 1ac94125bf93..a2eee574784e 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <linux/sysrq.h> | 8 | #include <linux/sysrq.h> |
| 9 | #include <linux/stop_machine.h> | 9 | #include <linux/stop_machine.h> |
| 10 | #include <linux/freezer.h> | 10 | #include <linux/freezer.h> |
| 11 | #include <linux/syscore_ops.h> | ||
| 11 | 12 | ||
| 12 | #include <xen/xen.h> | 13 | #include <xen/xen.h> |
| 13 | #include <xen/xenbus.h> | 14 | #include <xen/xenbus.h> |
| @@ -70,8 +71,13 @@ static int xen_suspend(void *data) | |||
| 70 | BUG_ON(!irqs_disabled()); | 71 | BUG_ON(!irqs_disabled()); |
| 71 | 72 | ||
| 72 | err = sysdev_suspend(PMSG_FREEZE); | 73 | err = sysdev_suspend(PMSG_FREEZE); |
| 74 | if (!err) { | ||
| 75 | err = syscore_suspend(); | ||
| 76 | if (err) | ||
| 77 | sysdev_resume(); | ||
| 78 | } | ||
| 73 | if (err) { | 79 | if (err) { |
| 74 | printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", | 80 | printk(KERN_ERR "xen_suspend: system core suspend failed: %d\n", |
| 75 | err); | 81 | err); |
| 76 | return err; | 82 | return err; |
| 77 | } | 83 | } |
| @@ -95,6 +101,7 @@ static int xen_suspend(void *data) | |||
| 95 | xen_timer_resume(); | 101 | xen_timer_resume(); |
| 96 | } | 102 | } |
| 97 | 103 | ||
| 104 | syscore_resume(); | ||
| 98 | sysdev_resume(); | 105 | sysdev_resume(); |
| 99 | 106 | ||
| 100 | return 0; | 107 | return 0; |
diff --git a/kernel/kexec.c b/kernel/kexec.c index 55936f9cb251..87b77de03dd3 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/vmalloc.h> | 33 | #include <linux/vmalloc.h> |
| 34 | #include <linux/swap.h> | 34 | #include <linux/swap.h> |
| 35 | #include <linux/kmsg_dump.h> | 35 | #include <linux/kmsg_dump.h> |
| 36 | #include <linux/syscore_ops.h> | ||
| 36 | 37 | ||
| 37 | #include <asm/page.h> | 38 | #include <asm/page.h> |
| 38 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
| @@ -1532,6 +1533,11 @@ int kernel_kexec(void) | |||
| 1532 | local_irq_disable(); | 1533 | local_irq_disable(); |
| 1533 | /* Suspend system devices */ | 1534 | /* Suspend system devices */ |
| 1534 | error = sysdev_suspend(PMSG_FREEZE); | 1535 | error = sysdev_suspend(PMSG_FREEZE); |
| 1536 | if (!error) { | ||
| 1537 | error = syscore_suspend(); | ||
| 1538 | if (error) | ||
| 1539 | sysdev_resume(); | ||
| 1540 | } | ||
| 1535 | if (error) | 1541 | if (error) |
| 1536 | goto Enable_irqs; | 1542 | goto Enable_irqs; |
| 1537 | } else | 1543 | } else |
| @@ -1546,6 +1552,7 @@ int kernel_kexec(void) | |||
| 1546 | 1552 | ||
| 1547 | #ifdef CONFIG_KEXEC_JUMP | 1553 | #ifdef CONFIG_KEXEC_JUMP |
| 1548 | if (kexec_image->preserve_context) { | 1554 | if (kexec_image->preserve_context) { |
| 1555 | syscore_resume(); | ||
| 1549 | sysdev_resume(); | 1556 | sysdev_resume(); |
| 1550 | Enable_irqs: | 1557 | Enable_irqs: |
| 1551 | local_irq_enable(); | 1558 | local_irq_enable(); |
