Skip to content

Commit b88ff47

Browse files
committed
PM: Check power.needs_force_resume in pm_runtime_force_suspend()
JIRA: https://issues.redhat.com/browse/RHEL-109251 commit ab5ce09 Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Date: Thu, 03 Jul 2025 17:10:40 +0000 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 Signed-off-by: Mark Langsdorf <mlangsdo@redhat.com>
1 parent c255141 commit b88ff47

File tree

1 file changed

+8
-13
lines changed

1 file changed

+8
-13
lines changed

drivers/base/power/runtime.c

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1969,7 +1969,7 @@ int pm_runtime_force_suspend(struct device *dev)
19691969
int ret;
19701970

19711971
pm_runtime_disable(dev);
1972-
if (pm_runtime_status_suspended(dev))
1972+
if (pm_runtime_status_suspended(dev) || dev->power.needs_force_resume)
19731973
return 0;
19741974

19751975
callback = RPM_GET_CALLBACK(dev, runtime_suspend);
@@ -1984,15 +1984,16 @@ int pm_runtime_force_suspend(struct device *dev)
19841984
/*
19851985
* If the device can stay in suspend after the system-wide transition
19861986
* to the working state that will follow, drop the children counter of
1987-
* its parent, but set its status to RPM_SUSPENDED anyway in case this
1988-
* function will be called again for it in the meantime.
1987+
* its parent and the usage counters of its suppliers. Otherwise, set
1988+
* power.needs_force_resume to let pm_runtime_force_resume() know that
1989+
* the device needs to be taken care of and to prevent this function
1990+
* from handling the device again in case the device is passed to it
1991+
* once more subsequently.
19891992
*/
1990-
if (pm_runtime_need_not_resume(dev)) {
1993+
if (pm_runtime_need_not_resume(dev))
19911994
pm_runtime_set_suspended(dev);
1992-
} else {
1993-
__update_runtime_status(dev, RPM_SUSPENDED);
1995+
else
19941996
dev->power.needs_force_resume = true;
1995-
}
19961997

19971998
return 0;
19981999

@@ -2033,12 +2034,6 @@ int pm_runtime_force_resume(struct device *dev)
20332034
pm_runtime_status_suspended(dev)))
20342035
goto out;
20352036

2036-
/*
2037-
* The value of the parent's children counter is correct already, so
2038-
* just update the status of the device.
2039-
*/
2040-
__update_runtime_status(dev, RPM_ACTIVE);
2041-
20422037
callback = RPM_GET_CALLBACK(dev, runtime_resume);
20432038

20442039
dev_pm_disable_wake_irq_check(dev, false);

0 commit comments

Comments
 (0)