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
This commit is contained in:
Rafael J. Wysocki
2025-02-25 18:06:18 +01:00
parent d2677d57d4
commit 7226386965

View File

@@ -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;
}