diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2025-02-25 18:06:18 +0100 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2025-03-03 14:46:19 +0100 |
commit | 72263869656d09a5f9727504bb1f3cb7b010f0e5 (patch) | |
tree | 004110d0ad58c716c5d0558370aa39011cd05328 | |
parent | d2677d57d4b8ec63da8f51357bcf855c4cf47c78 (diff) | |
download | linux-72263869656d09a5f9727504bb1f3cb7b010f0e5.tar.gz linux-72263869656d09a5f9727504bb1f3cb7b010f0e5.tar.bz2 linux-72263869656d09a5f9727504bb1f3cb7b010f0e5.zip |
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 <rafael.j.wysocki@intel.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://patch.msgid.link/12620037.O9o76ZdvQC@rjwysocki.net
-rw-r--r-- | drivers/base/power/runtime.c | 40 |
1 files changed, 24 insertions, 16 deletions
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; } |