pm: device: do not call device if already on the given state
If the device is already at the given state, do not call the device PM control function. This makes sure that devices are only called to change from one state to another. Even though asynchronous device PM is completely broken, transitional states are considered too. Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This commit is contained in:
parent
59f0e73522
commit
bc2990f82d
3 changed files with 30 additions and 3 deletions
|
@ -112,7 +112,9 @@ const char *pm_device_state_str(enum pm_device_state state);
|
|||
* @param state Device power state to be set.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval Errno Negative errno code in case of failure.
|
||||
* @retval -ENOTSUP If requested state is not supported.
|
||||
* @retval -EALREADY If device is already at (or transitioning to) the requested
|
||||
* state.
|
||||
*/
|
||||
int pm_device_state_set(const struct device *dev,
|
||||
enum pm_device_state state);
|
||||
|
|
|
@ -137,6 +137,32 @@ int pm_device_state_set(const struct device *dev,
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case PM_DEVICE_STATE_SUSPEND:
|
||||
if ((dev->pm->state == PM_DEVICE_STATE_SUSPEND) ||
|
||||
(dev->pm->state == PM_DEVICE_STATE_SUSPENDING)) {
|
||||
return -EALREADY;
|
||||
}
|
||||
break;
|
||||
case PM_DEVICE_STATE_ACTIVE:
|
||||
if ((dev->pm->state == PM_DEVICE_STATE_ACTIVE) ||
|
||||
(dev->pm->state == PM_DEVICE_STATE_RESUMING)) {
|
||||
return -EALREADY;
|
||||
}
|
||||
break;
|
||||
case PM_DEVICE_STATE_FORCE_SUSPEND:
|
||||
__fallthrough;
|
||||
case PM_DEVICE_STATE_LOW_POWER:
|
||||
__fallthrough;
|
||||
case PM_DEVICE_STATE_OFF:
|
||||
if (dev->pm->state == state) {
|
||||
return -EALREADY;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
ret = dev->pm_control(dev, state);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
|
|
@ -27,7 +27,6 @@ static void pm_device_runtime_state_set(struct pm_device *pm)
|
|||
switch (dev->pm->state) {
|
||||
case PM_DEVICE_STATE_ACTIVE:
|
||||
if ((dev->pm->usage == 0) && dev->pm->enable) {
|
||||
dev->pm->state = PM_DEVICE_STATE_SUSPENDING;
|
||||
ret = pm_device_state_set(dev, PM_DEVICE_STATE_SUSPEND);
|
||||
if (ret == 0) {
|
||||
dev->pm->state = PM_DEVICE_STATE_SUSPEND;
|
||||
|
@ -36,7 +35,6 @@ static void pm_device_runtime_state_set(struct pm_device *pm)
|
|||
break;
|
||||
case PM_DEVICE_STATE_SUSPEND:
|
||||
if ((dev->pm->usage > 0) || !dev->pm->enable) {
|
||||
dev->pm->state = PM_DEVICE_STATE_RESUMING;
|
||||
ret = pm_device_state_set(dev, PM_DEVICE_STATE_ACTIVE);
|
||||
if (ret == 0) {
|
||||
dev->pm->state = PM_DEVICE_STATE_ACTIVE;
|
||||
|
@ -77,6 +75,7 @@ static int pm_device_request(const struct device *dev,
|
|||
int ret = 0;
|
||||
|
||||
SYS_PORT_TRACING_FUNC_ENTER(pm, device_request, dev, target_state);
|
||||
|
||||
__ASSERT((target_state == PM_DEVICE_STATE_ACTIVE) ||
|
||||
(target_state == PM_DEVICE_STATE_SUSPEND),
|
||||
"Invalid device PM state requested");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue