Replies: 1 comment
-
This is the meat of runtime_suspend()static int runtime_suspend(const struct device *dev, bool async)
{
int ret = 0;
struct pm_device *pm = dev->pm;
/*
* Early return if device runtime is not enabled.
*/
if (!atomic_test_bit(&pm->flags, PM_DEVICE_FLAG_RUNTIME_ENABLED)) {
return 0;
}
if (k_is_pre_kernel()) {
async = false;
} else {
ret = k_sem_take(&pm->lock, k_is_in_isr() ? K_NO_WAIT : K_FOREVER);
if (ret < 0) {
return -EBUSY;
}
}
if (pm->usage == 0U) {
LOG_WRN("Unbalanced suspend");
ret = -EALREADY;
goto unlock;
}
pm->usage--;
if (pm->usage > 0U) {
goto unlock;
}
if (async && !k_is_pre_kernel()) {
/* queue suspend */
pm->state = PM_DEVICE_STATE_SUSPENDING;
(void)k_work_schedule(&pm->work, K_NO_WAIT);
} else {
/* suspend now */
ret = pm->action_cb(pm->dev, PM_DEVICE_ACTION_SUSPEND);
if (ret < 0) {
pm->usage++;
goto unlock;
}
pm->state = PM_DEVICE_STATE_SUSPENDED;
}
unlock:
if (!k_is_pre_kernel()) {
k_sem_give(&pm->lock);
}
return ret;
} As you can see, there are a few places returning a failure code
Except for the call-back, the device specific function to actually put the device in suspend, the function does pretty good job of decrementing the usage counter. In fact when the call-back failed, When device is busyThis happends when two threads are accessing the same device for PM. But, if you look closer, the call will block if you are not in ISR. Thus, it will eventually take a semaphore and decrement the usage. If you are calling from an ISR, it returns imediately with When unbalanced suspendThis is more like programing error. You should debug it. When the device specific function failedIt all depends. Some devices are simple some are not. A device might be behind a data bus, which can fail as well. ConclusionSo, basically the answer is, as always, "it depends". You need to know why it failed and handle accordingly. Question regarding "releasing must always be successful"How could this be possible? Taking from the above case, does the systems you've used before:
Best, |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
According to the Runtime PM API documentation, when requesting or releasing a PM resource with
pm_device_runtime_get/set
, the usage count of the device will not change in the event of a failure. This brings up some questions as to how code should respond to encountering a failure. For example, if one attempts to release a PM resource, and it fails, you're still holding a reference to that resource that you no longer want, which may now be in an unusable state. This is further complicated if you're creating a driver that as part of its own PM callback requests/releases dependent resources such as a bus or GPIO.In other systems I've used before I've seen requesting can fail (with the usage count not changing) but releasing must always be successful. There are very few examples of things using the runtime PM API in non-trivial ways. Does anybody have any insight on how one should handle runtime PM failures in Zephyr?
Beta Was this translation helpful? Give feedback.
All reactions