From 0a32eadd13ab0d2d57149cf62f3a005e688bfa64 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 17 Nov 2021 21:50:08 -0800 Subject: [PATCH] pm: Account device pm state lock Do not execute pm operations on devices that the device pm state is locked. Signed-off-by: Flavio Ceolin --- include/pm/device.h | 3 +++ subsys/pm/device.c | 7 ++++++- subsys/pm/device_runtime.c | 5 +++++ subsys/pm/pm.c | 4 ++-- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/pm/device.h b/include/pm/device.h index e81148c4cc2..f9412aa4cbc 100644 --- a/include/pm/device.h +++ b/include/pm/device.h @@ -298,6 +298,7 @@ const char *pm_device_state_str(enum pm_device_state state); * @retval -EALREADY If device is already at the requested state. * @retval -EBUSY If device is changing its state. * @retval -ENOSYS If device does not support PM. + * @retval -EPERM If device has power state locked. * @retval Errno Other negative errno on failure. */ __deprecated int pm_device_state_set(const struct device *dev, @@ -418,6 +419,8 @@ bool pm_device_wakeup_is_capable(const struct device *dev); * system power management or device runtime power * management until unlocked. * + * @note The given device should not have device runtime enabled. + * * @see pm_device_state_unlock * * @param dev Device instance. diff --git a/subsys/pm/device.c b/subsys/pm/device.c index 6a8324ce71d..942bba71906 100644 --- a/subsys/pm/device.c +++ b/subsys/pm/device.c @@ -6,6 +6,7 @@ #include #include +#include #include LOG_MODULE_REGISTER(pm_device, CONFIG_PM_DEVICE_LOG_LEVEL); @@ -35,6 +36,10 @@ int pm_device_state_set(const struct device *dev, return -ENOSYS; } + if (pm_device_state_is_locked(dev)) { + return -EPERM; + } + switch (state) { case PM_DEVICE_STATE_SUSPENDED: if (pm->state == PM_DEVICE_STATE_SUSPENDED) { @@ -246,7 +251,7 @@ void pm_device_state_lock(const struct device *dev) { struct pm_device *pm = dev->pm; - if (pm != NULL) { + if ((pm != NULL) && !pm_device_runtime_is_enabled(dev)) { atomic_set_bit(&pm->flags, PM_DEVICE_FLAG_STATE_LOCKED); } } diff --git a/subsys/pm/device_runtime.c b/subsys/pm/device_runtime.c index 371138ba3c5..74b65bda352 100644 --- a/subsys/pm/device_runtime.c +++ b/subsys/pm/device_runtime.c @@ -172,6 +172,10 @@ void pm_device_runtime_enable(const struct device *dev) SYS_PORT_TRACING_FUNC_ENTER(pm, device_runtime_enable, dev); + if (pm_device_state_is_locked(dev)) { + goto end; + } + if (!k_is_pre_kernel()) { (void)k_mutex_lock(&pm->lock, K_FOREVER); } @@ -195,6 +199,7 @@ unlock: k_mutex_unlock(&pm->lock); } +end: SYS_PORT_TRACING_FUNC_EXIT(pm, device_runtime_enable, dev); } diff --git a/subsys/pm/pm.c b/subsys/pm/pm.c index 0dc09130439..c58b0213192 100644 --- a/subsys/pm/pm.c +++ b/subsys/pm/pm.c @@ -56,8 +56,8 @@ static int pm_suspend_devices(void) * ignore busy devices, wake up source and devices with * runtime PM enabled. */ - if (pm_device_is_busy(dev) || - pm_device_wakeup_is_enabled(dev) || + if (pm_device_is_busy(dev) || pm_device_state_is_locked(dev) + || pm_device_wakeup_is_enabled(dev) || ((dev->pm != NULL) && pm_device_runtime_is_enabled(dev))) { continue; }