diff options
author | 2025-06-27 21:19:31 +0200 | |
---|---|---|
committer | 2025-07-03 17:10:40 +0200 | |
commit | ab5ce09709b5f3cc73124bd1f2d6de06c1a4b6be (patch) | |
tree | 292d8aa1f47fdb2a53fb9e49e1917758d3851be3 | |
parent | PM: runtime: Clear power.needs_force_resume in pm_runtime_reinit() (diff) | |
download | wireguard-linux-ab5ce09709b5f3cc73124bd1f2d6de06c1a4b6be.tar.xz wireguard-linux-ab5ce09709b5f3cc73124bd1f2d6de06c1a4b6be.zip |
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
-rw-r--r-- | drivers/base/power/runtime.c | 21 |
1 files changed, 8 insertions, 13 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index d863b13c2e05..f61b7fa183e0 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -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); |