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 <ccaione@baylibre.com>
This commit is contained in:
parent
6bf275a8ca
commit
d38a6b4bcd
3 changed files with 20 additions and 7 deletions
|
@ -124,12 +124,12 @@ struct pm_device {
|
||||||
const struct device *dev;
|
const struct device *dev;
|
||||||
/** Lock to synchronize the get/put operations */
|
/** Lock to synchronize the get/put operations */
|
||||||
struct k_mutex lock;
|
struct k_mutex lock;
|
||||||
|
/** Event var to listen to the sync request events */
|
||||||
|
struct k_event event;
|
||||||
/** Device usage count */
|
/** Device usage count */
|
||||||
uint32_t usage;
|
uint32_t usage;
|
||||||
/** Work object for asynchronous calls */
|
/** Work object for asynchronous calls */
|
||||||
struct k_work_delayable work;
|
struct k_work_delayable work;
|
||||||
/** Event conditional var to listen to the sync request events */
|
|
||||||
struct k_condvar condvar;
|
|
||||||
#endif /* CONFIG_PM_DEVICE_RUNTIME */
|
#endif /* CONFIG_PM_DEVICE_RUNTIME */
|
||||||
#ifdef CONFIG_PM_DEVICE_POWER_DOMAIN
|
#ifdef CONFIG_PM_DEVICE_POWER_DOMAIN
|
||||||
/** Power Domain it belongs */
|
/** Power Domain it belongs */
|
||||||
|
@ -148,7 +148,7 @@ struct pm_device {
|
||||||
#ifdef CONFIG_PM_DEVICE_RUNTIME
|
#ifdef CONFIG_PM_DEVICE_RUNTIME
|
||||||
#define Z_PM_DEVICE_RUNTIME_INIT(obj) \
|
#define Z_PM_DEVICE_RUNTIME_INIT(obj) \
|
||||||
.lock = Z_MUTEX_INITIALIZER(obj.lock), \
|
.lock = Z_MUTEX_INITIALIZER(obj.lock), \
|
||||||
.condvar = Z_CONDVAR_INITIALIZER(obj.condvar),
|
.event = Z_EVENT_INITIALIZER(obj.event),
|
||||||
#else
|
#else
|
||||||
#define Z_PM_DEVICE_RUNTIME_INIT(obj)
|
#define Z_PM_DEVICE_RUNTIME_INIT(obj)
|
||||||
#endif /* CONFIG_PM_DEVICE_RUNTIME */
|
#endif /* CONFIG_PM_DEVICE_RUNTIME */
|
||||||
|
|
|
@ -104,6 +104,7 @@ config PM_DEVICE_POWER_DOMAIN_DYNAMIC_NUM
|
||||||
|
|
||||||
config PM_DEVICE_RUNTIME
|
config PM_DEVICE_RUNTIME
|
||||||
bool "Runtime Device Power Management"
|
bool "Runtime Device Power Management"
|
||||||
|
select EVENTS
|
||||||
help
|
help
|
||||||
Enable Runtime Power Management to save power. With device runtime PM
|
Enable Runtime Power Management to save power. With device runtime PM
|
||||||
enabled, devices can be suspended or resumed based on the device
|
enabled, devices can be suspended or resumed based on the device
|
||||||
|
|
|
@ -19,6 +19,11 @@ LOG_MODULE_DECLARE(pm_device, CONFIG_PM_DEVICE_LOG_LEVEL);
|
||||||
#define PM_DOMAIN(_pm) NULL
|
#define PM_DOMAIN(_pm) NULL
|
||||||
#endif
|
#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
|
* @brief Suspend a device
|
||||||
*
|
*
|
||||||
|
@ -100,7 +105,7 @@ static void runtime_suspend_work(struct k_work *work)
|
||||||
} else {
|
} else {
|
||||||
pm->state = PM_DEVICE_STATE_SUSPENDED;
|
pm->state = PM_DEVICE_STATE_SUSPENDED;
|
||||||
}
|
}
|
||||||
k_condvar_broadcast(&pm->condvar);
|
k_event_set(&pm->event, BIT(pm->state));
|
||||||
k_mutex_unlock(&pm->lock);
|
k_mutex_unlock(&pm->lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -155,7 +160,11 @@ int pm_device_runtime_get(const struct device *dev)
|
||||||
if (!k_is_pre_kernel()) {
|
if (!k_is_pre_kernel()) {
|
||||||
/* wait until possible async suspend is completed */
|
/* wait until possible async suspend is completed */
|
||||||
while (pm->state == PM_DEVICE_STATE_SUSPENDING) {
|
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 */
|
/* wait until possible async suspend is completed */
|
||||||
if (!k_is_pre_kernel()) {
|
if (!k_is_pre_kernel()) {
|
||||||
while (pm->state == PM_DEVICE_STATE_SUSPENDING) {
|
while (pm->state == PM_DEVICE_STATE_SUSPENDING) {
|
||||||
(void)k_condvar_wait(&pm->condvar, &pm->lock,
|
k_mutex_unlock(&pm->lock);
|
||||||
K_FOREVER);
|
|
||||||
|
k_event_wait(&pm->event, EVENT_MASK, true, K_FOREVER);
|
||||||
|
|
||||||
|
(void)k_mutex_lock(&pm->lock, K_FOREVER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue