diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2011-04-11 16:54:42 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2011-04-11 16:54:42 -0400 |
commit | 1f112cee07b314e244ee9e71d9c1e6950dc13327 (patch) | |
tree | e089e646c78701e37b4ebe00db36082e47cab2d5 | |
parent | b42282e5a05018ecdc0d63a4ad530b0999785912 (diff) |
PM / Hibernate: Introduce CONFIG_HIBERNATE_CALLBACKS
Xen save/restore is going to use hibernate device callbacks for
quiescing devices and putting them back to normal operations and it
would need to select CONFIG_HIBERNATION for this purpose. However,
that also would cause the hibernate interfaces for user space to be
enabled, which might confuse user space, because the Xen kernels
don't support hibernation. Moreover, it would be wasteful, as it
would make the Xen kernels include a substantial amount of code that
they would never use.
To address this issue introduce new power management Kconfig option
CONFIG_HIBERNATE_CALLBACKS, such that it will only select the code
that is necessary for the hibernate device callbacks to work and make
CONFIG_HIBERNATION select it. Then, Xen save/restore will be able to
select CONFIG_HIBERNATE_CALLBACKS without dragging the entire
hibernate code along with it.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Tested-by: Shriram Rajagopalan <rshriram@cs.ubc.ca>
-rw-r--r-- | arch/powerpc/kernel/ibmebus.c | 6 | ||||
-rw-r--r-- | drivers/amba/bus.c | 6 | ||||
-rw-r--r-- | drivers/base/platform.c | 6 | ||||
-rw-r--r-- | drivers/base/power/main.c | 8 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 6 | ||||
-rw-r--r-- | drivers/xen/manage.c | 6 | ||||
-rw-r--r-- | include/linux/suspend.h | 11 | ||||
-rw-r--r-- | kernel/power/Kconfig | 6 |
8 files changed, 27 insertions, 28 deletions
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index c00d4ca1ee15..28581f1ad2c0 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c | |||
@@ -527,7 +527,7 @@ static int ibmebus_bus_pm_resume_noirq(struct device *dev) | |||
527 | 527 | ||
528 | #endif /* !CONFIG_SUSPEND */ | 528 | #endif /* !CONFIG_SUSPEND */ |
529 | 529 | ||
530 | #ifdef CONFIG_HIBERNATION | 530 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
531 | 531 | ||
532 | static int ibmebus_bus_pm_freeze(struct device *dev) | 532 | static int ibmebus_bus_pm_freeze(struct device *dev) |
533 | { | 533 | { |
@@ -665,7 +665,7 @@ static int ibmebus_bus_pm_restore_noirq(struct device *dev) | |||
665 | return ret; | 665 | return ret; |
666 | } | 666 | } |
667 | 667 | ||
668 | #else /* !CONFIG_HIBERNATION */ | 668 | #else /* !CONFIG_HIBERNATE_CALLBACKS */ |
669 | 669 | ||
670 | #define ibmebus_bus_pm_freeze NULL | 670 | #define ibmebus_bus_pm_freeze NULL |
671 | #define ibmebus_bus_pm_thaw NULL | 671 | #define ibmebus_bus_pm_thaw NULL |
@@ -676,7 +676,7 @@ static int ibmebus_bus_pm_restore_noirq(struct device *dev) | |||
676 | #define ibmebus_bus_pm_poweroff_noirq NULL | 676 | #define ibmebus_bus_pm_poweroff_noirq NULL |
677 | #define ibmebus_bus_pm_restore_noirq NULL | 677 | #define ibmebus_bus_pm_restore_noirq NULL |
678 | 678 | ||
679 | #endif /* !CONFIG_HIBERNATION */ | 679 | #endif /* !CONFIG_HIBERNATE_CALLBACKS */ |
680 | 680 | ||
681 | static struct dev_pm_ops ibmebus_bus_dev_pm_ops = { | 681 | static struct dev_pm_ops ibmebus_bus_dev_pm_ops = { |
682 | .prepare = ibmebus_bus_pm_prepare, | 682 | .prepare = ibmebus_bus_pm_prepare, |
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 821040503154..7025593a58c8 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c | |||
@@ -214,7 +214,7 @@ static int amba_pm_resume_noirq(struct device *dev) | |||
214 | 214 | ||
215 | #endif /* !CONFIG_SUSPEND */ | 215 | #endif /* !CONFIG_SUSPEND */ |
216 | 216 | ||
217 | #ifdef CONFIG_HIBERNATION | 217 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
218 | 218 | ||
219 | static int amba_pm_freeze(struct device *dev) | 219 | static int amba_pm_freeze(struct device *dev) |
220 | { | 220 | { |
@@ -352,7 +352,7 @@ static int amba_pm_restore_noirq(struct device *dev) | |||
352 | return ret; | 352 | return ret; |
353 | } | 353 | } |
354 | 354 | ||
355 | #else /* !CONFIG_HIBERNATION */ | 355 | #else /* !CONFIG_HIBERNATE_CALLBACKS */ |
356 | 356 | ||
357 | #define amba_pm_freeze NULL | 357 | #define amba_pm_freeze NULL |
358 | #define amba_pm_thaw NULL | 358 | #define amba_pm_thaw NULL |
@@ -363,7 +363,7 @@ static int amba_pm_restore_noirq(struct device *dev) | |||
363 | #define amba_pm_poweroff_noirq NULL | 363 | #define amba_pm_poweroff_noirq NULL |
364 | #define amba_pm_restore_noirq NULL | 364 | #define amba_pm_restore_noirq NULL |
365 | 365 | ||
366 | #endif /* !CONFIG_HIBERNATION */ | 366 | #endif /* !CONFIG_HIBERNATE_CALLBACKS */ |
367 | 367 | ||
368 | #ifdef CONFIG_PM | 368 | #ifdef CONFIG_PM |
369 | 369 | ||
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index f051cfff18af..92792313d24a 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -771,7 +771,7 @@ int __weak platform_pm_resume_noirq(struct device *dev) | |||
771 | 771 | ||
772 | #endif /* !CONFIG_SUSPEND */ | 772 | #endif /* !CONFIG_SUSPEND */ |
773 | 773 | ||
774 | #ifdef CONFIG_HIBERNATION | 774 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
775 | 775 | ||
776 | static int platform_pm_freeze(struct device *dev) | 776 | static int platform_pm_freeze(struct device *dev) |
777 | { | 777 | { |
@@ -909,7 +909,7 @@ static int platform_pm_restore_noirq(struct device *dev) | |||
909 | return ret; | 909 | return ret; |
910 | } | 910 | } |
911 | 911 | ||
912 | #else /* !CONFIG_HIBERNATION */ | 912 | #else /* !CONFIG_HIBERNATE_CALLBACKS */ |
913 | 913 | ||
914 | #define platform_pm_freeze NULL | 914 | #define platform_pm_freeze NULL |
915 | #define platform_pm_thaw NULL | 915 | #define platform_pm_thaw NULL |
@@ -920,7 +920,7 @@ static int platform_pm_restore_noirq(struct device *dev) | |||
920 | #define platform_pm_poweroff_noirq NULL | 920 | #define platform_pm_poweroff_noirq NULL |
921 | #define platform_pm_restore_noirq NULL | 921 | #define platform_pm_restore_noirq NULL |
922 | 922 | ||
923 | #endif /* !CONFIG_HIBERNATION */ | 923 | #endif /* !CONFIG_HIBERNATE_CALLBACKS */ |
924 | 924 | ||
925 | #ifdef CONFIG_PM_RUNTIME | 925 | #ifdef CONFIG_PM_RUNTIME |
926 | 926 | ||
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 052dc53eef38..fbc5b6e7c591 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -233,7 +233,7 @@ static int pm_op(struct device *dev, | |||
233 | } | 233 | } |
234 | break; | 234 | break; |
235 | #endif /* CONFIG_SUSPEND */ | 235 | #endif /* CONFIG_SUSPEND */ |
236 | #ifdef CONFIG_HIBERNATION | 236 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
237 | case PM_EVENT_FREEZE: | 237 | case PM_EVENT_FREEZE: |
238 | case PM_EVENT_QUIESCE: | 238 | case PM_EVENT_QUIESCE: |
239 | if (ops->freeze) { | 239 | if (ops->freeze) { |
@@ -260,7 +260,7 @@ static int pm_op(struct device *dev, | |||
260 | suspend_report_result(ops->restore, error); | 260 | suspend_report_result(ops->restore, error); |
261 | } | 261 | } |
262 | break; | 262 | break; |
263 | #endif /* CONFIG_HIBERNATION */ | 263 | #endif /* CONFIG_HIBERNATE_CALLBACKS */ |
264 | default: | 264 | default: |
265 | error = -EINVAL; | 265 | error = -EINVAL; |
266 | } | 266 | } |
@@ -308,7 +308,7 @@ static int pm_noirq_op(struct device *dev, | |||
308 | } | 308 | } |
309 | break; | 309 | break; |
310 | #endif /* CONFIG_SUSPEND */ | 310 | #endif /* CONFIG_SUSPEND */ |
311 | #ifdef CONFIG_HIBERNATION | 311 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
312 | case PM_EVENT_FREEZE: | 312 | case PM_EVENT_FREEZE: |
313 | case PM_EVENT_QUIESCE: | 313 | case PM_EVENT_QUIESCE: |
314 | if (ops->freeze_noirq) { | 314 | if (ops->freeze_noirq) { |
@@ -335,7 +335,7 @@ static int pm_noirq_op(struct device *dev, | |||
335 | suspend_report_result(ops->restore_noirq, error); | 335 | suspend_report_result(ops->restore_noirq, error); |
336 | } | 336 | } |
337 | break; | 337 | break; |
338 | #endif /* CONFIG_HIBERNATION */ | 338 | #endif /* CONFIG_HIBERNATE_CALLBACKS */ |
339 | default: | 339 | default: |
340 | error = -EINVAL; | 340 | error = -EINVAL; |
341 | } | 341 | } |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index d86ea8b01137..135df164a4c1 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -781,7 +781,7 @@ static int pci_pm_resume(struct device *dev) | |||
781 | 781 | ||
782 | #endif /* !CONFIG_SUSPEND */ | 782 | #endif /* !CONFIG_SUSPEND */ |
783 | 783 | ||
784 | #ifdef CONFIG_HIBERNATION | 784 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
785 | 785 | ||
786 | static int pci_pm_freeze(struct device *dev) | 786 | static int pci_pm_freeze(struct device *dev) |
787 | { | 787 | { |
@@ -970,7 +970,7 @@ static int pci_pm_restore(struct device *dev) | |||
970 | return error; | 970 | return error; |
971 | } | 971 | } |
972 | 972 | ||
973 | #else /* !CONFIG_HIBERNATION */ | 973 | #else /* !CONFIG_HIBERNATE_CALLBACKS */ |
974 | 974 | ||
975 | #define pci_pm_freeze NULL | 975 | #define pci_pm_freeze NULL |
976 | #define pci_pm_freeze_noirq NULL | 976 | #define pci_pm_freeze_noirq NULL |
@@ -981,7 +981,7 @@ static int pci_pm_restore(struct device *dev) | |||
981 | #define pci_pm_restore NULL | 981 | #define pci_pm_restore NULL |
982 | #define pci_pm_restore_noirq NULL | 982 | #define pci_pm_restore_noirq NULL |
983 | 983 | ||
984 | #endif /* !CONFIG_HIBERNATION */ | 984 | #endif /* !CONFIG_HIBERNATE_CALLBACKS */ |
985 | 985 | ||
986 | #ifdef CONFIG_PM_RUNTIME | 986 | #ifdef CONFIG_PM_RUNTIME |
987 | 987 | ||
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 95143dd6904d..1ac94125bf93 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
@@ -61,7 +61,7 @@ static void xen_post_suspend(int cancelled) | |||
61 | xen_mm_unpin_all(); | 61 | xen_mm_unpin_all(); |
62 | } | 62 | } |
63 | 63 | ||
64 | #ifdef CONFIG_HIBERNATION | 64 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
65 | static int xen_suspend(void *data) | 65 | static int xen_suspend(void *data) |
66 | { | 66 | { |
67 | struct suspend_info *si = data; | 67 | struct suspend_info *si = data; |
@@ -173,7 +173,7 @@ out: | |||
173 | #endif | 173 | #endif |
174 | shutting_down = SHUTDOWN_INVALID; | 174 | shutting_down = SHUTDOWN_INVALID; |
175 | } | 175 | } |
176 | #endif /* CONFIG_HIBERNATION */ | 176 | #endif /* CONFIG_HIBERNATE_CALLBACKS */ |
177 | 177 | ||
178 | struct shutdown_handler { | 178 | struct shutdown_handler { |
179 | const char *command; | 179 | const char *command; |
@@ -202,7 +202,7 @@ static void shutdown_handler(struct xenbus_watch *watch, | |||
202 | { "poweroff", do_poweroff }, | 202 | { "poweroff", do_poweroff }, |
203 | { "halt", do_poweroff }, | 203 | { "halt", do_poweroff }, |
204 | { "reboot", do_reboot }, | 204 | { "reboot", do_reboot }, |
205 | #ifdef CONFIG_HIBERNATION | 205 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
206 | { "suspend", do_suspend }, | 206 | { "suspend", do_suspend }, |
207 | #endif | 207 | #endif |
208 | {NULL, NULL}, | 208 | {NULL, NULL}, |
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 5a89e3612875..083ffea7ba18 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
@@ -249,6 +249,8 @@ extern void hibernation_set_ops(const struct platform_hibernation_ops *ops); | |||
249 | extern int hibernate(void); | 249 | extern int hibernate(void); |
250 | extern bool system_entering_hibernation(void); | 250 | extern bool system_entering_hibernation(void); |
251 | #else /* CONFIG_HIBERNATION */ | 251 | #else /* CONFIG_HIBERNATION */ |
252 | static inline void register_nosave_region(unsigned long b, unsigned long e) {} | ||
253 | static inline void register_nosave_region_late(unsigned long b, unsigned long e) {} | ||
252 | static inline int swsusp_page_is_forbidden(struct page *p) { return 0; } | 254 | static inline int swsusp_page_is_forbidden(struct page *p) { return 0; } |
253 | static inline void swsusp_set_page_free(struct page *p) {} | 255 | static inline void swsusp_set_page_free(struct page *p) {} |
254 | static inline void swsusp_unset_page_free(struct page *p) {} | 256 | static inline void swsusp_unset_page_free(struct page *p) {} |
@@ -297,14 +299,7 @@ static inline bool pm_wakeup_pending(void) { return false; } | |||
297 | 299 | ||
298 | extern struct mutex pm_mutex; | 300 | extern struct mutex pm_mutex; |
299 | 301 | ||
300 | #ifndef CONFIG_HIBERNATION | 302 | #ifndef CONFIG_HIBERNATE_CALLBACKS |
301 | static inline void register_nosave_region(unsigned long b, unsigned long e) | ||
302 | { | ||
303 | } | ||
304 | static inline void register_nosave_region_late(unsigned long b, unsigned long e) | ||
305 | { | ||
306 | } | ||
307 | |||
308 | static inline void lock_system_sleep(void) {} | 303 | static inline void lock_system_sleep(void) {} |
309 | static inline void unlock_system_sleep(void) {} | 304 | static inline void unlock_system_sleep(void) {} |
310 | 305 | ||
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 4603f08dc47b..049791468d37 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -18,9 +18,13 @@ config SUSPEND_FREEZER | |||
18 | 18 | ||
19 | Turning OFF this setting is NOT recommended! If in doubt, say Y. | 19 | Turning OFF this setting is NOT recommended! If in doubt, say Y. |
20 | 20 | ||
21 | config HIBERNATE_CALLBACKS | ||
22 | bool | ||
23 | |||
21 | config HIBERNATION | 24 | config HIBERNATION |
22 | bool "Hibernation (aka 'suspend to disk')" | 25 | bool "Hibernation (aka 'suspend to disk')" |
23 | depends on SWAP && ARCH_HIBERNATION_POSSIBLE | 26 | depends on SWAP && ARCH_HIBERNATION_POSSIBLE |
27 | select HIBERNATE_CALLBACKS | ||
24 | select LZO_COMPRESS | 28 | select LZO_COMPRESS |
25 | select LZO_DECOMPRESS | 29 | select LZO_DECOMPRESS |
26 | ---help--- | 30 | ---help--- |
@@ -85,7 +89,7 @@ config PM_STD_PARTITION | |||
85 | 89 | ||
86 | config PM_SLEEP | 90 | config PM_SLEEP |
87 | def_bool y | 91 | def_bool y |
88 | depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE | 92 | depends on SUSPEND || HIBERNATE_CALLBACKS || XEN_SAVE_RESTORE |
89 | 93 | ||
90 | config PM_SLEEP_SMP | 94 | config PM_SLEEP_SMP |
91 | def_bool y | 95 | def_bool y |