diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2007-07-29 17:27:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-29 19:45:38 -0400 |
commit | 296699de6bdc717189a331ab6bbe90e05c94db06 (patch) | |
tree | 53c847ecc8cce11952502921844052e44ca60d5e | |
parent | b0cb1a19d05b8ea8611a9ef48a17fe417f1832e6 (diff) |
Introduce CONFIG_SUSPEND for suspend-to-Ram and standby
Introduce CONFIG_SUSPEND representing the ability to enter system sleep
states, such as the ACPI S3 state, and allow the user to choose SUSPEND
and HIBERNATION independently of each other.
Make HOTPLUG_CPU be selected automatically if SUSPEND or HIBERNATION has
been chosen and the kernel is intended for SMP systems.
Also, introduce CONFIG_PM_SLEEP which is automatically selected if
CONFIG_SUSPEND or CONFIG_HIBERNATION is set and use it to select the
code needed for both suspend and hibernation.
The top-level power management headers and the ACPI code related to
suspend and hibernation are modified to use the new definitions (the
changes in drivers/acpi/sleep/main.c are, mostly, moving code to reduce
the number of ifdefs).
There are many other files in which CONFIG_PM can be replaced with
CONFIG_PM_SLEEP or even with CONFIG_SUSPEND, but they can be updated in
the future.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/acpi/Kconfig | 8 | ||||
-rw-r--r-- | drivers/acpi/sleep/Makefile | 2 | ||||
-rw-r--r-- | drivers/acpi/sleep/main.c | 94 | ||||
-rw-r--r-- | drivers/acpi/sleep/proc.c | 10 | ||||
-rw-r--r-- | drivers/acpi/sleep/sleep.h | 2 | ||||
-rw-r--r-- | drivers/base/power/Makefile | 2 | ||||
-rw-r--r-- | drivers/base/power/power.h | 4 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 9 | ||||
-rw-r--r-- | include/acpi/acpi_drivers.h | 4 | ||||
-rw-r--r-- | include/linux/freezer.h | 6 | ||||
-rw-r--r-- | include/linux/pm.h | 15 | ||||
-rw-r--r-- | include/linux/suspend.h | 10 | ||||
-rw-r--r-- | kernel/power/Kconfig | 41 | ||||
-rw-r--r-- | kernel/power/Makefile | 3 | ||||
-rw-r--r-- | kernel/power/main.c | 26 | ||||
-rw-r--r-- | kernel/power/power.h | 10 | ||||
-rw-r--r-- | mm/page_alloc.c | 4 |
17 files changed, 164 insertions, 86 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 22b401b2e088..66e78d52a093 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -63,6 +63,14 @@ config ACPI_PROCFS | |||
63 | 63 | ||
64 | Say N to delete /proc/acpi/ files that have moved to /sys/ | 64 | Say N to delete /proc/acpi/ files that have moved to /sys/ |
65 | 65 | ||
66 | config ACPI_PROCFS_SLEEP | ||
67 | bool "/proc/acpi/sleep (deprecated)" | ||
68 | depends on PM_SLEEP && ACPI_PROCFS | ||
69 | default n | ||
70 | ---help--- | ||
71 | Create /proc/acpi/sleep | ||
72 | Deprecated by /sys/power/state | ||
73 | |||
66 | config ACPI_AC | 74 | config ACPI_AC |
67 | tristate "AC Adapter" | 75 | tristate "AC Adapter" |
68 | depends on X86 | 76 | depends on X86 |
diff --git a/drivers/acpi/sleep/Makefile b/drivers/acpi/sleep/Makefile index 01a993a1d086..2bec897ab1eb 100644 --- a/drivers/acpi/sleep/Makefile +++ b/drivers/acpi/sleep/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-y := poweroff.o wakeup.o | 1 | obj-y := poweroff.o wakeup.o |
2 | obj-y += main.o | 2 | obj-$(CONFIG_PM_SLEEP) += main.o |
3 | obj-$(CONFIG_X86) += proc.o | 3 | obj-$(CONFIG_X86) += proc.o |
4 | 4 | ||
5 | EXTRA_CFLAGS += $(ACPI_CFLAGS) | 5 | EXTRA_CFLAGS += $(ACPI_CFLAGS) |
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index b4e94c893c81..e8cff5dd4cbc 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c | |||
@@ -21,6 +21,9 @@ | |||
21 | 21 | ||
22 | u8 sleep_states[ACPI_S_STATE_COUNT]; | 22 | u8 sleep_states[ACPI_S_STATE_COUNT]; |
23 | 23 | ||
24 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | ||
25 | |||
26 | #ifdef CONFIG_SUSPEND | ||
24 | static struct pm_ops acpi_pm_ops; | 27 | static struct pm_ops acpi_pm_ops; |
25 | 28 | ||
26 | extern void do_suspend_lowlevel(void); | 29 | extern void do_suspend_lowlevel(void); |
@@ -34,11 +37,6 @@ static u32 acpi_suspend_states[] = { | |||
34 | 37 | ||
35 | static int init_8259A_after_S1; | 38 | static int init_8259A_after_S1; |
36 | 39 | ||
37 | extern int acpi_sleep_prepare(u32 acpi_state); | ||
38 | extern void acpi_power_off(void); | ||
39 | |||
40 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | ||
41 | |||
42 | /** | 40 | /** |
43 | * acpi_pm_set_target - Set the target system sleep state to the state | 41 | * acpi_pm_set_target - Set the target system sleep state to the state |
44 | * associated with given @pm_state, if supported. | 42 | * associated with given @pm_state, if supported. |
@@ -163,21 +161,6 @@ static int acpi_pm_finish(suspend_state_t pm_state) | |||
163 | return 0; | 161 | return 0; |
164 | } | 162 | } |
165 | 163 | ||
166 | int acpi_suspend(u32 acpi_state) | ||
167 | { | ||
168 | suspend_state_t states[] = { | ||
169 | [1] = PM_SUSPEND_STANDBY, | ||
170 | [3] = PM_SUSPEND_MEM, | ||
171 | [5] = PM_SUSPEND_MAX | ||
172 | }; | ||
173 | |||
174 | if (acpi_state < 6 && states[acpi_state]) | ||
175 | return pm_suspend(states[acpi_state]); | ||
176 | if (acpi_state == 4) | ||
177 | return hibernate(); | ||
178 | return -EINVAL; | ||
179 | } | ||
180 | |||
181 | static int acpi_pm_state_valid(suspend_state_t pm_state) | 164 | static int acpi_pm_state_valid(suspend_state_t pm_state) |
182 | { | 165 | { |
183 | u32 acpi_state; | 166 | u32 acpi_state; |
@@ -202,6 +185,27 @@ static struct pm_ops acpi_pm_ops = { | |||
202 | .finish = acpi_pm_finish, | 185 | .finish = acpi_pm_finish, |
203 | }; | 186 | }; |
204 | 187 | ||
188 | /* | ||
189 | * Toshiba fails to preserve interrupts over S1, reinitialization | ||
190 | * of 8259 is needed after S1 resume. | ||
191 | */ | ||
192 | static int __init init_ints_after_s1(struct dmi_system_id *d) | ||
193 | { | ||
194 | printk(KERN_WARNING "%s with broken S1 detected.\n", d->ident); | ||
195 | init_8259A_after_S1 = 1; | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | ||
200 | { | ||
201 | .callback = init_ints_after_s1, | ||
202 | .ident = "Toshiba Satellite 4030cdt", | ||
203 | .matches = {DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),}, | ||
204 | }, | ||
205 | {}, | ||
206 | }; | ||
207 | #endif /* CONFIG_SUSPEND */ | ||
208 | |||
205 | #ifdef CONFIG_HIBERNATION | 209 | #ifdef CONFIG_HIBERNATION |
206 | static int acpi_hibernation_prepare(void) | 210 | static int acpi_hibernation_prepare(void) |
207 | { | 211 | { |
@@ -256,6 +260,21 @@ static struct hibernation_ops acpi_hibernation_ops = { | |||
256 | }; | 260 | }; |
257 | #endif /* CONFIG_HIBERNATION */ | 261 | #endif /* CONFIG_HIBERNATION */ |
258 | 262 | ||
263 | int acpi_suspend(u32 acpi_state) | ||
264 | { | ||
265 | suspend_state_t states[] = { | ||
266 | [1] = PM_SUSPEND_STANDBY, | ||
267 | [3] = PM_SUSPEND_MEM, | ||
268 | [5] = PM_SUSPEND_MAX | ||
269 | }; | ||
270 | |||
271 | if (acpi_state < 6 && states[acpi_state]) | ||
272 | return pm_suspend(states[acpi_state]); | ||
273 | if (acpi_state == 4) | ||
274 | return hibernate(); | ||
275 | return -EINVAL; | ||
276 | } | ||
277 | |||
259 | /** | 278 | /** |
260 | * acpi_pm_device_sleep_state - return preferred power state of ACPI device | 279 | * acpi_pm_device_sleep_state - return preferred power state of ACPI device |
261 | * in the system sleep state given by %acpi_target_sleep_state | 280 | * in the system sleep state given by %acpi_target_sleep_state |
@@ -331,39 +350,22 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) | |||
331 | return d_max; | 350 | return d_max; |
332 | } | 351 | } |
333 | 352 | ||
334 | /* | ||
335 | * Toshiba fails to preserve interrupts over S1, reinitialization | ||
336 | * of 8259 is needed after S1 resume. | ||
337 | */ | ||
338 | static int __init init_ints_after_s1(struct dmi_system_id *d) | ||
339 | { | ||
340 | printk(KERN_WARNING "%s with broken S1 detected.\n", d->ident); | ||
341 | init_8259A_after_S1 = 1; | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | ||
346 | { | ||
347 | .callback = init_ints_after_s1, | ||
348 | .ident = "Toshiba Satellite 4030cdt", | ||
349 | .matches = {DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),}, | ||
350 | }, | ||
351 | {}, | ||
352 | }; | ||
353 | |||
354 | int __init acpi_sleep_init(void) | 353 | int __init acpi_sleep_init(void) |
355 | { | 354 | { |
355 | acpi_status status; | ||
356 | u8 type_a, type_b; | ||
357 | #ifdef CONFIG_SUSPEND | ||
356 | int i = 0; | 358 | int i = 0; |
357 | 359 | ||
358 | dmi_check_system(acpisleep_dmi_table); | 360 | dmi_check_system(acpisleep_dmi_table); |
361 | #endif | ||
359 | 362 | ||
360 | if (acpi_disabled) | 363 | if (acpi_disabled) |
361 | return 0; | 364 | return 0; |
362 | 365 | ||
366 | #ifdef CONFIG_SUSPEND | ||
363 | printk(KERN_INFO PREFIX "(supports"); | 367 | printk(KERN_INFO PREFIX "(supports"); |
364 | for (i = 0; i < ACPI_S_STATE_COUNT; i++) { | 368 | for (i = ACPI_STATE_S0; i < ACPI_STATE_S4; i++) { |
365 | acpi_status status; | ||
366 | u8 type_a, type_b; | ||
367 | status = acpi_get_sleep_type_data(i, &type_a, &type_b); | 369 | status = acpi_get_sleep_type_data(i, &type_a, &type_b); |
368 | if (ACPI_SUCCESS(status)) { | 370 | if (ACPI_SUCCESS(status)) { |
369 | sleep_states[i] = 1; | 371 | sleep_states[i] = 1; |
@@ -373,10 +375,14 @@ int __init acpi_sleep_init(void) | |||
373 | printk(")\n"); | 375 | printk(")\n"); |
374 | 376 | ||
375 | pm_set_ops(&acpi_pm_ops); | 377 | pm_set_ops(&acpi_pm_ops); |
378 | #endif | ||
376 | 379 | ||
377 | #ifdef CONFIG_HIBERNATION | 380 | #ifdef CONFIG_HIBERNATION |
378 | if (sleep_states[ACPI_STATE_S4]) | 381 | status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b); |
382 | if (ACPI_SUCCESS(status)) { | ||
379 | hibernation_set_ops(&acpi_hibernation_ops); | 383 | hibernation_set_ops(&acpi_hibernation_ops); |
384 | sleep_states[ACPI_STATE_S4] = 1; | ||
385 | } | ||
380 | #else | 386 | #else |
381 | sleep_states[ACPI_STATE_S4] = 0; | 387 | sleep_states[ACPI_STATE_S4] = 0; |
382 | #endif | 388 | #endif |
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 1b7bbb5ba623..5dfe8b789633 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c | |||
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | ACPI_MODULE_NAME("sleep") | 25 | ACPI_MODULE_NAME("sleep") |
26 | #ifdef CONFIG_ACPI_PROCFS | 26 | #ifdef CONFIG_ACPI_PROCFS_SLEEP |
27 | static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset) | 27 | static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset) |
28 | { | 28 | { |
29 | int i; | 29 | int i; |
@@ -76,7 +76,7 @@ acpi_system_write_sleep(struct file *file, | |||
76 | Done: | 76 | Done: |
77 | return error ? error : count; | 77 | return error ? error : count; |
78 | } | 78 | } |
79 | #endif /* CONFIG_ACPI_PROCFS */ | 79 | #endif /* CONFIG_ACPI_PROCFS_SLEEP */ |
80 | 80 | ||
81 | #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) | 81 | #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) |
82 | /* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */ | 82 | /* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */ |
@@ -471,7 +471,7 @@ static const struct file_operations acpi_system_wakeup_device_fops = { | |||
471 | .release = single_release, | 471 | .release = single_release, |
472 | }; | 472 | }; |
473 | 473 | ||
474 | #ifdef CONFIG_ACPI_PROCFS | 474 | #ifdef CONFIG_ACPI_PROCFS_SLEEP |
475 | static const struct file_operations acpi_system_sleep_fops = { | 475 | static const struct file_operations acpi_system_sleep_fops = { |
476 | .open = acpi_system_sleep_open_fs, | 476 | .open = acpi_system_sleep_open_fs, |
477 | .read = seq_read, | 477 | .read = seq_read, |
@@ -479,7 +479,7 @@ static const struct file_operations acpi_system_sleep_fops = { | |||
479 | .llseek = seq_lseek, | 479 | .llseek = seq_lseek, |
480 | .release = single_release, | 480 | .release = single_release, |
481 | }; | 481 | }; |
482 | #endif /* CONFIG_ACPI_PROCFS */ | 482 | #endif /* CONFIG_ACPI_PROCFS_SLEEP */ |
483 | 483 | ||
484 | #ifdef HAVE_ACPI_LEGACY_ALARM | 484 | #ifdef HAVE_ACPI_LEGACY_ALARM |
485 | static const struct file_operations acpi_system_alarm_fops = { | 485 | static const struct file_operations acpi_system_alarm_fops = { |
@@ -506,7 +506,7 @@ static int __init acpi_sleep_proc_init(void) | |||
506 | if (acpi_disabled) | 506 | if (acpi_disabled) |
507 | return 0; | 507 | return 0; |
508 | 508 | ||
509 | #ifdef CONFIG_ACPI_PROCFS | 509 | #ifdef CONFIG_ACPI_PROCFS_SLEEP |
510 | /* 'sleep' [R/W] */ | 510 | /* 'sleep' [R/W] */ |
511 | entry = | 511 | entry = |
512 | create_proc_entry("sleep", S_IFREG | S_IRUGO | S_IWUSR, | 512 | create_proc_entry("sleep", S_IFREG | S_IRUGO | S_IWUSR, |
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h index f3e70397a7d6..ff1f8504f497 100644 --- a/drivers/acpi/sleep/sleep.h +++ b/drivers/acpi/sleep/sleep.h | |||
@@ -6,3 +6,5 @@ extern void acpi_enable_wakeup_device_prep(u8 sleep_state); | |||
6 | extern void acpi_enable_wakeup_device(u8 sleep_state); | 6 | extern void acpi_enable_wakeup_device(u8 sleep_state); |
7 | extern void acpi_disable_wakeup_device(u8 sleep_state); | 7 | extern void acpi_disable_wakeup_device(u8 sleep_state); |
8 | extern void acpi_gpe_sleep_prepare(u32 sleep_state); | 8 | extern void acpi_gpe_sleep_prepare(u32 sleep_state); |
9 | |||
10 | extern int acpi_sleep_prepare(u32 acpi_state); | ||
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index 966a5e287415..9caeaea753a3 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-y := shutdown.o | 1 | obj-y := shutdown.o |
2 | obj-$(CONFIG_PM) += main.o suspend.o resume.o sysfs.o | 2 | obj-$(CONFIG_PM_SLEEP) += main.o suspend.o resume.o sysfs.o |
3 | obj-$(CONFIG_PM_TRACE) += trace.o | 3 | obj-$(CONFIG_PM_TRACE) += trace.o |
4 | 4 | ||
5 | ifeq ($(CONFIG_DEBUG_DRIVER),y) | 5 | ifeq ($(CONFIG_DEBUG_DRIVER),y) |
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 591a0dd5deee..8ba0830cbc03 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h | |||
@@ -5,7 +5,7 @@ | |||
5 | extern void device_shutdown(void); | 5 | extern void device_shutdown(void); |
6 | 6 | ||
7 | 7 | ||
8 | #ifdef CONFIG_PM | 8 | #ifdef CONFIG_PM_SLEEP |
9 | 9 | ||
10 | /* | 10 | /* |
11 | * main.c | 11 | * main.c |
@@ -62,7 +62,7 @@ extern int resume_device(struct device *); | |||
62 | */ | 62 | */ |
63 | extern int suspend_device(struct device *, pm_message_t); | 63 | extern int suspend_device(struct device *, pm_message_t); |
64 | 64 | ||
65 | #else /* CONFIG_PM */ | 65 | #else /* CONFIG_PM_SLEEP */ |
66 | 66 | ||
67 | 67 | ||
68 | static inline int device_pm_add(struct device * dev) | 68 | static inline int device_pm_add(struct device * dev) |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 533ef40f7ccf..3d0fea235bf3 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -366,7 +366,16 @@ acpi_handle acpi_get_child(acpi_handle, acpi_integer); | |||
366 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); | 366 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); |
367 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) | 367 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) |
368 | 368 | ||
369 | #ifdef CONFIG_PM_SLEEP | ||
369 | int acpi_pm_device_sleep_state(struct device *, int, int *); | 370 | int acpi_pm_device_sleep_state(struct device *, int, int *); |
371 | #else /* !CONFIG_PM_SLEEP */ | ||
372 | static inline int acpi_pm_device_sleep_state(struct device *d, int w, int *p) | ||
373 | { | ||
374 | if (p) | ||
375 | *p = ACPI_STATE_D0; | ||
376 | return ACPI_STATE_D3; | ||
377 | } | ||
378 | #endif /* !CONFIG_PM_SLEEP */ | ||
370 | 379 | ||
371 | #endif /* CONFIG_ACPI */ | 380 | #endif /* CONFIG_ACPI */ |
372 | 381 | ||
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index f85f77a538aa..777d37ae81a2 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h | |||
@@ -147,6 +147,10 @@ static inline void unregister_hotplug_dock_device(acpi_handle handle) | |||
147 | /*-------------------------------------------------------------------------- | 147 | /*-------------------------------------------------------------------------- |
148 | Suspend/Resume | 148 | Suspend/Resume |
149 | -------------------------------------------------------------------------- */ | 149 | -------------------------------------------------------------------------- */ |
150 | #ifdef CONFIG_PM_SLEEP | ||
150 | extern int acpi_sleep_init(void); | 151 | extern int acpi_sleep_init(void); |
152 | #else | ||
153 | static inline int acpi_sleep_init(void) { return 0; } | ||
154 | #endif | ||
151 | 155 | ||
152 | #endif /*__ACPI_DRIVERS_H__*/ | 156 | #endif /*__ACPI_DRIVERS_H__*/ |
diff --git a/include/linux/freezer.h b/include/linux/freezer.h index c8e02de737f6..efded00ad08c 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
7 | 7 | ||
8 | #ifdef CONFIG_PM | 8 | #ifdef CONFIG_PM_SLEEP |
9 | /* | 9 | /* |
10 | * Check if a process has been frozen | 10 | * Check if a process has been frozen |
11 | */ | 11 | */ |
@@ -126,7 +126,7 @@ static inline void set_freezable(void) | |||
126 | current->flags &= ~PF_NOFREEZE; | 126 | current->flags &= ~PF_NOFREEZE; |
127 | } | 127 | } |
128 | 128 | ||
129 | #else | 129 | #else /* !CONFIG_PM_SLEEP */ |
130 | static inline int frozen(struct task_struct *p) { return 0; } | 130 | static inline int frozen(struct task_struct *p) { return 0; } |
131 | static inline int freezing(struct task_struct *p) { return 0; } | 131 | static inline int freezing(struct task_struct *p) { return 0; } |
132 | static inline void set_freeze_flag(struct task_struct *p) {} | 132 | static inline void set_freeze_flag(struct task_struct *p) {} |
@@ -143,6 +143,6 @@ static inline void freezer_do_not_count(void) {} | |||
143 | static inline void freezer_count(void) {} | 143 | static inline void freezer_count(void) {} |
144 | static inline int freezer_should_skip(struct task_struct *p) { return 0; } | 144 | static inline int freezer_should_skip(struct task_struct *p) { return 0; } |
145 | static inline void set_freezable(void) {} | 145 | static inline void set_freezable(void) {} |
146 | #endif | 146 | #endif /* !CONFIG_PM_SLEEP */ |
147 | 147 | ||
148 | #endif /* FREEZER_H_INCLUDED */ | 148 | #endif /* FREEZER_H_INCLUDED */ |
diff --git a/include/linux/pm.h b/include/linux/pm.h index ad3cc2eb0d34..e52f6f83c061 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -165,6 +165,7 @@ struct pm_ops { | |||
165 | int (*finish)(suspend_state_t state); | 165 | int (*finish)(suspend_state_t state); |
166 | }; | 166 | }; |
167 | 167 | ||
168 | #ifdef CONFIG_SUSPEND | ||
168 | extern struct pm_ops *pm_ops; | 169 | extern struct pm_ops *pm_ops; |
169 | 170 | ||
170 | /** | 171 | /** |
@@ -193,6 +194,12 @@ extern void arch_suspend_disable_irqs(void); | |||
193 | extern void arch_suspend_enable_irqs(void); | 194 | extern void arch_suspend_enable_irqs(void); |
194 | 195 | ||
195 | extern int pm_suspend(suspend_state_t state); | 196 | extern int pm_suspend(suspend_state_t state); |
197 | #else /* !CONFIG_SUSPEND */ | ||
198 | #define suspend_valid_only_mem NULL | ||
199 | |||
200 | static inline void pm_set_ops(struct pm_ops *pm_ops) {} | ||
201 | static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; } | ||
202 | #endif /* !CONFIG_SUSPEND */ | ||
196 | 203 | ||
197 | /* | 204 | /* |
198 | * Device power management | 205 | * Device power management |
@@ -266,7 +273,7 @@ typedef struct pm_message { | |||
266 | struct dev_pm_info { | 273 | struct dev_pm_info { |
267 | pm_message_t power_state; | 274 | pm_message_t power_state; |
268 | unsigned can_wakeup:1; | 275 | unsigned can_wakeup:1; |
269 | #ifdef CONFIG_PM | 276 | #ifdef CONFIG_PM_SLEEP |
270 | unsigned should_wakeup:1; | 277 | unsigned should_wakeup:1; |
271 | struct list_head entry; | 278 | struct list_head entry; |
272 | #endif | 279 | #endif |
@@ -276,7 +283,7 @@ extern int device_power_down(pm_message_t state); | |||
276 | extern void device_power_up(void); | 283 | extern void device_power_up(void); |
277 | extern void device_resume(void); | 284 | extern void device_resume(void); |
278 | 285 | ||
279 | #ifdef CONFIG_PM | 286 | #ifdef CONFIG_PM_SLEEP |
280 | extern int device_suspend(pm_message_t state); | 287 | extern int device_suspend(pm_message_t state); |
281 | extern int device_prepare_suspend(pm_message_t state); | 288 | extern int device_prepare_suspend(pm_message_t state); |
282 | 289 | ||
@@ -306,7 +313,7 @@ static inline int call_platform_enable_wakeup(struct device *dev, int is_on) | |||
306 | return 0; | 313 | return 0; |
307 | } | 314 | } |
308 | 315 | ||
309 | #else /* !CONFIG_PM */ | 316 | #else /* !CONFIG_PM_SLEEP */ |
310 | 317 | ||
311 | static inline int device_suspend(pm_message_t state) | 318 | static inline int device_suspend(pm_message_t state) |
312 | { | 319 | { |
@@ -323,7 +330,7 @@ static inline int call_platform_enable_wakeup(struct device *dev, int is_on) | |||
323 | return 0; | 330 | return 0; |
324 | } | 331 | } |
325 | 332 | ||
326 | #endif | 333 | #endif /* !CONFIG_PM_SLEEP */ |
327 | 334 | ||
328 | /* changes to device_may_wakeup take effect on the next pm state change. | 335 | /* changes to device_may_wakeup take effect on the next pm state change. |
329 | * by default, devices should wakeup if they can. | 336 | * by default, devices should wakeup if they can. |
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index d16c1b85d512..388cace9751f 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
@@ -24,7 +24,7 @@ struct pbe { | |||
24 | extern void drain_local_pages(void); | 24 | extern void drain_local_pages(void); |
25 | extern void mark_free_pages(struct zone *zone); | 25 | extern void mark_free_pages(struct zone *zone); |
26 | 26 | ||
27 | #if defined(CONFIG_PM) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) | 27 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) |
28 | extern int pm_prepare_console(void); | 28 | extern int pm_prepare_console(void); |
29 | extern void pm_restore_console(void); | 29 | extern void pm_restore_console(void); |
30 | #else | 30 | #else |
@@ -54,7 +54,6 @@ struct hibernation_ops { | |||
54 | void (*restore_cleanup)(void); | 54 | void (*restore_cleanup)(void); |
55 | }; | 55 | }; |
56 | 56 | ||
57 | #ifdef CONFIG_PM | ||
58 | #ifdef CONFIG_HIBERNATION | 57 | #ifdef CONFIG_HIBERNATION |
59 | /* kernel/power/snapshot.c */ | 58 | /* kernel/power/snapshot.c */ |
60 | extern void __register_nosave_region(unsigned long b, unsigned long e, int km); | 59 | extern void __register_nosave_region(unsigned long b, unsigned long e, int km); |
@@ -82,6 +81,7 @@ static inline void hibernation_set_ops(struct hibernation_ops *ops) {} | |||
82 | static inline int hibernate(void) { return -ENOSYS; } | 81 | static inline int hibernate(void) { return -ENOSYS; } |
83 | #endif /* CONFIG_HIBERNATION */ | 82 | #endif /* CONFIG_HIBERNATION */ |
84 | 83 | ||
84 | #ifdef CONFIG_PM_SLEEP | ||
85 | void save_processor_state(void); | 85 | void save_processor_state(void); |
86 | void restore_processor_state(void); | 86 | void restore_processor_state(void); |
87 | struct saved_context; | 87 | struct saved_context; |
@@ -106,7 +106,7 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) | |||
106 | { .notifier_call = fn, .priority = pri }; \ | 106 | { .notifier_call = fn, .priority = pri }; \ |
107 | register_pm_notifier(&fn##_nb); \ | 107 | register_pm_notifier(&fn##_nb); \ |
108 | } | 108 | } |
109 | #else /* CONFIG_PM */ | 109 | #else /* !CONFIG_PM_SLEEP */ |
110 | 110 | ||
111 | static inline int register_pm_notifier(struct notifier_block *nb) | 111 | static inline int register_pm_notifier(struct notifier_block *nb) |
112 | { | 112 | { |
@@ -119,9 +119,9 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) | |||
119 | } | 119 | } |
120 | 120 | ||
121 | #define pm_notifier(fn, pri) do { (void)(fn); } while (0) | 121 | #define pm_notifier(fn, pri) do { (void)(fn); } while (0) |
122 | #endif /* CONFIG_PM */ | 122 | #endif /* !CONFIG_PM_SLEEP */ |
123 | 123 | ||
124 | #if !defined CONFIG_HIBERNATION || !defined(CONFIG_PM) | 124 | #ifndef CONFIG_HIBERNATION |
125 | static inline void register_nosave_region(unsigned long b, unsigned long e) | 125 | static inline void register_nosave_region(unsigned long b, unsigned long e) |
126 | { | 126 | { |
127 | } | 127 | } |
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index c2582a4a5373..412859f8d94a 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -46,7 +46,7 @@ config PM_VERBOSE | |||
46 | 46 | ||
47 | config DISABLE_CONSOLE_SUSPEND | 47 | config DISABLE_CONSOLE_SUSPEND |
48 | bool "Keep console(s) enabled during suspend/resume (DANGEROUS)" | 48 | bool "Keep console(s) enabled during suspend/resume (DANGEROUS)" |
49 | depends on PM_DEBUG | 49 | depends on PM_DEBUG && PM_SLEEP |
50 | default n | 50 | default n |
51 | ---help--- | 51 | ---help--- |
52 | This option turns off the console suspend mechanism that prevents | 52 | This option turns off the console suspend mechanism that prevents |
@@ -57,7 +57,7 @@ config DISABLE_CONSOLE_SUSPEND | |||
57 | 57 | ||
58 | config PM_TRACE | 58 | config PM_TRACE |
59 | bool "Suspend/resume event tracing" | 59 | bool "Suspend/resume event tracing" |
60 | depends on PM_DEBUG && X86 && EXPERIMENTAL | 60 | depends on PM_DEBUG && X86 && PM_SLEEP && EXPERIMENTAL |
61 | default n | 61 | default n |
62 | ---help--- | 62 | ---help--- |
63 | This enables some cheesy code to save the last PM event point in the | 63 | This enables some cheesy code to save the last PM event point in the |
@@ -72,9 +72,37 @@ config PM_TRACE | |||
72 | CAUTION: this option will cause your machine's real-time clock to be | 72 | CAUTION: this option will cause your machine's real-time clock to be |
73 | set to an invalid time after a resume. | 73 | set to an invalid time after a resume. |
74 | 74 | ||
75 | config SUSPEND_SMP_POSSIBLE | ||
76 | bool | ||
77 | depends on (X86 && !X86_VOYAGER) || (PPC64 && (PPC_PSERIES || PPC_PMAC)) | ||
78 | depends on SMP | ||
79 | default y | ||
80 | |||
81 | config SUSPEND_SMP | ||
82 | bool | ||
83 | depends on SUSPEND_SMP_POSSIBLE && PM_SLEEP | ||
84 | select HOTPLUG_CPU | ||
85 | default y | ||
86 | |||
87 | config PM_SLEEP | ||
88 | bool | ||
89 | depends on SUSPEND || HIBERNATION | ||
90 | default y | ||
91 | |||
92 | config SUSPEND | ||
93 | bool "Suspend to RAM and standby" | ||
94 | depends on PM | ||
95 | depends on !SMP || SUSPEND_SMP_POSSIBLE | ||
96 | default y | ||
97 | ---help--- | ||
98 | Allow the system to enter sleep states in which main memory is | ||
99 | powered and thus its contents are preserved, such as the | ||
100 | suspend-to-RAM state (i.e. the ACPI S3 state). | ||
101 | |||
75 | config HIBERNATION | 102 | config HIBERNATION |
76 | bool "Hibernation" | 103 | bool "Hibernation (aka 'suspend to disk')" |
77 | depends on PM && SWAP && (((X86 || PPC64_SWSUSP) && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP)) | 104 | depends on PM && SWAP |
105 | depends on ((X86 || PPC64_SWSUSP || FRV || PPC32) && !SMP) || SUSPEND_SMP_POSSIBLE | ||
78 | ---help--- | 106 | ---help--- |
79 | Enable the suspend to disk (STD) functionality, which is usually | 107 | Enable the suspend to disk (STD) functionality, which is usually |
80 | called "hibernation" in user interfaces. STD checkpoints the | 108 | called "hibernation" in user interfaces. STD checkpoints the |
@@ -132,11 +160,6 @@ config PM_STD_PARTITION | |||
132 | suspended image to. It will simply pick the first available swap | 160 | suspended image to. It will simply pick the first available swap |
133 | device. | 161 | device. |
134 | 162 | ||
135 | config SUSPEND_SMP | ||
136 | bool | ||
137 | depends on HOTPLUG_CPU && (X86 || PPC64) && PM | ||
138 | default y | ||
139 | |||
140 | config APM_EMULATION | 163 | config APM_EMULATION |
141 | tristate "Advanced Power Management Emulation" | 164 | tristate "Advanced Power Management Emulation" |
142 | depends on PM && SYS_SUPPORTS_APM_EMULATION | 165 | depends on PM && SYS_SUPPORTS_APM_EMULATION |
diff --git a/kernel/power/Makefile b/kernel/power/Makefile index c6b03764512f..f7dfff28ecdb 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile | |||
@@ -3,8 +3,9 @@ ifeq ($(CONFIG_PM_DEBUG),y) | |||
3 | EXTRA_CFLAGS += -DDEBUG | 3 | EXTRA_CFLAGS += -DDEBUG |
4 | endif | 4 | endif |
5 | 5 | ||
6 | obj-y := main.o process.o console.o | 6 | obj-y := main.o |
7 | obj-$(CONFIG_PM_LEGACY) += pm.o | 7 | obj-$(CONFIG_PM_LEGACY) += pm.o |
8 | obj-$(CONFIG_PM_SLEEP) += process.o console.o | ||
8 | obj-$(CONFIG_HIBERNATION) += swsusp.o disk.o snapshot.o swap.o user.o | 9 | obj-$(CONFIG_HIBERNATION) += swsusp.o disk.o snapshot.o swap.o user.o |
9 | 10 | ||
10 | obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o | 11 | obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o |
diff --git a/kernel/power/main.c b/kernel/power/main.c index cfba6987ae7d..350b485b3b60 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
@@ -25,11 +25,13 @@ | |||
25 | 25 | ||
26 | BLOCKING_NOTIFIER_HEAD(pm_chain_head); | 26 | BLOCKING_NOTIFIER_HEAD(pm_chain_head); |
27 | 27 | ||
28 | /*This is just an arbitrary number */ | ||
29 | #define FREE_PAGE_NUMBER (100) | ||
30 | |||
31 | DEFINE_MUTEX(pm_mutex); | 28 | DEFINE_MUTEX(pm_mutex); |
32 | 29 | ||
30 | #ifdef CONFIG_SUSPEND | ||
31 | |||
32 | /* This is just an arbitrary number */ | ||
33 | #define FREE_PAGE_NUMBER (100) | ||
34 | |||
33 | struct pm_ops *pm_ops; | 35 | struct pm_ops *pm_ops; |
34 | 36 | ||
35 | /** | 37 | /** |
@@ -269,6 +271,8 @@ int pm_suspend(suspend_state_t state) | |||
269 | 271 | ||
270 | EXPORT_SYMBOL(pm_suspend); | 272 | EXPORT_SYMBOL(pm_suspend); |
271 | 273 | ||
274 | #endif /* CONFIG_SUSPEND */ | ||
275 | |||
272 | decl_subsys(power,NULL,NULL); | 276 | decl_subsys(power,NULL,NULL); |
273 | 277 | ||
274 | 278 | ||
@@ -285,13 +289,15 @@ decl_subsys(power,NULL,NULL); | |||
285 | 289 | ||
286 | static ssize_t state_show(struct kset *kset, char *buf) | 290 | static ssize_t state_show(struct kset *kset, char *buf) |
287 | { | 291 | { |
292 | char *s = buf; | ||
293 | #ifdef CONFIG_SUSPEND | ||
288 | int i; | 294 | int i; |
289 | char * s = buf; | ||
290 | 295 | ||
291 | for (i = 0; i < PM_SUSPEND_MAX; i++) { | 296 | for (i = 0; i < PM_SUSPEND_MAX; i++) { |
292 | if (pm_states[i] && valid_state(i)) | 297 | if (pm_states[i] && valid_state(i)) |
293 | s += sprintf(s,"%s ", pm_states[i]); | 298 | s += sprintf(s,"%s ", pm_states[i]); |
294 | } | 299 | } |
300 | #endif | ||
295 | #ifdef CONFIG_HIBERNATION | 301 | #ifdef CONFIG_HIBERNATION |
296 | s += sprintf(s, "%s\n", "disk"); | 302 | s += sprintf(s, "%s\n", "disk"); |
297 | #else | 303 | #else |
@@ -304,11 +310,13 @@ static ssize_t state_show(struct kset *kset, char *buf) | |||
304 | 310 | ||
305 | static ssize_t state_store(struct kset *kset, const char *buf, size_t n) | 311 | static ssize_t state_store(struct kset *kset, const char *buf, size_t n) |
306 | { | 312 | { |
313 | #ifdef CONFIG_SUSPEND | ||
307 | suspend_state_t state = PM_SUSPEND_STANDBY; | 314 | suspend_state_t state = PM_SUSPEND_STANDBY; |
308 | const char * const *s; | 315 | const char * const *s; |
316 | #endif | ||
309 | char *p; | 317 | char *p; |
310 | int error; | ||
311 | int len; | 318 | int len; |
319 | int error = -EINVAL; | ||
312 | 320 | ||
313 | p = memchr(buf, '\n', n); | 321 | p = memchr(buf, '\n', n); |
314 | len = p ? p - buf : n; | 322 | len = p ? p - buf : n; |
@@ -316,17 +324,19 @@ static ssize_t state_store(struct kset *kset, const char *buf, size_t n) | |||
316 | /* First, check if we are requested to hibernate */ | 324 | /* First, check if we are requested to hibernate */ |
317 | if (len == 4 && !strncmp(buf, "disk", len)) { | 325 | if (len == 4 && !strncmp(buf, "disk", len)) { |
318 | error = hibernate(); | 326 | error = hibernate(); |
319 | return error ? error : n; | 327 | goto Exit; |
320 | } | 328 | } |
321 | 329 | ||
330 | #ifdef CONFIG_SUSPEND | ||
322 | for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) { | 331 | for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) { |
323 | if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) | 332 | if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) |
324 | break; | 333 | break; |
325 | } | 334 | } |
326 | if (state < PM_SUSPEND_MAX && *s) | 335 | if (state < PM_SUSPEND_MAX && *s) |
327 | error = enter_state(state); | 336 | error = enter_state(state); |
328 | else | 337 | #endif |
329 | error = -EINVAL; | 338 | |
339 | Exit: | ||
330 | return error ? error : n; | 340 | return error ? error : n; |
331 | } | 341 | } |
332 | 342 | ||
diff --git a/kernel/power/power.h b/kernel/power/power.h index 9080914796f5..95fbf2dd3fe3 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
@@ -176,9 +176,17 @@ struct timeval; | |||
176 | extern void swsusp_show_speed(struct timeval *, struct timeval *, | 176 | extern void swsusp_show_speed(struct timeval *, struct timeval *, |
177 | unsigned int, char *); | 177 | unsigned int, char *); |
178 | 178 | ||
179 | #ifdef CONFIG_SUSPEND | ||
179 | /* kernel/power/main.c */ | 180 | /* kernel/power/main.c */ |
180 | extern int suspend_enter(suspend_state_t state); | ||
181 | extern int suspend_devices_and_enter(suspend_state_t state); | 181 | extern int suspend_devices_and_enter(suspend_state_t state); |
182 | #else /* !CONFIG_SUSPEND */ | ||
183 | static inline int suspend_devices_and_enter(suspend_state_t state) | ||
184 | { | ||
185 | return -ENOSYS; | ||
186 | } | ||
187 | #endif /* !CONFIG_SUSPEND */ | ||
188 | |||
189 | /* kernel/power/common.c */ | ||
182 | extern struct blocking_notifier_head pm_chain_head; | 190 | extern struct blocking_notifier_head pm_chain_head; |
183 | 191 | ||
184 | static inline int pm_notifier_call_chain(unsigned long val) | 192 | static inline int pm_notifier_call_chain(unsigned long val) |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6d3550ca0282..0bd4d82ddfff 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -726,7 +726,7 @@ static void __drain_pages(unsigned int cpu) | |||
726 | } | 726 | } |
727 | } | 727 | } |
728 | 728 | ||
729 | #ifdef CONFIG_PM | 729 | #ifdef CONFIG_HIBERNATION |
730 | 730 | ||
731 | void mark_free_pages(struct zone *zone) | 731 | void mark_free_pages(struct zone *zone) |
732 | { | 732 | { |
@@ -772,7 +772,7 @@ void drain_local_pages(void) | |||
772 | __drain_pages(smp_processor_id()); | 772 | __drain_pages(smp_processor_id()); |
773 | local_irq_restore(flags); | 773 | local_irq_restore(flags); |
774 | } | 774 | } |
775 | #endif /* CONFIG_PM */ | 775 | #endif /* CONFIG_HIBERNATION */ |
776 | 776 | ||
777 | /* | 777 | /* |
778 | * Free a 0-order page | 778 | * Free a 0-order page |