aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/sleep
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 /drivers/acpi/sleep
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>
Diffstat (limited to 'drivers/acpi/sleep')
-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
4 files changed, 58 insertions, 50 deletions
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);