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) */
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
*
* @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
* 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()
*/
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.
@ -188,9 +189,11 @@ static inline int pm_device_runtime_put(const struct device *dev)
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(delay);
return 0;
}

View File

@ -1954,15 +1954,17 @@
/**
* @brief Trace putting a device (asynchronously) call entry.
* @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.
* @param dev Device instance.
* @param delay Time to delay the operation.
* @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.

View File

@ -35,6 +35,7 @@ LOG_MODULE_DECLARE(pm_device, CONFIG_PM_DEVICE_LOG_LEVEL);
*
* @param dev Device instance.
* @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 -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 -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;
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()) {
/* queue suspend */
pm->state = PM_DEVICE_STATE_SUSPENDING;
(void)k_work_schedule(&pm->work, K_NO_WAIT);
(void)k_work_schedule(&pm->work, delay);
} else {
/* suspend now */
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);
ret = runtime_suspend(dev, false);
ret = runtime_suspend(dev, false, K_NO_WAIT);
/*
* Now put the domain
@ -247,7 +249,7 @@ int pm_device_runtime_put(const struct device *dev)
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;
@ -255,9 +257,9 @@ int pm_device_runtime_put_async(const struct device *dev)
return 0;
}
SYS_PORT_TRACING_FUNC_ENTER(pm, device_runtime_put_async, dev);
ret = runtime_suspend(dev, true);
SYS_PORT_TRACING_FUNC_EXIT(pm, device_runtime_put_async, dev, ret);
SYS_PORT_TRACING_FUNC_ENTER(pm, device_runtime_put_async, dev, delay);
ret = runtime_suspend(dev, true, delay);
SYS_PORT_TRACING_FUNC_EXIT(pm, device_runtime_put_async, dev, delay, 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_put_enter(dev)
#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_exit(dev, ret)
#define sys_port_trace_pm_device_runtime_put_async_enter(dev, delay)
#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_exit(dev, ret)
#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
157 pm_device_runtime_get 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
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) \
SEGGER_SYSVIEW_RecordEndCallU32(TID_PM_DEVICE_RUNTIME_PUT, \
(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, \
(uint32_t)(uintptr_t)dev)
#define sys_port_trace_pm_device_runtime_put_async_exit(dev, ret) \
(uint32_t)(uintptr_t)dev, (uint32_t)delay.ticks)
#define sys_port_trace_pm_device_runtime_put_async_exit(dev, delay, ret) \
SEGGER_SYSVIEW_RecordEndCallU32(TID_PM_DEVICE_RUNTIME_PUT_ASYNC, \
(uint32_t)ret)
#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_put_enter(dev)
#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_exit(dev, ret)
#define sys_port_trace_pm_device_runtime_put_async_enter(dev, delay)
#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_exit(dev, ret)
#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_put_enter(dev)
#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_exit(dev, ret)
#define sys_port_trace_pm_device_runtime_put_async_enter(dev, delay)
#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_exit(dev, ret)
#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);
ret = pm_device_runtime_put(test_dev);
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);
/* enable runtime PM */
@ -138,7 +138,7 @@ ZTEST(device_runtime_api, test_api)
test_driver_pm_async(test_dev);
/* 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);
(void)pm_device_state_get(test_dev, &state);
@ -149,7 +149,7 @@ ZTEST(device_runtime_api, test_api)
zassert_equal(ret, -EALREADY);
/* 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);
/* unblock test driver and let it finish */
@ -171,7 +171,7 @@ ZTEST(device_runtime_api, test_api)
test_driver_pm_async(test_dev);
/* 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);
(void)pm_device_state_get(test_dev, &state);