aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2007-07-29 17:27:18 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-29 19:45:38 -0400
commit296699de6bdc717189a331ab6bbe90e05c94db06 (patch)
tree53c847ecc8cce11952502921844052e44ca60d5e
parentb0cb1a19d05b8ea8611a9ef48a17fe417f1832e6 (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/Kconfig8
-rw-r--r--drivers/acpi/sleep/Makefile2
-rw-r--r--drivers/acpi/sleep/main.c94
-rw-r--r--drivers/acpi/sleep/proc.c10
-rw-r--r--drivers/acpi/sleep/sleep.h2
-rw-r--r--drivers/base/power/Makefile2
-rw-r--r--drivers/base/power/power.h4
-rw-r--r--include/acpi/acpi_bus.h9
-rw-r--r--include/acpi/acpi_drivers.h4
-rw-r--r--include/linux/freezer.h6
-rw-r--r--include/linux/pm.h15
-rw-r--r--include/linux/suspend.h10
-rw-r--r--kernel/power/Kconfig41
-rw-r--r--kernel/power/Makefile3
-rw-r--r--kernel/power/main.c26
-rw-r--r--kernel/power/power.h10
-rw-r--r--mm/page_alloc.c4
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
66config 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
66config ACPI_AC 74config 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 @@
1obj-y := poweroff.o wakeup.o 1obj-y := poweroff.o wakeup.o
2obj-y += main.o 2obj-$(CONFIG_PM_SLEEP) += main.o
3obj-$(CONFIG_X86) += proc.o 3obj-$(CONFIG_X86) += proc.o
4 4
5EXTRA_CFLAGS += $(ACPI_CFLAGS) 5EXTRA_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
22u8 sleep_states[ACPI_S_STATE_COUNT]; 22u8 sleep_states[ACPI_S_STATE_COUNT];
23 23
24static u32 acpi_target_sleep_state = ACPI_STATE_S0;
25
26#ifdef CONFIG_SUSPEND
24static struct pm_ops acpi_pm_ops; 27static struct pm_ops acpi_pm_ops;
25 28
26extern void do_suspend_lowlevel(void); 29extern void do_suspend_lowlevel(void);
@@ -34,11 +37,6 @@ static u32 acpi_suspend_states[] = {
34 37
35static int init_8259A_after_S1; 38static int init_8259A_after_S1;
36 39
37extern int acpi_sleep_prepare(u32 acpi_state);
38extern void acpi_power_off(void);
39
40static 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
166int 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
181static int acpi_pm_state_valid(suspend_state_t pm_state) 164static 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 */
192static 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
199static 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
206static int acpi_hibernation_prepare(void) 210static 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
263int 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 */
338static 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
345static 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
354int __init acpi_sleep_init(void) 353int __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
25ACPI_MODULE_NAME("sleep") 25ACPI_MODULE_NAME("sleep")
26#ifdef CONFIG_ACPI_PROCFS 26#ifdef CONFIG_ACPI_PROCFS_SLEEP
27static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset) 27static 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
475static const struct file_operations acpi_system_sleep_fops = { 475static 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
485static const struct file_operations acpi_system_alarm_fops = { 485static 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);
6extern void acpi_enable_wakeup_device(u8 sleep_state); 6extern void acpi_enable_wakeup_device(u8 sleep_state);
7extern void acpi_disable_wakeup_device(u8 sleep_state); 7extern void acpi_disable_wakeup_device(u8 sleep_state);
8extern void acpi_gpe_sleep_prepare(u32 sleep_state); 8extern void acpi_gpe_sleep_prepare(u32 sleep_state);
9
10extern 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 @@
1obj-y := shutdown.o 1obj-y := shutdown.o
2obj-$(CONFIG_PM) += main.o suspend.o resume.o sysfs.o 2obj-$(CONFIG_PM_SLEEP) += main.o suspend.o resume.o sysfs.o
3obj-$(CONFIG_PM_TRACE) += trace.o 3obj-$(CONFIG_PM_TRACE) += trace.o
4 4
5ifeq ($(CONFIG_DEBUG_DRIVER),y) 5ifeq ($(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 @@
5extern void device_shutdown(void); 5extern 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 */
63extern int suspend_device(struct device *, pm_message_t); 63extern int suspend_device(struct device *, pm_message_t);
64 64
65#else /* CONFIG_PM */ 65#else /* CONFIG_PM_SLEEP */
66 66
67 67
68static inline int device_pm_add(struct device * dev) 68static 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);
366acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); 366acpi_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
369int acpi_pm_device_sleep_state(struct device *, int, int *); 370int acpi_pm_device_sleep_state(struct device *, int, int *);
371#else /* !CONFIG_PM_SLEEP */
372static 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
150extern int acpi_sleep_init(void); 151extern int acpi_sleep_init(void);
152#else
153static 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 */
130static inline int frozen(struct task_struct *p) { return 0; } 130static inline int frozen(struct task_struct *p) { return 0; }
131static inline int freezing(struct task_struct *p) { return 0; } 131static inline int freezing(struct task_struct *p) { return 0; }
132static inline void set_freeze_flag(struct task_struct *p) {} 132static inline void set_freeze_flag(struct task_struct *p) {}
@@ -143,6 +143,6 @@ static inline void freezer_do_not_count(void) {}
143static inline void freezer_count(void) {} 143static inline void freezer_count(void) {}
144static inline int freezer_should_skip(struct task_struct *p) { return 0; } 144static inline int freezer_should_skip(struct task_struct *p) { return 0; }
145static inline void set_freezable(void) {} 145static 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
168extern struct pm_ops *pm_ops; 169extern struct pm_ops *pm_ops;
169 170
170/** 171/**
@@ -193,6 +194,12 @@ extern void arch_suspend_disable_irqs(void);
193extern void arch_suspend_enable_irqs(void); 194extern void arch_suspend_enable_irqs(void);
194 195
195extern int pm_suspend(suspend_state_t state); 196extern int pm_suspend(suspend_state_t state);
197#else /* !CONFIG_SUSPEND */
198#define suspend_valid_only_mem NULL
199
200static inline void pm_set_ops(struct pm_ops *pm_ops) {}
201static 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 {
266struct dev_pm_info { 273struct 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);
276extern void device_power_up(void); 283extern void device_power_up(void);
277extern void device_resume(void); 284extern void device_resume(void);
278 285
279#ifdef CONFIG_PM 286#ifdef CONFIG_PM_SLEEP
280extern int device_suspend(pm_message_t state); 287extern int device_suspend(pm_message_t state);
281extern int device_prepare_suspend(pm_message_t state); 288extern 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
311static inline int device_suspend(pm_message_t state) 318static 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 {
24extern void drain_local_pages(void); 24extern void drain_local_pages(void);
25extern void mark_free_pages(struct zone *zone); 25extern 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)
28extern int pm_prepare_console(void); 28extern int pm_prepare_console(void);
29extern void pm_restore_console(void); 29extern 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 */
60extern void __register_nosave_region(unsigned long b, unsigned long e, int km); 59extern 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) {}
82static inline int hibernate(void) { return -ENOSYS; } 81static inline int hibernate(void) { return -ENOSYS; }
83#endif /* CONFIG_HIBERNATION */ 82#endif /* CONFIG_HIBERNATION */
84 83
84#ifdef CONFIG_PM_SLEEP
85void save_processor_state(void); 85void save_processor_state(void);
86void restore_processor_state(void); 86void restore_processor_state(void);
87struct saved_context; 87struct 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
111static inline int register_pm_notifier(struct notifier_block *nb) 111static 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
125static inline void register_nosave_region(unsigned long b, unsigned long e) 125static 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
47config DISABLE_CONSOLE_SUSPEND 47config 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
58config PM_TRACE 58config 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
75config SUSPEND_SMP_POSSIBLE
76 bool
77 depends on (X86 && !X86_VOYAGER) || (PPC64 && (PPC_PSERIES || PPC_PMAC))
78 depends on SMP
79 default y
80
81config SUSPEND_SMP
82 bool
83 depends on SUSPEND_SMP_POSSIBLE && PM_SLEEP
84 select HOTPLUG_CPU
85 default y
86
87config PM_SLEEP
88 bool
89 depends on SUSPEND || HIBERNATION
90 default y
91
92config 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
75config HIBERNATION 102config 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
135config SUSPEND_SMP
136 bool
137 depends on HOTPLUG_CPU && (X86 || PPC64) && PM
138 default y
139
140config APM_EMULATION 163config 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)
3EXTRA_CFLAGS += -DDEBUG 3EXTRA_CFLAGS += -DDEBUG
4endif 4endif
5 5
6obj-y := main.o process.o console.o 6obj-y := main.o
7obj-$(CONFIG_PM_LEGACY) += pm.o 7obj-$(CONFIG_PM_LEGACY) += pm.o
8obj-$(CONFIG_PM_SLEEP) += process.o console.o
8obj-$(CONFIG_HIBERNATION) += swsusp.o disk.o snapshot.o swap.o user.o 9obj-$(CONFIG_HIBERNATION) += swsusp.o disk.o snapshot.o swap.o user.o
9 10
10obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o 11obj-$(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
26BLOCKING_NOTIFIER_HEAD(pm_chain_head); 26BLOCKING_NOTIFIER_HEAD(pm_chain_head);
27 27
28/*This is just an arbitrary number */
29#define FREE_PAGE_NUMBER (100)
30
31DEFINE_MUTEX(pm_mutex); 28DEFINE_MUTEX(pm_mutex);
32 29
30#ifdef CONFIG_SUSPEND
31
32/* This is just an arbitrary number */
33#define FREE_PAGE_NUMBER (100)
34
33struct pm_ops *pm_ops; 35struct pm_ops *pm_ops;
34 36
35/** 37/**
@@ -269,6 +271,8 @@ int pm_suspend(suspend_state_t state)
269 271
270EXPORT_SYMBOL(pm_suspend); 272EXPORT_SYMBOL(pm_suspend);
271 273
274#endif /* CONFIG_SUSPEND */
275
272decl_subsys(power,NULL,NULL); 276decl_subsys(power,NULL,NULL);
273 277
274 278
@@ -285,13 +289,15 @@ decl_subsys(power,NULL,NULL);
285 289
286static ssize_t state_show(struct kset *kset, char *buf) 290static 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
305static ssize_t state_store(struct kset *kset, const char *buf, size_t n) 311static 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;
176extern void swsusp_show_speed(struct timeval *, struct timeval *, 176extern 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 */
180extern int suspend_enter(suspend_state_t state);
181extern int suspend_devices_and_enter(suspend_state_t state); 181extern int suspend_devices_and_enter(suspend_state_t state);
182#else /* !CONFIG_SUSPEND */
183static 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 */
182extern struct blocking_notifier_head pm_chain_head; 190extern struct blocking_notifier_head pm_chain_head;
183 191
184static inline int pm_notifier_call_chain(unsigned long val) 192static 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
731void mark_free_pages(struct zone *zone) 731void 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