aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/sleep/main.c
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/main.c
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/main.c')
-rw-r--r--drivers/acpi/sleep/main.c94
1 files changed, 50 insertions, 44 deletions
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