diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2010-10-14 23:24:13 +0200 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-10-15 16:25:15 -0400 |
commit | 761afb869f649ea23e2dea7bfe9b550d3a1b7631 (patch) | |
tree | 816a6eb04802b1befedaf07f9c1359dd4dc7a9f6 /drivers/acpi/sleep.c | |
parent | cd07202cc8262e1669edff0d97715f3dd9260917 (diff) | |
download | linux-761afb869f649ea23e2dea7bfe9b550d3a1b7631.tar.bz2 |
ACPI / PM: Fix problems with acpi_pm_device_sleep_state()
There is a number of problems with acpi_pm_device_sleep_state() now.
First, if _S0W is not defined, it prevents devices from being put
into D3 by PCI runtime PM, which shouldn't happen. Second, it
shouldn't use adev->wakeup.state.enabled, because if it's set, it
only means that either the device is permanently enabled to wake up
the system, or that it has been enabled to do that through
/proc/acpi/wakeup. Finally, it should be compiled if CONFIG_PM_SLEEP
is not set, so that PCI runtime PM works correctly in that case.
Fix these problems.
Reported-by: Matthew Garrett <mjg59@srcf.ucam.org>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/sleep.c')
-rw-r--r-- | drivers/acpi/sleep.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 4754ff6e70e6..e807f4196f89 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -27,6 +27,8 @@ u8 sleep_states[ACPI_S_STATE_COUNT]; +static u32 acpi_target_sleep_state = ACPI_STATE_S0; + static void acpi_sleep_tts_switch(u32 acpi_state) { union acpi_object in_arg = { ACPI_TYPE_INTEGER }; @@ -79,8 +81,6 @@ static int acpi_sleep_prepare(u32 acpi_state) } #ifdef CONFIG_ACPI_SLEEP -static u32 acpi_target_sleep_state = ACPI_STATE_S0; - /* * The ACPI specification wants us to save NVS memory regions during hibernation * and to restore them during the subsequent resume. Windows does that also for @@ -562,7 +562,7 @@ int acpi_suspend(u32 acpi_state) return -EINVAL; } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM_OPS /** * acpi_pm_device_sleep_state - return preferred power state of ACPI device * in the system sleep state given by %acpi_target_sleep_state @@ -624,7 +624,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) * can wake the system. _S0W may be valid, too. */ if (acpi_target_sleep_state == ACPI_STATE_S0 || - (device_may_wakeup(dev) && adev->wakeup.state.enabled && + (device_may_wakeup(dev) && adev->wakeup.sleep_state <= acpi_target_sleep_state)) { acpi_status status; @@ -632,7 +632,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) status = acpi_evaluate_integer(handle, acpi_method, NULL, &d_max); if (ACPI_FAILURE(status)) { - d_max = d_min; + if (acpi_target_sleep_state != ACPI_STATE_S0 || + status != AE_NOT_FOUND) + d_max = d_min; } else if (d_max < d_min) { /* Warn the user of the broken DSDT */ printk(KERN_WARNING "ACPI: Wrong value from %s\n", @@ -646,7 +648,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) *d_min_p = d_min; return d_max; } +#endif /* CONFIG_PM_OPS */ +#ifdef CONFIG_PM_SLEEP /** * acpi_pm_device_sleep_wake - enable or disable the system wake-up * capability of given device @@ -677,7 +681,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) return error; } -#endif +#endif /* CONFIG_PM_SLEEP */ static void acpi_power_off_prepare(void) { |