pm: device_runtime: Add delay to async put

Add a delay parameter to asynchronous device runtim put. This allows
to delay the put operation what is useful to avoid multiple states
transitions.

Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
This commit is contained in:
Flavio Ceolin 2023-12-05 23:17:56 +00:00 committed by Carles Cufí
parent 0ea173b774
commit b5ca7a06b4
10 changed files with 33 additions and 26 deletions

View file

@ -224,5 +224,5 @@ asynchronous API:
... ...
/* "put" device (decreases usage count, schedule suspend if no more users) */ /* "put" device (decreases usage count, schedule suspend if no more users) */
return pm_device_runtime_put_async(dev); return pm_device_runtime_put_async(dev, K_NO_WAIT);
} }

View file

@ -131,6 +131,7 @@ int pm_device_runtime_put(const struct device *dev);
* @funcprops \pre_kernel_ok, \async, \isr_ok * @funcprops \pre_kernel_ok, \async, \isr_ok
* *
* @param dev Device instance. * @param dev Device instance.
* @param delay Minimum amount of time before triggering the action.
* *
* @retval 0 If it succeeds. In case device runtime PM is not enabled or not * @retval 0 If it succeeds. In case device runtime PM is not enabled or not
* available this function will be a no-op and will also return 0. * available this function will be a no-op and will also return 0.
@ -140,7 +141,7 @@ int pm_device_runtime_put(const struct device *dev);
* *
* @see pm_device_runtime_put() * @see pm_device_runtime_put()
*/ */
int pm_device_runtime_put_async(const struct device *dev); int pm_device_runtime_put_async(const struct device *dev, k_timeout_t delay);
/** /**
* @brief Check if device runtime is enabled for a given device. * @brief Check if device runtime is enabled for a given device.
@ -188,9 +189,11 @@ static inline int pm_device_runtime_put(const struct device *dev)
return 0; return 0;
} }
static inline int pm_device_runtime_put_async(const struct device *dev) static inline int pm_device_runtime_put_async(const struct device *dev,
k_timeout_t delay)
{ {
ARG_UNUSED(dev); ARG_UNUSED(dev);
ARG_UNUSED(delay);
return 0; return 0;
} }

View file

@ -1954,15 +1954,17 @@
/** /**
* @brief Trace putting a device (asynchronously) call entry. * @brief Trace putting a device (asynchronously) call entry.
* @param dev Device instance. * @param dev Device instance.
* @param delay Time to delay the operation
*/ */
#define sys_port_trace_pm_device_runtime_put_async_enter(dev) #define sys_port_trace_pm_device_runtime_put_async_enter(dev, delay)
/** /**
* @brief Trace putting a device (asynchronously) call exit. * @brief Trace putting a device (asynchronously) call exit.
* @param dev Device instance. * @param dev Device instance.
* @param delay Time to delay the operation.
* @param ret Return value. * @param ret Return value.
*/ */
#define sys_port_trace_pm_device_runtime_put_async_exit(dev, ret) #define sys_port_trace_pm_device_runtime_put_async_exit(dev, delay, ret)
/** /**
* @brief Trace enabling device runtime PM call entry. * @brief Trace enabling device runtime PM call entry.

View file

@ -35,6 +35,7 @@ LOG_MODULE_DECLARE(pm_device, CONFIG_PM_DEVICE_LOG_LEVEL);
* *
* @param dev Device instance. * @param dev Device instance.
* @param async Perform operation asynchronously. * @param async Perform operation asynchronously.
* @param delay Period to delay the asynchronous operation.
* *
* @retval 0 If device has been suspended or queued for suspend. * @retval 0 If device has been suspended or queued for suspend.
* @retval -EALREADY If device is already suspended (can only happen if get/put * @retval -EALREADY If device is already suspended (can only happen if get/put
@ -42,7 +43,8 @@ LOG_MODULE_DECLARE(pm_device, CONFIG_PM_DEVICE_LOG_LEVEL);
* @retval -EBUSY If the device is busy. * @retval -EBUSY If the device is busy.
* @retval -errno Other negative errno, result of the action callback. * @retval -errno Other negative errno, result of the action callback.
*/ */
static int runtime_suspend(const struct device *dev, bool async) static int runtime_suspend(const struct device *dev, bool async,
k_timeout_t delay)
{ {
int ret = 0; int ret = 0;
struct pm_device *pm = dev->pm; struct pm_device *pm = dev->pm;
@ -77,7 +79,7 @@ static int runtime_suspend(const struct device *dev, bool async)
if (async && !k_is_pre_kernel()) { if (async && !k_is_pre_kernel()) {
/* queue suspend */ /* queue suspend */
pm->state = PM_DEVICE_STATE_SUSPENDING; pm->state = PM_DEVICE_STATE_SUSPENDING;
(void)k_work_schedule(&pm->work, K_NO_WAIT); (void)k_work_schedule(&pm->work, delay);
} else { } else {
/* suspend now */ /* suspend now */
ret = pm->action_cb(pm->dev, PM_DEVICE_ACTION_SUSPEND); ret = pm->action_cb(pm->dev, PM_DEVICE_ACTION_SUSPEND);
@ -233,7 +235,7 @@ int pm_device_runtime_put(const struct device *dev)
} }
SYS_PORT_TRACING_FUNC_ENTER(pm, device_runtime_put, dev); SYS_PORT_TRACING_FUNC_ENTER(pm, device_runtime_put, dev);
ret = runtime_suspend(dev, false); ret = runtime_suspend(dev, false, K_NO_WAIT);
/* /*
* Now put the domain * Now put the domain
@ -247,7 +249,7 @@ int pm_device_runtime_put(const struct device *dev)
return ret; return ret;
} }
int pm_device_runtime_put_async(const struct device *dev) int pm_device_runtime_put_async(const struct device *dev, k_timeout_t delay)
{ {
int ret; int ret;
@ -255,9 +257,9 @@ int pm_device_runtime_put_async(const struct device *dev)
return 0; return 0;
} }
SYS_PORT_TRACING_FUNC_ENTER(pm, device_runtime_put_async, dev); SYS_PORT_TRACING_FUNC_ENTER(pm, device_runtime_put_async, dev, delay);
ret = runtime_suspend(dev, true); ret = runtime_suspend(dev, true, delay);
SYS_PORT_TRACING_FUNC_EXIT(pm, device_runtime_put_async, dev, ret); SYS_PORT_TRACING_FUNC_EXIT(pm, device_runtime_put_async, dev, delay, ret);
return ret; return ret;
} }

View file

@ -338,8 +338,8 @@ extern "C" {
#define sys_port_trace_pm_device_runtime_get_exit(dev, ret) #define sys_port_trace_pm_device_runtime_get_exit(dev, ret)
#define sys_port_trace_pm_device_runtime_put_enter(dev) #define sys_port_trace_pm_device_runtime_put_enter(dev)
#define sys_port_trace_pm_device_runtime_put_exit(dev, ret) #define sys_port_trace_pm_device_runtime_put_exit(dev, ret)
#define sys_port_trace_pm_device_runtime_put_async_enter(dev) #define sys_port_trace_pm_device_runtime_put_async_enter(dev, delay)
#define sys_port_trace_pm_device_runtime_put_async_exit(dev, ret) #define sys_port_trace_pm_device_runtime_put_async_exit(dev, delay, ret)
#define sys_port_trace_pm_device_runtime_enable_enter(dev) #define sys_port_trace_pm_device_runtime_enable_enter(dev)
#define sys_port_trace_pm_device_runtime_enable_exit(dev, ret) #define sys_port_trace_pm_device_runtime_enable_exit(dev, ret)
#define sys_port_trace_pm_device_runtime_disable_enter(dev) #define sys_port_trace_pm_device_runtime_disable_enter(dev)

View file

@ -164,7 +164,7 @@ TaskState 0xBF 1=dummy, 2=Waiting, 4=New, 8=Terminated, 16=Suspended, 32=Termina
156 pm_system_suspend ticks=%u | Returns %Bool 156 pm_system_suspend ticks=%u | Returns %Bool
157 pm_device_runtime_get dev=%I | Returns %u 157 pm_device_runtime_get dev=%I | Returns %u
158 pm_device_runtime_put dev=%I | Returns %u 158 pm_device_runtime_put dev=%I | Returns %u
159 pm_device_runtime_put_async dev=%I | Returns %u 159 pm_device_runtime_put_async dev=%I, Delay=%TimeOut | Returns %u
160 pm_device_runtime_enable dev=%I | Returns %u 160 pm_device_runtime_enable dev=%I | Returns %u
161 pm_device_runtime_disable dev=%I | Returns %u 161 pm_device_runtime_disable dev=%I | Returns %u

View file

@ -640,10 +640,10 @@ void sys_trace_k_thread_info(struct k_thread *thread);
#define sys_port_trace_pm_device_runtime_put_exit(dev, ret) \ #define sys_port_trace_pm_device_runtime_put_exit(dev, ret) \
SEGGER_SYSVIEW_RecordEndCallU32(TID_PM_DEVICE_RUNTIME_PUT, \ SEGGER_SYSVIEW_RecordEndCallU32(TID_PM_DEVICE_RUNTIME_PUT, \
(uint32_t)ret) (uint32_t)ret)
#define sys_port_trace_pm_device_runtime_put_async_enter(dev) \ #define sys_port_trace_pm_device_runtime_put_async_enter(dev, delay) \
SEGGER_SYSVIEW_RecordU32(TID_PM_DEVICE_RUNTIME_PUT_ASYNC, \ SEGGER_SYSVIEW_RecordU32(TID_PM_DEVICE_RUNTIME_PUT_ASYNC, \
(uint32_t)(uintptr_t)dev) (uint32_t)(uintptr_t)dev, (uint32_t)delay.ticks)
#define sys_port_trace_pm_device_runtime_put_async_exit(dev, ret) \ #define sys_port_trace_pm_device_runtime_put_async_exit(dev, delay, ret) \
SEGGER_SYSVIEW_RecordEndCallU32(TID_PM_DEVICE_RUNTIME_PUT_ASYNC, \ SEGGER_SYSVIEW_RecordEndCallU32(TID_PM_DEVICE_RUNTIME_PUT_ASYNC, \
(uint32_t)ret) (uint32_t)ret)
#define sys_port_trace_pm_device_runtime_enable_enter(dev) \ #define sys_port_trace_pm_device_runtime_enable_enter(dev) \

View file

@ -442,8 +442,8 @@
#define sys_port_trace_pm_device_runtime_get_exit(dev, ret) #define sys_port_trace_pm_device_runtime_get_exit(dev, ret)
#define sys_port_trace_pm_device_runtime_put_enter(dev) #define sys_port_trace_pm_device_runtime_put_enter(dev)
#define sys_port_trace_pm_device_runtime_put_exit(dev, ret) #define sys_port_trace_pm_device_runtime_put_exit(dev, ret)
#define sys_port_trace_pm_device_runtime_put_async_enter(dev) #define sys_port_trace_pm_device_runtime_put_async_enter(dev, delay)
#define sys_port_trace_pm_device_runtime_put_async_exit(dev, ret) #define sys_port_trace_pm_device_runtime_put_async_exit(dev, delay, ret)
#define sys_port_trace_pm_device_runtime_enable_enter(dev) #define sys_port_trace_pm_device_runtime_enable_enter(dev)
#define sys_port_trace_pm_device_runtime_enable_exit(dev, ret) #define sys_port_trace_pm_device_runtime_enable_exit(dev, ret)
#define sys_port_trace_pm_device_runtime_disable_enter(dev) #define sys_port_trace_pm_device_runtime_disable_enter(dev)

View file

@ -329,8 +329,8 @@ void sys_trace_idle(void);
#define sys_port_trace_pm_device_runtime_get_exit(dev, ret) #define sys_port_trace_pm_device_runtime_get_exit(dev, ret)
#define sys_port_trace_pm_device_runtime_put_enter(dev) #define sys_port_trace_pm_device_runtime_put_enter(dev)
#define sys_port_trace_pm_device_runtime_put_exit(dev, ret) #define sys_port_trace_pm_device_runtime_put_exit(dev, ret)
#define sys_port_trace_pm_device_runtime_put_async_enter(dev) #define sys_port_trace_pm_device_runtime_put_async_enter(dev, delay)
#define sys_port_trace_pm_device_runtime_put_async_exit(dev, ret) #define sys_port_trace_pm_device_runtime_put_async_exit(dev, delay, ret)
#define sys_port_trace_pm_device_runtime_enable_enter(dev) #define sys_port_trace_pm_device_runtime_enable_enter(dev)
#define sys_port_trace_pm_device_runtime_enable_exit(dev, ret) #define sys_port_trace_pm_device_runtime_enable_exit(dev, ret)
#define sys_port_trace_pm_device_runtime_disable_enter(dev) #define sys_port_trace_pm_device_runtime_disable_enter(dev)

View file

@ -42,7 +42,7 @@ void test_api_setup(void *data)
zassert_equal(ret, 0); zassert_equal(ret, 0);
ret = pm_device_runtime_put(test_dev); ret = pm_device_runtime_put(test_dev);
zassert_equal(ret, 0); zassert_equal(ret, 0);
ret = pm_device_runtime_put_async(test_dev); ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
zassert_equal(ret, 0); zassert_equal(ret, 0);
/* enable runtime PM */ /* enable runtime PM */
@ -138,7 +138,7 @@ ZTEST(device_runtime_api, test_api)
test_driver_pm_async(test_dev); test_driver_pm_async(test_dev);
/* usage: 1, -1, suspend: yes (queued) */ /* usage: 1, -1, suspend: yes (queued) */
ret = pm_device_runtime_put_async(test_dev); ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
zassert_equal(ret, 0); zassert_equal(ret, 0);
(void)pm_device_state_get(test_dev, &state); (void)pm_device_state_get(test_dev, &state);
@ -149,7 +149,7 @@ ZTEST(device_runtime_api, test_api)
zassert_equal(ret, -EALREADY); zassert_equal(ret, -EALREADY);
/* usage: 0, -1, suspend: no (unbalanced call) */ /* usage: 0, -1, suspend: no (unbalanced call) */
ret = pm_device_runtime_put_async(test_dev); ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
zassert_equal(ret, -EALREADY); zassert_equal(ret, -EALREADY);
/* unblock test driver and let it finish */ /* unblock test driver and let it finish */
@ -171,7 +171,7 @@ ZTEST(device_runtime_api, test_api)
test_driver_pm_async(test_dev); test_driver_pm_async(test_dev);
/* usage: 1, -1, suspend: yes (queued) */ /* usage: 1, -1, suspend: yes (queued) */
ret = pm_device_runtime_put_async(test_dev); ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
zassert_equal(ret, 0); zassert_equal(ret, 0);
(void)pm_device_state_get(test_dev, &state); (void)pm_device_state_get(test_dev, &state);