diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/acpi/sleep.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/acpi/sleep.c')
-rw-r--r-- | drivers/acpi/sleep.c | 119 |
1 files changed, 99 insertions, 20 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 5f2c379ab7bf..baa76bbf244a 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -81,6 +81,23 @@ static int acpi_sleep_prepare(u32 acpi_state) | |||
81 | #ifdef CONFIG_ACPI_SLEEP | 81 | #ifdef CONFIG_ACPI_SLEEP |
82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | 82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; |
83 | /* | 83 | /* |
84 | * According to the ACPI specification the BIOS should make sure that ACPI is | ||
85 | * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, | ||
86 | * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI | ||
87 | * on such systems during resume. Unfortunately that doesn't help in | ||
88 | * particularly pathological cases in which SCI_EN has to be set directly on | ||
89 | * resume, although the specification states very clearly that this flag is | ||
90 | * owned by the hardware. The set_sci_en_on_resume variable will be set in such | ||
91 | * cases. | ||
92 | */ | ||
93 | static bool set_sci_en_on_resume; | ||
94 | |||
95 | void __init acpi_set_sci_en_on_resume(void) | ||
96 | { | ||
97 | set_sci_en_on_resume = true; | ||
98 | } | ||
99 | |||
100 | /* | ||
84 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the | 101 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the |
85 | * user to request that behavior by using the 'acpi_old_suspend_ordering' | 102 | * user to request that behavior by using the 'acpi_old_suspend_ordering' |
86 | * kernel command line option that causes the following variable to be set. | 103 | * kernel command line option that causes the following variable to be set. |
@@ -170,18 +187,6 @@ static void acpi_pm_end(void) | |||
170 | #endif /* CONFIG_ACPI_SLEEP */ | 187 | #endif /* CONFIG_ACPI_SLEEP */ |
171 | 188 | ||
172 | #ifdef CONFIG_SUSPEND | 189 | #ifdef CONFIG_SUSPEND |
173 | /* | ||
174 | * According to the ACPI specification the BIOS should make sure that ACPI is | ||
175 | * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, | ||
176 | * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI | ||
177 | * on such systems during resume. Unfortunately that doesn't help in | ||
178 | * particularly pathological cases in which SCI_EN has to be set directly on | ||
179 | * resume, although the specification states very clearly that this flag is | ||
180 | * owned by the hardware. The set_sci_en_on_resume variable will be set in such | ||
181 | * cases. | ||
182 | */ | ||
183 | static bool set_sci_en_on_resume; | ||
184 | |||
185 | extern void do_suspend_lowlevel(void); | 190 | extern void do_suspend_lowlevel(void); |
186 | 191 | ||
187 | static u32 acpi_suspend_states[] = { | 192 | static u32 acpi_suspend_states[] = { |
@@ -445,6 +450,38 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
445 | }, | 450 | }, |
446 | }, | 451 | }, |
447 | { | 452 | { |
453 | .callback = init_set_sci_en_on_resume, | ||
454 | .ident = "Lenovo ThinkPad T410", | ||
455 | .matches = { | ||
456 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
457 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T410"), | ||
458 | }, | ||
459 | }, | ||
460 | { | ||
461 | .callback = init_set_sci_en_on_resume, | ||
462 | .ident = "Lenovo ThinkPad T510", | ||
463 | .matches = { | ||
464 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
465 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T510"), | ||
466 | }, | ||
467 | }, | ||
468 | { | ||
469 | .callback = init_set_sci_en_on_resume, | ||
470 | .ident = "Lenovo ThinkPad W510", | ||
471 | .matches = { | ||
472 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
473 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W510"), | ||
474 | }, | ||
475 | }, | ||
476 | { | ||
477 | .callback = init_set_sci_en_on_resume, | ||
478 | .ident = "Lenovo ThinkPad X201[s]", | ||
479 | .matches = { | ||
480 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
481 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201"), | ||
482 | }, | ||
483 | }, | ||
484 | { | ||
448 | .callback = init_old_suspend_ordering, | 485 | .callback = init_old_suspend_ordering, |
449 | .ident = "Panasonic CF51-2L", | 486 | .ident = "Panasonic CF51-2L", |
450 | .matches = { | 487 | .matches = { |
@@ -453,6 +490,30 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
453 | DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), | 490 | DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), |
454 | }, | 491 | }, |
455 | }, | 492 | }, |
493 | { | ||
494 | .callback = init_set_sci_en_on_resume, | ||
495 | .ident = "Dell Studio 1558", | ||
496 | .matches = { | ||
497 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
498 | DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1558"), | ||
499 | }, | ||
500 | }, | ||
501 | { | ||
502 | .callback = init_set_sci_en_on_resume, | ||
503 | .ident = "Dell Studio 1557", | ||
504 | .matches = { | ||
505 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
506 | DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"), | ||
507 | }, | ||
508 | }, | ||
509 | { | ||
510 | .callback = init_set_sci_en_on_resume, | ||
511 | .ident = "Dell Studio 1555", | ||
512 | .matches = { | ||
513 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
514 | DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1555"), | ||
515 | }, | ||
516 | }, | ||
456 | {}, | 517 | {}, |
457 | }; | 518 | }; |
458 | #endif /* CONFIG_SUSPEND */ | 519 | #endif /* CONFIG_SUSPEND */ |
@@ -547,8 +608,17 @@ static void acpi_hibernation_leave(void) | |||
547 | hibernate_nvs_restore(); | 608 | hibernate_nvs_restore(); |
548 | } | 609 | } |
549 | 610 | ||
550 | static void acpi_pm_enable_gpes(void) | 611 | static int acpi_pm_pre_restore(void) |
551 | { | 612 | { |
613 | acpi_disable_all_gpes(); | ||
614 | acpi_os_wait_events_complete(NULL); | ||
615 | acpi_ec_suspend_transactions(); | ||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | static void acpi_pm_restore_cleanup(void) | ||
620 | { | ||
621 | acpi_ec_resume_transactions(); | ||
552 | acpi_enable_all_runtime_gpes(); | 622 | acpi_enable_all_runtime_gpes(); |
553 | } | 623 | } |
554 | 624 | ||
@@ -560,8 +630,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops = { | |||
560 | .prepare = acpi_pm_prepare, | 630 | .prepare = acpi_pm_prepare, |
561 | .enter = acpi_hibernation_enter, | 631 | .enter = acpi_hibernation_enter, |
562 | .leave = acpi_hibernation_leave, | 632 | .leave = acpi_hibernation_leave, |
563 | .pre_restore = acpi_pm_disable_gpes, | 633 | .pre_restore = acpi_pm_pre_restore, |
564 | .restore_cleanup = acpi_pm_enable_gpes, | 634 | .restore_cleanup = acpi_pm_restore_cleanup, |
565 | }; | 635 | }; |
566 | 636 | ||
567 | /** | 637 | /** |
@@ -613,8 +683,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = { | |||
613 | .prepare = acpi_pm_disable_gpes, | 683 | .prepare = acpi_pm_disable_gpes, |
614 | .enter = acpi_hibernation_enter, | 684 | .enter = acpi_hibernation_enter, |
615 | .leave = acpi_hibernation_leave, | 685 | .leave = acpi_hibernation_leave, |
616 | .pre_restore = acpi_pm_disable_gpes, | 686 | .pre_restore = acpi_pm_pre_restore, |
617 | .restore_cleanup = acpi_pm_enable_gpes, | 687 | .restore_cleanup = acpi_pm_restore_cleanup, |
618 | .recover = acpi_pm_finish, | 688 | .recover = acpi_pm_finish, |
619 | }; | 689 | }; |
620 | #endif /* CONFIG_HIBERNATION */ | 690 | #endif /* CONFIG_HIBERNATION */ |
@@ -740,9 +810,18 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) | |||
740 | return -ENODEV; | 810 | return -ENODEV; |
741 | } | 811 | } |
742 | 812 | ||
743 | error = enable ? | 813 | if (enable) { |
744 | acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) : | 814 | error = acpi_enable_wakeup_device_power(adev, |
745 | acpi_disable_wakeup_device_power(adev); | 815 | acpi_target_sleep_state); |
816 | if (!error) | ||
817 | acpi_enable_gpe(adev->wakeup.gpe_device, | ||
818 | adev->wakeup.gpe_number, | ||
819 | ACPI_GPE_TYPE_WAKE); | ||
820 | } else { | ||
821 | acpi_disable_gpe(adev->wakeup.gpe_device, adev->wakeup.gpe_number, | ||
822 | ACPI_GPE_TYPE_WAKE); | ||
823 | error = acpi_disable_wakeup_device_power(adev); | ||
824 | } | ||
746 | if (!error) | 825 | if (!error) |
747 | dev_info(dev, "wake-up capability %s by ACPI\n", | 826 | dev_info(dev, "wake-up capability %s by ACPI\n", |
748 | enable ? "enabled" : "disabled"); | 827 | enable ? "enabled" : "disabled"); |