mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 02:24:24 +02:00
PM: Check power.needs_force_resume in pm_runtime_force_suspend()
Add a power.needs_force_resume check to pm_runtime_force_suspend() so it need not rely on the runtime PM status of the device when deciding whether or not to return early. With the new check in place, pm_runtime_force_suspend() will also skip devices with the runtime PM status equal to RPM_ACTIVE if they have power.needs_force_resume set, so it won't need to change the RPM status of the device to RPM_SUSPENDED in addition to setting power.needs_force_resume in the case when pm_runtime_need_not_resume() return false. That allows the runtime PM status update to be removed from pm_runtime_force_resume(), so the runtime PM status remains unchanged between the pm_runtime_force_suspend() and pm_runtime_force_resume() calls. This change potentially unbreaks drivers that call pm_runtime_force_suspend() from their ->remove() callbacks because currently, if the device being unbound from its driver has a parent with enabled runtime PM and/or (possibly) device links respecting runtime PM to suppliers, and it is RPM_ACTIVE when the remove takes place, pm_runtime_force_suspend() will not drop the parent's child count and the suppliers' runtime PM usage counters after force-suspending the device unless pm_runtime_need_not_resume() returns 'true' for it. Moreover, because pm_runtime_force_suspend() changes the device's runtime PM status to RPM_SUSPENDED, in the above case pm_runtime_reinit() will not cause those counters to drop, so they will remain nonzero forever effectively preventing the devices in question from runtime-suspending going forward. This change is also needed for pm_runtime_force_suspend() to work with PCI PM and ACPI PM after subsequent changes. Namely, say DPM_FLAG_SMART_SUSPEND is set for a PCI device and its driver uses pm_runtime_force_suspend() as its ->suspend() callback. If pm_runtime_force_suspend() changed the runtime PM status of the device to RPM_SUSPENDED, pci_pm_suspend_noirq() would skip the device due to the dev_pm_skip_suspend() check. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Link: https://patch.msgid.link/1855933.VLH7GnMWUR@rjwysocki.net
This commit is contained in:
parent
89d9cec3b1
commit
ab5ce09709
|
|
@ -1969,7 +1969,7 @@ int pm_runtime_force_suspend(struct device *dev)
|
|||
int ret;
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
if (pm_runtime_status_suspended(dev))
|
||||
if (pm_runtime_status_suspended(dev) || dev->power.needs_force_resume)
|
||||
return 0;
|
||||
|
||||
callback = RPM_GET_CALLBACK(dev, runtime_suspend);
|
||||
|
|
@ -1984,15 +1984,16 @@ int pm_runtime_force_suspend(struct device *dev)
|
|||
/*
|
||||
* If the device can stay in suspend after the system-wide transition
|
||||
* to the working state that will follow, drop the children counter of
|
||||
* its parent, but set its status to RPM_SUSPENDED anyway in case this
|
||||
* function will be called again for it in the meantime.
|
||||
* its parent and the usage counters of its suppliers. Otherwise, set
|
||||
* power.needs_force_resume to let pm_runtime_force_resume() know that
|
||||
* the device needs to be taken care of and to prevent this function
|
||||
* from handling the device again in case the device is passed to it
|
||||
* once more subsequently.
|
||||
*/
|
||||
if (pm_runtime_need_not_resume(dev)) {
|
||||
if (pm_runtime_need_not_resume(dev))
|
||||
pm_runtime_set_suspended(dev);
|
||||
} else {
|
||||
__update_runtime_status(dev, RPM_SUSPENDED);
|
||||
else
|
||||
dev->power.needs_force_resume = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -2033,12 +2034,6 @@ int pm_runtime_force_resume(struct device *dev)
|
|||
pm_runtime_status_suspended(dev)))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* The value of the parent's children counter is correct already, so
|
||||
* just update the status of the device.
|
||||
*/
|
||||
__update_runtime_status(dev, RPM_ACTIVE);
|
||||
|
||||
callback = RPM_GET_CALLBACK(dev, runtime_resume);
|
||||
|
||||
dev_pm_disable_wake_irq_check(dev, false);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user