diff options
Diffstat (limited to 'drivers/acpi/sleep.c')
-rw-r--r-- | drivers/acpi/sleep.c | 84 |
1 files changed, 47 insertions, 37 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 4754ff6e70e6..6c949602cbd1 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/suspend.h> | 17 | #include <linux/suspend.h> |
18 | #include <linux/reboot.h> | 18 | #include <linux/reboot.h> |
19 | #include <linux/acpi.h> | ||
19 | 20 | ||
20 | #include <asm/io.h> | 21 | #include <asm/io.h> |
21 | 22 | ||
@@ -25,7 +26,7 @@ | |||
25 | #include "internal.h" | 26 | #include "internal.h" |
26 | #include "sleep.h" | 27 | #include "sleep.h" |
27 | 28 | ||
28 | u8 sleep_states[ACPI_S_STATE_COUNT]; | 29 | static u8 sleep_states[ACPI_S_STATE_COUNT]; |
29 | 30 | ||
30 | static void acpi_sleep_tts_switch(u32 acpi_state) | 31 | static void acpi_sleep_tts_switch(u32 acpi_state) |
31 | { | 32 | { |
@@ -124,8 +125,7 @@ static int acpi_pm_freeze(void) | |||
124 | static int acpi_pm_pre_suspend(void) | 125 | static int acpi_pm_pre_suspend(void) |
125 | { | 126 | { |
126 | acpi_pm_freeze(); | 127 | acpi_pm_freeze(); |
127 | suspend_nvs_save(); | 128 | return suspend_nvs_save(); |
128 | return 0; | ||
129 | } | 129 | } |
130 | 130 | ||
131 | /** | 131 | /** |
@@ -151,7 +151,7 @@ static int acpi_pm_prepare(void) | |||
151 | { | 151 | { |
152 | int error = __acpi_pm_prepare(); | 152 | int error = __acpi_pm_prepare(); |
153 | if (!error) | 153 | if (!error) |
154 | acpi_pm_pre_suspend(); | 154 | error = acpi_pm_pre_suspend(); |
155 | 155 | ||
156 | return error; | 156 | return error; |
157 | } | 157 | } |
@@ -167,6 +167,7 @@ static void acpi_pm_finish(void) | |||
167 | u32 acpi_state = acpi_target_sleep_state; | 167 | u32 acpi_state = acpi_target_sleep_state; |
168 | 168 | ||
169 | acpi_ec_unblock_transactions(); | 169 | acpi_ec_unblock_transactions(); |
170 | suspend_nvs_free(); | ||
170 | 171 | ||
171 | if (acpi_state == ACPI_STATE_S0) | 172 | if (acpi_state == ACPI_STATE_S0) |
172 | return; | 173 | return; |
@@ -187,7 +188,6 @@ static void acpi_pm_finish(void) | |||
187 | */ | 188 | */ |
188 | static void acpi_pm_end(void) | 189 | static void acpi_pm_end(void) |
189 | { | 190 | { |
190 | suspend_nvs_free(); | ||
191 | /* | 191 | /* |
192 | * This is necessary in case acpi_pm_finish() is not called during a | 192 | * This is necessary in case acpi_pm_finish() is not called during a |
193 | * failing transition to a sleep state. | 193 | * failing transition to a sleep state. |
@@ -200,8 +200,6 @@ static void acpi_pm_end(void) | |||
200 | #endif /* CONFIG_ACPI_SLEEP */ | 200 | #endif /* CONFIG_ACPI_SLEEP */ |
201 | 201 | ||
202 | #ifdef CONFIG_SUSPEND | 202 | #ifdef CONFIG_SUSPEND |
203 | extern void do_suspend_lowlevel(void); | ||
204 | |||
205 | static u32 acpi_suspend_states[] = { | 203 | static u32 acpi_suspend_states[] = { |
206 | [PM_SUSPEND_ON] = ACPI_STATE_S0, | 204 | [PM_SUSPEND_ON] = ACPI_STATE_S0, |
207 | [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, | 205 | [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, |
@@ -244,20 +242,11 @@ static int acpi_suspend_begin(suspend_state_t pm_state) | |||
244 | static int acpi_suspend_enter(suspend_state_t pm_state) | 242 | static int acpi_suspend_enter(suspend_state_t pm_state) |
245 | { | 243 | { |
246 | acpi_status status = AE_OK; | 244 | acpi_status status = AE_OK; |
247 | unsigned long flags = 0; | ||
248 | u32 acpi_state = acpi_target_sleep_state; | 245 | u32 acpi_state = acpi_target_sleep_state; |
246 | int error; | ||
249 | 247 | ||
250 | ACPI_FLUSH_CPU_CACHE(); | 248 | ACPI_FLUSH_CPU_CACHE(); |
251 | 249 | ||
252 | /* Do arch specific saving of state. */ | ||
253 | if (acpi_state == ACPI_STATE_S3) { | ||
254 | int error = acpi_save_state_mem(); | ||
255 | |||
256 | if (error) | ||
257 | return error; | ||
258 | } | ||
259 | |||
260 | local_irq_save(flags); | ||
261 | switch (acpi_state) { | 250 | switch (acpi_state) { |
262 | case ACPI_STATE_S1: | 251 | case ACPI_STATE_S1: |
263 | barrier(); | 252 | barrier(); |
@@ -265,7 +254,10 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
265 | break; | 254 | break; |
266 | 255 | ||
267 | case ACPI_STATE_S3: | 256 | case ACPI_STATE_S3: |
268 | do_suspend_lowlevel(); | 257 | error = acpi_suspend_lowlevel(); |
258 | if (error) | ||
259 | return error; | ||
260 | pr_info(PREFIX "Low-level resume complete\n"); | ||
269 | break; | 261 | break; |
270 | } | 262 | } |
271 | 263 | ||
@@ -291,13 +283,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
291 | /* Allow EC transactions to happen. */ | 283 | /* Allow EC transactions to happen. */ |
292 | acpi_ec_unblock_transactions_early(); | 284 | acpi_ec_unblock_transactions_early(); |
293 | 285 | ||
294 | local_irq_restore(flags); | ||
295 | printk(KERN_DEBUG "Back to C!\n"); | ||
296 | |||
297 | /* restore processor state */ | ||
298 | if (acpi_state == ACPI_STATE_S3) | ||
299 | acpi_restore_state_mem(); | ||
300 | |||
301 | suspend_nvs_restore(); | 286 | suspend_nvs_restore(); |
302 | 287 | ||
303 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 288 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
@@ -319,7 +304,7 @@ static int acpi_suspend_state_valid(suspend_state_t pm_state) | |||
319 | } | 304 | } |
320 | } | 305 | } |
321 | 306 | ||
322 | static struct platform_suspend_ops acpi_suspend_ops = { | 307 | static const struct platform_suspend_ops acpi_suspend_ops = { |
323 | .valid = acpi_suspend_state_valid, | 308 | .valid = acpi_suspend_state_valid, |
324 | .begin = acpi_suspend_begin, | 309 | .begin = acpi_suspend_begin, |
325 | .prepare_late = acpi_pm_prepare, | 310 | .prepare_late = acpi_pm_prepare, |
@@ -347,7 +332,7 @@ static int acpi_suspend_begin_old(suspend_state_t pm_state) | |||
347 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has | 332 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has |
348 | * been requested. | 333 | * been requested. |
349 | */ | 334 | */ |
350 | static struct platform_suspend_ops acpi_suspend_ops_old = { | 335 | static const struct platform_suspend_ops acpi_suspend_ops_old = { |
351 | .valid = acpi_suspend_state_valid, | 336 | .valid = acpi_suspend_state_valid, |
352 | .begin = acpi_suspend_begin_old, | 337 | .begin = acpi_suspend_begin_old, |
353 | .prepare_late = acpi_pm_pre_suspend, | 338 | .prepare_late = acpi_pm_pre_suspend, |
@@ -419,6 +404,30 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
419 | DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"), | 404 | DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"), |
420 | }, | 405 | }, |
421 | }, | 406 | }, |
407 | { | ||
408 | .callback = init_nvs_nosave, | ||
409 | .ident = "Sony Vaio VPCEB1Z1E", | ||
410 | .matches = { | ||
411 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
412 | DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"), | ||
413 | }, | ||
414 | }, | ||
415 | { | ||
416 | .callback = init_nvs_nosave, | ||
417 | .ident = "Sony Vaio VGN-NW130D", | ||
418 | .matches = { | ||
419 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
420 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"), | ||
421 | }, | ||
422 | }, | ||
423 | { | ||
424 | .callback = init_nvs_nosave, | ||
425 | .ident = "Averatec AV1020-ED2", | ||
426 | .matches = { | ||
427 | DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"), | ||
428 | DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"), | ||
429 | }, | ||
430 | }, | ||
422 | {}, | 431 | {}, |
423 | }; | 432 | }; |
424 | #endif /* CONFIG_SUSPEND */ | 433 | #endif /* CONFIG_SUSPEND */ |
@@ -449,16 +458,13 @@ static int acpi_hibernation_begin(void) | |||
449 | static int acpi_hibernation_enter(void) | 458 | static int acpi_hibernation_enter(void) |
450 | { | 459 | { |
451 | acpi_status status = AE_OK; | 460 | acpi_status status = AE_OK; |
452 | unsigned long flags = 0; | ||
453 | 461 | ||
454 | ACPI_FLUSH_CPU_CACHE(); | 462 | ACPI_FLUSH_CPU_CACHE(); |
455 | 463 | ||
456 | local_irq_save(flags); | ||
457 | /* This shouldn't return. If it returns, we have a problem */ | 464 | /* This shouldn't return. If it returns, we have a problem */ |
458 | status = acpi_enter_sleep_state(ACPI_STATE_S4); | 465 | status = acpi_enter_sleep_state(ACPI_STATE_S4); |
459 | /* Reprogram control registers and execute _BFS */ | 466 | /* Reprogram control registers and execute _BFS */ |
460 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); | 467 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); |
461 | local_irq_restore(flags); | ||
462 | 468 | ||
463 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 469 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
464 | } | 470 | } |
@@ -490,7 +496,7 @@ static void acpi_pm_thaw(void) | |||
490 | acpi_enable_all_runtime_gpes(); | 496 | acpi_enable_all_runtime_gpes(); |
491 | } | 497 | } |
492 | 498 | ||
493 | static struct platform_hibernation_ops acpi_hibernation_ops = { | 499 | static const struct platform_hibernation_ops acpi_hibernation_ops = { |
494 | .begin = acpi_hibernation_begin, | 500 | .begin = acpi_hibernation_begin, |
495 | .end = acpi_pm_end, | 501 | .end = acpi_pm_end, |
496 | .pre_snapshot = acpi_pm_prepare, | 502 | .pre_snapshot = acpi_pm_prepare, |
@@ -533,7 +539,7 @@ static int acpi_hibernation_begin_old(void) | |||
533 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has | 539 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has |
534 | * been requested. | 540 | * been requested. |
535 | */ | 541 | */ |
536 | static struct platform_hibernation_ops acpi_hibernation_ops_old = { | 542 | static const struct platform_hibernation_ops acpi_hibernation_ops_old = { |
537 | .begin = acpi_hibernation_begin_old, | 543 | .begin = acpi_hibernation_begin_old, |
538 | .end = acpi_pm_end, | 544 | .end = acpi_pm_end, |
539 | .pre_snapshot = acpi_pm_pre_suspend, | 545 | .pre_snapshot = acpi_pm_pre_suspend, |
@@ -562,7 +568,7 @@ int acpi_suspend(u32 acpi_state) | |||
562 | return -EINVAL; | 568 | return -EINVAL; |
563 | } | 569 | } |
564 | 570 | ||
565 | #ifdef CONFIG_PM_SLEEP | 571 | #ifdef CONFIG_PM |
566 | /** | 572 | /** |
567 | * acpi_pm_device_sleep_state - return preferred power state of ACPI device | 573 | * acpi_pm_device_sleep_state - return preferred power state of ACPI device |
568 | * in the system sleep state given by %acpi_target_sleep_state | 574 | * in the system sleep state given by %acpi_target_sleep_state |
@@ -624,7 +630,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
624 | * can wake the system. _S0W may be valid, too. | 630 | * can wake the system. _S0W may be valid, too. |
625 | */ | 631 | */ |
626 | if (acpi_target_sleep_state == ACPI_STATE_S0 || | 632 | if (acpi_target_sleep_state == ACPI_STATE_S0 || |
627 | (device_may_wakeup(dev) && adev->wakeup.state.enabled && | 633 | (device_may_wakeup(dev) && |
628 | adev->wakeup.sleep_state <= acpi_target_sleep_state)) { | 634 | adev->wakeup.sleep_state <= acpi_target_sleep_state)) { |
629 | acpi_status status; | 635 | acpi_status status; |
630 | 636 | ||
@@ -632,7 +638,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
632 | status = acpi_evaluate_integer(handle, acpi_method, NULL, | 638 | status = acpi_evaluate_integer(handle, acpi_method, NULL, |
633 | &d_max); | 639 | &d_max); |
634 | if (ACPI_FAILURE(status)) { | 640 | if (ACPI_FAILURE(status)) { |
635 | d_max = d_min; | 641 | if (acpi_target_sleep_state != ACPI_STATE_S0 || |
642 | status != AE_NOT_FOUND) | ||
643 | d_max = d_min; | ||
636 | } else if (d_max < d_min) { | 644 | } else if (d_max < d_min) { |
637 | /* Warn the user of the broken DSDT */ | 645 | /* Warn the user of the broken DSDT */ |
638 | printk(KERN_WARNING "ACPI: Wrong value from %s\n", | 646 | printk(KERN_WARNING "ACPI: Wrong value from %s\n", |
@@ -646,7 +654,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
646 | *d_min_p = d_min; | 654 | *d_min_p = d_min; |
647 | return d_max; | 655 | return d_max; |
648 | } | 656 | } |
657 | #endif /* CONFIG_PM */ | ||
649 | 658 | ||
659 | #ifdef CONFIG_PM_SLEEP | ||
650 | /** | 660 | /** |
651 | * acpi_pm_device_sleep_wake - enable or disable the system wake-up | 661 | * acpi_pm_device_sleep_wake - enable or disable the system wake-up |
652 | * capability of given device | 662 | * capability of given device |
@@ -677,7 +687,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) | |||
677 | 687 | ||
678 | return error; | 688 | return error; |
679 | } | 689 | } |
680 | #endif | 690 | #endif /* CONFIG_PM_SLEEP */ |
681 | 691 | ||
682 | static void acpi_power_off_prepare(void) | 692 | static void acpi_power_off_prepare(void) |
683 | { | 693 | { |
@@ -702,7 +712,7 @@ static void acpi_power_off(void) | |||
702 | * paths through the BIOS, so disable _GTS and _BFS by default, | 712 | * paths through the BIOS, so disable _GTS and _BFS by default, |
703 | * but do speak up and offer the option to enable them. | 713 | * but do speak up and offer the option to enable them. |
704 | */ | 714 | */ |
705 | void __init acpi_gts_bfs_check(void) | 715 | static void __init acpi_gts_bfs_check(void) |
706 | { | 716 | { |
707 | acpi_handle dummy; | 717 | acpi_handle dummy; |
708 | 718 | ||