PM / sleep: Avoid excess pm_runtime_enable() calls in device_resume()
Middle-layer code doing suspend-time optimizations for devices with the DPM_FLAG_SMART_SUSPEND flag set (currently, the PCI bus type and the ACPI PM domain) needs to make the core skip ->thaw_early and ->thaw callbacks for those devices in some cases and it sets the power.direct_complete flag for them for this purpose. However, it turns out that setting power.direct_complete outside of the PM core is a bad idea as it triggers an excess invocation of pm_runtime_enable() in device_resume(). For this reason, provide a helper to clear power.is_late_suspended and power.is_suspended to be invoked by the middle-layer code in question instead of setting power.direct_complete and make that code call the new helper. Fixes:c4b65157ae
(PCI / PM: Take SMART_SUSPEND driver flag into account) Fixes:05087360fd
(ACPI / PM: Take SMART_SUSPEND driver flag into account) Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
This commit is contained in:
Родитель
50c4c4e268
Коммит
3487972d7f
|
@ -1138,7 +1138,7 @@ int acpi_subsys_thaw_noirq(struct device *dev)
|
|||
* skip all of the subsequent "thaw" callbacks for the device.
|
||||
*/
|
||||
if (dev_pm_smart_suspend_and_suspended(dev)) {
|
||||
dev->power.direct_complete = true;
|
||||
dev_pm_skip_next_resume_phases(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -525,6 +525,21 @@ static void dpm_watchdog_clear(struct dpm_watchdog *wd)
|
|||
|
||||
/*------------------------- Resume routines -------------------------*/
|
||||
|
||||
/**
|
||||
* dev_pm_skip_next_resume_phases - Skip next system resume phases for device.
|
||||
* @dev: Target device.
|
||||
*
|
||||
* Make the core skip the "early resume" and "resume" phases for @dev.
|
||||
*
|
||||
* This function can be called by middle-layer code during the "noirq" phase of
|
||||
* system resume if necessary, but not by device drivers.
|
||||
*/
|
||||
void dev_pm_skip_next_resume_phases(struct device *dev)
|
||||
{
|
||||
dev->power.is_late_suspended = false;
|
||||
dev->power.is_suspended = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* device_resume_noirq - Execute a "noirq resume" callback for given device.
|
||||
* @dev: Device to handle.
|
||||
|
|
|
@ -999,7 +999,7 @@ static int pci_pm_thaw_noirq(struct device *dev)
|
|||
* the subsequent "thaw" callbacks for the device.
|
||||
*/
|
||||
if (dev_pm_smart_suspend_and_suspended(dev)) {
|
||||
dev->power.direct_complete = true;
|
||||
dev_pm_skip_next_resume_phases(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -765,6 +765,7 @@ extern int pm_generic_poweroff_late(struct device *dev);
|
|||
extern int pm_generic_poweroff(struct device *dev);
|
||||
extern void pm_generic_complete(struct device *dev);
|
||||
|
||||
extern void dev_pm_skip_next_resume_phases(struct device *dev);
|
||||
extern bool dev_pm_smart_suspend_and_suspended(struct device *dev);
|
||||
|
||||
#else /* !CONFIG_PM_SLEEP */
|
||||
|
|
Загрузка…
Ссылка в новой задаче