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(); |