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>
This commit is contained in:
committed by
Len Brown
parent
cd07202cc8
commit
761afb869f
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
u8 sleep_states[ACPI_S_STATE_COUNT];
|
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)
|
static void acpi_sleep_tts_switch(u32 acpi_state)
|
||||||
{
|
{
|
||||||
union acpi_object in_arg = { ACPI_TYPE_INTEGER };
|
union acpi_object in_arg = { ACPI_TYPE_INTEGER };
|
||||||
@@ -79,8 +81,6 @@ static int acpi_sleep_prepare(u32 acpi_state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI_SLEEP
|
#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
|
* 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
|
* 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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_OPS
|
||||||
/**
|
/**
|
||||||
* acpi_pm_device_sleep_state - return preferred power state of ACPI device
|
* acpi_pm_device_sleep_state - return preferred power state of ACPI device
|
||||||
* in the system sleep state given by %acpi_target_sleep_state
|
* 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.
|
* can wake the system. _S0W may be valid, too.
|
||||||
*/
|
*/
|
||||||
if (acpi_target_sleep_state == ACPI_STATE_S0 ||
|
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)) {
|
adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
|
||||||
acpi_status status;
|
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,
|
status = acpi_evaluate_integer(handle, acpi_method, NULL,
|
||||||
&d_max);
|
&d_max);
|
||||||
if (ACPI_FAILURE(status)) {
|
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) {
|
} else if (d_max < d_min) {
|
||||||
/* Warn the user of the broken DSDT */
|
/* Warn the user of the broken DSDT */
|
||||||
printk(KERN_WARNING "ACPI: Wrong value from %s\n",
|
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;
|
*d_min_p = d_min;
|
||||||
return d_max;
|
return d_max;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_PM_OPS */
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
/**
|
/**
|
||||||
* acpi_pm_device_sleep_wake - enable or disable the system wake-up
|
* acpi_pm_device_sleep_wake - enable or disable the system wake-up
|
||||||
* capability of given device
|
* capability of given device
|
||||||
@@ -677,7 +681,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
|
|||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
static void acpi_power_off_prepare(void)
|
static void acpi_power_off_prepare(void)
|
||||||
{
|
{
|
||||||
|
@@ -389,21 +389,25 @@ struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
|
|||||||
int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
|
int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
|
||||||
int acpi_disable_wakeup_device_power(struct acpi_device *dev);
|
int acpi_disable_wakeup_device_power(struct acpi_device *dev);
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_OPS
|
||||||
int acpi_pm_device_sleep_state(struct device *, int *);
|
int acpi_pm_device_sleep_state(struct device *, int *);
|
||||||
int acpi_pm_device_sleep_wake(struct device *, bool);
|
#else
|
||||||
#else /* !CONFIG_PM_SLEEP */
|
|
||||||
static inline int acpi_pm_device_sleep_state(struct device *d, int *p)
|
static inline int acpi_pm_device_sleep_state(struct device *d, int *p)
|
||||||
{
|
{
|
||||||
if (p)
|
if (p)
|
||||||
*p = ACPI_STATE_D0;
|
*p = ACPI_STATE_D0;
|
||||||
return ACPI_STATE_D3;
|
return ACPI_STATE_D3;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
int acpi_pm_device_sleep_wake(struct device *, bool);
|
||||||
|
#else
|
||||||
static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
|
static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
#endif /* !CONFIG_PM_SLEEP */
|
#endif
|
||||||
|
|
||||||
#endif /* CONFIG_ACPI */
|
#endif /* CONFIG_ACPI */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user