From 258e231dc29fbd72bc82c16859a8304f71780ba2 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 17 Feb 2025 21:03:01 +0100 Subject: PM: Rearrange documentation related to __pm_runtime_disable() There are only two callers of __pm_runtime_disable(), one of which is device_suspend_late() and the other is pm_runtime_disable() that has its own kerneldoc comment and there are no plans to add any more of them. Since they use different values of the __pm_runtime_disable() second parameter, the actual code behavior is different in each case, but it is all documented in the __pm_runtime_disable() kerneldoc comment which is not particularly straightforward. For this reason, move the information from the __pm_runtime_disable() kerneldoc comment to the pm_runtime_disable() one and into a separate comment in device_suspend_late() and remove the __pm_runtime_disable() kerneldoc comment altogether. No functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Ulf Hansson Link: https://patch.msgid.link/12617588.O9o76ZdvQC@rjwysocki.net --- drivers/base/power/main.c | 4 ++++ drivers/base/power/runtime.c | 14 -------------- 2 files changed, 4 insertions(+), 14 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 40e1d8d8a589..dffa2aa1ba7d 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1404,6 +1404,10 @@ static int device_suspend_late(struct device *dev, pm_message_t state, bool asyn TRACE_DEVICE(dev); TRACE_SUSPEND(0); + /* + * Disable runtime PM for the device without checking if there is a + * pending resume request for it. + */ __pm_runtime_disable(dev, false); dpm_wait_for_subordinate(dev, async); diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 2ee45841486b..a5aed89e1a6b 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1460,20 +1460,6 @@ int pm_runtime_barrier(struct device *dev) } EXPORT_SYMBOL_GPL(pm_runtime_barrier); -/** - * __pm_runtime_disable - Disable runtime PM of a device. - * @dev: Device to handle. - * @check_resume: If set, check if there's a resume request for the device. - * - * Increment power.disable_depth for the device and if it was zero previously, - * cancel all pending runtime PM requests for the device and wait for all - * operations in progress to complete. The device can be either active or - * suspended after its runtime PM has been disabled. - * - * If @check_resume is set and there's a resume request pending when - * __pm_runtime_disable() is called and power.disable_depth is zero, the - * function will wake up the device before disabling its runtime PM. - */ void __pm_runtime_disable(struct device *dev, bool check_resume) { spin_lock_irq(&dev->power.lock); -- cgit From d2677d57d4b8ec63da8f51357bcf855c4cf47c78 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 27 Feb 2025 11:56:12 +0100 Subject: PM: runtime: Drop status check from pm_runtime_force_resume() Since pm_runtime_force_resume() requires pm_runtime_force_suspend() to be called before it on the same device, the runtime PM status of the device is RPM_SUSPENDED when it is called unless the device's runtime PM status is changed somewhere else in the meantime. However, even if that happens, the power.needs_force_resume check is still required to pass and that flag is only set by pm_runtime_force_suspend() once and it is cleared at the end of pm_runtime_force_resume(), so it cannot be taken into account twice in a row. According to the above, the pm_runtime_status_suspended(dev) check in pm_runtime_force_resume() is redundant, so drop it. Signed-off-by: Rafael J. Wysocki Reviewed-by: Ulf Hansson Link: https://patch.msgid.link/2309120.iZASKD2KPV@rjwysocki.net --- drivers/base/power/runtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index a5aed89e1a6b..1714358b541e 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1945,7 +1945,7 @@ int pm_runtime_force_resume(struct device *dev) int (*callback)(struct device *); int ret = 0; - if (!pm_runtime_status_suspended(dev) || !dev->power.needs_force_resume) + if (!dev->power.needs_force_resume) goto out; /* -- cgit From 72263869656d09a5f9727504bb1f3cb7b010f0e5 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 25 Feb 2025 18:06:18 +0100 Subject: PM: runtime: Unify error handling during suspend and resume There is a confusing difference in error handling between rpm_suspend() and rpm_resume() related to the special way in which -EAGAIN and -EBUSY error values are treated by the former. Also, converting -EACCES coming from the callback to I/O error, which it quite likely is not, may confuse runtime PM users. To address the above, modify rpm_callback() to convert -EACCES coming from the driver to -EAGAIN and to set power.runtime_error only if the return value is not -EAGAIN or -EBUSY. This will cause the error handling in rpm_resume() and rpm_suspend() to work consistently, so drop the no longer needed -EAGAIN or -EBUSY special case from the latter and make it retry autosuspend if power.runtime_error is unset. Signed-off-by: Rafael J. Wysocki Reviewed-by: Ulf Hansson Link: https://patch.msgid.link/12620037.O9o76ZdvQC@rjwysocki.net --- drivers/base/power/runtime.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 1714358b541e..da74e1c69f7a 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -448,8 +448,19 @@ static int rpm_callback(int (*cb)(struct device *), struct device *dev) retval = __rpm_callback(cb, dev); } - dev->power.runtime_error = retval; - return retval != -EACCES ? retval : -EIO; + /* + * Since -EACCES means that runtime PM is disabled for the given device, + * it should not be returned by runtime PM callbacks. If it is returned + * nevertheless, assume it to be a transient error and convert it to + * -EAGAIN. + */ + if (retval == -EACCES) + retval = -EAGAIN; + + if (retval != -EAGAIN && retval != -EBUSY) + dev->power.runtime_error = retval; + + return retval; } /** @@ -725,21 +736,18 @@ static int rpm_suspend(struct device *dev, int rpmflags) dev->power.deferred_resume = false; wake_up_all(&dev->power.wait_queue); - if (retval == -EAGAIN || retval == -EBUSY) { - dev->power.runtime_error = 0; + /* + * On transient errors, if the callback routine failed an autosuspend, + * and if the last_busy time has been updated so that there is a new + * autosuspend expiration time, automatically reschedule another + * autosuspend. + */ + if (!dev->power.runtime_error && (rpmflags & RPM_AUTO) && + pm_runtime_autosuspend_expiration(dev) != 0) + goto repeat; + + pm_runtime_cancel_pending(dev); - /* - * If the callback routine failed an autosuspend, and - * if the last_busy time has been updated so that there - * is a new autosuspend expiration time, automatically - * reschedule another autosuspend. - */ - if ((rpmflags & RPM_AUTO) && - pm_runtime_autosuspend_expiration(dev) != 0) - goto repeat; - } else { - pm_runtime_cancel_pending(dev); - } goto out; } -- cgit