From d38a6b4bcdf03f6a86f4035a47de7e845c88a9f7 Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Tue, 6 Dec 2022 17:44:24 +0100 Subject: [PATCH] pm: runtime: Migrate from condition variables to events For the async operation move from condition variables to events to reduce the dependency on the mutexes that cannot be used in IRQ context. Signed-off-by: Carlo Caione --- include/zephyr/pm/device.h | 6 +++--- subsys/pm/Kconfig | 1 + subsys/pm/device_runtime.c | 20 ++++++++++++++++---- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/include/zephyr/pm/device.h b/include/zephyr/pm/device.h index 1161d6aabae..023d35b3d37 100644 --- a/include/zephyr/pm/device.h +++ b/include/zephyr/pm/device.h @@ -124,12 +124,12 @@ struct pm_device { const struct device *dev; /** Lock to synchronize the get/put operations */ struct k_mutex lock; + /** Event var to listen to the sync request events */ + struct k_event event; /** Device usage count */ uint32_t usage; /** Work object for asynchronous calls */ struct k_work_delayable work; - /** Event conditional var to listen to the sync request events */ - struct k_condvar condvar; #endif /* CONFIG_PM_DEVICE_RUNTIME */ #ifdef CONFIG_PM_DEVICE_POWER_DOMAIN /** Power Domain it belongs */ @@ -148,7 +148,7 @@ struct pm_device { #ifdef CONFIG_PM_DEVICE_RUNTIME #define Z_PM_DEVICE_RUNTIME_INIT(obj) \ .lock = Z_MUTEX_INITIALIZER(obj.lock), \ - .condvar = Z_CONDVAR_INITIALIZER(obj.condvar), + .event = Z_EVENT_INITIALIZER(obj.event), #else #define Z_PM_DEVICE_RUNTIME_INIT(obj) #endif /* CONFIG_PM_DEVICE_RUNTIME */ diff --git a/subsys/pm/Kconfig b/subsys/pm/Kconfig index a1f02a1279a..4395e771859 100644 --- a/subsys/pm/Kconfig +++ b/subsys/pm/Kconfig @@ -104,6 +104,7 @@ config PM_DEVICE_POWER_DOMAIN_DYNAMIC_NUM config PM_DEVICE_RUNTIME bool "Runtime Device Power Management" + select EVENTS help Enable Runtime Power Management to save power. With device runtime PM enabled, devices can be suspended or resumed based on the device diff --git a/subsys/pm/device_runtime.c b/subsys/pm/device_runtime.c index bc105193d12..55cc645faee 100644 --- a/subsys/pm/device_runtime.c +++ b/subsys/pm/device_runtime.c @@ -19,6 +19,11 @@ LOG_MODULE_DECLARE(pm_device, CONFIG_PM_DEVICE_LOG_LEVEL); #define PM_DOMAIN(_pm) NULL #endif +#define EVENT_STATE_ACTIVE BIT(PM_DEVICE_STATE_ACTIVE) +#define EVENT_STATE_SUSPENDED BIT(PM_DEVICE_STATE_SUSPENDED) + +#define EVENT_MASK (EVENT_STATE_ACTIVE | EVENT_STATE_SUSPENDED) + /** * @brief Suspend a device * @@ -100,7 +105,7 @@ static void runtime_suspend_work(struct k_work *work) } else { pm->state = PM_DEVICE_STATE_SUSPENDED; } - k_condvar_broadcast(&pm->condvar); + k_event_set(&pm->event, BIT(pm->state)); k_mutex_unlock(&pm->lock); /* @@ -155,7 +160,11 @@ int pm_device_runtime_get(const struct device *dev) if (!k_is_pre_kernel()) { /* wait until possible async suspend is completed */ while (pm->state == PM_DEVICE_STATE_SUSPENDING) { - (void)k_condvar_wait(&pm->condvar, &pm->lock, K_FOREVER); + k_mutex_unlock(&pm->lock); + + k_event_wait(&pm->event, EVENT_MASK, true, K_FOREVER); + + (void)k_mutex_lock(&pm->lock, K_FOREVER); } } @@ -292,8 +301,11 @@ int pm_device_runtime_disable(const struct device *dev) /* wait until possible async suspend is completed */ if (!k_is_pre_kernel()) { while (pm->state == PM_DEVICE_STATE_SUSPENDING) { - (void)k_condvar_wait(&pm->condvar, &pm->lock, - K_FOREVER); + k_mutex_unlock(&pm->lock); + + k_event_wait(&pm->event, EVENT_MASK, true, K_FOREVER); + + (void)k_mutex_lock(&pm->lock, K_FOREVER); } }