Skip to content

Commit 28276b2

Browse files
committed
PM: Make pm_runtime_force_resume() work with DPM_FLAG_SMART_SUSPEND
JIRA: https://issues.redhat.com/browse/RHEL-109251 commit e21bd84 Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Date: Thu, 03 Jul 2025 17:10:40 +0000 Curently, drivers using pm_runtime_force_suspend/resume() cannot set DPM_FLAG_SMART_SUSPEND because the devices with that flag set may need to be resumed during system-wide resume regardless of whether or not they have power.needs_force_resume set. That can happen due to a dependency resolved at the beginning of a system-wide resume transition (for instance, a bus type or PM domain has decided to resume a subordinate device with DPM_FLAG_SMART_SUSPEND and its parent and suppliers also need to be resumed). To overcome this limitation, modify pm_runtime_force_resume() to check the device's power.smart_suspend flag (which is set for devices with DPM_FLAG_SMART_SUSPEND set that meet some additional requirements) and the device's runtime PM status in addition to power.needs_force_resume. Also change it to clear power.smart_suspend to ensure that it will not handle the same device twice during one transition. The underlying observation is that there are two cases in which the device needs to be resumed by pm_runtime_force_resume(). One of them is when the device has power.needs_force_resume set, which means that pm_runtime_force_suspend() has suspended it and decided that it should be resumed during the subsequent system resume. The other one is when power.smart_suspend is set and the device's runtume PM status is RPM_ACTIVE. Update kerneldoc comments in accordance with the code changes. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Link: https://patch.msgid.link/3662906.iIbC2pHGDl@rjwysocki.net Signed-off-by: Mark Langsdorf <mlangsdo@redhat.com>
1 parent 9ec17c7 commit 28276b2

File tree

1 file changed

+27
-11
lines changed

1 file changed

+27
-11
lines changed

drivers/base/power/runtime.c

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,10 +1957,6 @@ void pm_runtime_drop_link(struct device_link *link)
19571957
* sure the device is put into low power state and it should only be used during
19581958
* system-wide PM transitions to sleep states. It assumes that the analogous
19591959
* pm_runtime_force_resume() will be used to resume the device.
1960-
*
1961-
* Do not use with DPM_FLAG_SMART_SUSPEND as this can lead to an inconsistent
1962-
* state where this function has called the ->runtime_suspend callback but the
1963-
* PM core marks the driver as runtime active.
19641960
*/
19651961
int pm_runtime_force_suspend(struct device *dev)
19661962
{
@@ -2008,20 +2004,28 @@ EXPORT_SYMBOL_GPL(pm_runtime_force_suspend);
20082004
* pm_runtime_force_resume - Force a device into resume state if needed.
20092005
* @dev: Device to resume.
20102006
*
2011-
* Prior invoking this function we expect the user to have brought the device
2012-
* into low power state by a call to pm_runtime_force_suspend(). Here we reverse
2013-
* those actions and bring the device into full power, if it is expected to be
2014-
* used on system resume. In the other case, we defer the resume to be managed
2015-
* via runtime PM.
2007+
* This function expects that either pm_runtime_force_suspend() has put the
2008+
* device into a low-power state prior to calling it, or the device had been
2009+
* runtime-suspended before the preceding system-wide suspend transition and it
2010+
* was left in suspend during that transition.
2011+
*
2012+
* The actions carried out by pm_runtime_force_suspend(), or by a runtime
2013+
* suspend in general, are reversed and the device is brought back into full
2014+
* power if it is expected to be used on system resume, which is the case when
2015+
* its needs_force_resume flag is set or when its smart_suspend flag is set and
2016+
* its runtime PM status is "active".
2017+
*
2018+
* In other cases, the resume is deferred to be managed via runtime PM.
20162019
*
2017-
* Typically this function may be invoked from a system resume callback.
2020+
* Typically, this function may be invoked from a system resume callback.
20182021
*/
20192022
int pm_runtime_force_resume(struct device *dev)
20202023
{
20212024
int (*callback)(struct device *);
20222025
int ret = 0;
20232026

2024-
if (!dev->power.needs_force_resume)
2027+
if (!dev->power.needs_force_resume && (!dev_pm_smart_suspend(dev) ||
2028+
pm_runtime_status_suspended(dev)))
20252029
goto out;
20262030

20272031
/*
@@ -2041,8 +2045,20 @@ int pm_runtime_force_resume(struct device *dev)
20412045
}
20422046

20432047
pm_runtime_mark_last_busy(dev);
2048+
20442049
out:
2050+
/*
2051+
* The smart_suspend flag can be cleared here because it is not going
2052+
* to be necessary until the next system-wide suspend transition that
2053+
* will update it again.
2054+
*/
2055+
dev->power.smart_suspend = false;
2056+
/*
2057+
* Also clear needs_force_resume to make this function skip devices that
2058+
* have been seen by it once.
2059+
*/
20452060
dev->power.needs_force_resume = false;
2061+
20462062
pm_runtime_enable(dev);
20472063
return ret;
20482064
}

0 commit comments

Comments
 (0)