Skip to content

Commit

Permalink
tests: pm: device_runtime_api: Extend with synchronous device
Browse files Browse the repository at this point in the history
Extended test to support case when PM device is defined as
synchronous.

Signed-off-by: Krzysztof Chruściński <[email protected]>
  • Loading branch information
nordic-krch committed Jan 16, 2024
1 parent f80b7f8 commit db501ed
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 83 deletions.
8 changes: 8 additions & 0 deletions tests/subsys/pm/device_runtime_api/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0

source "Kconfig.zephyr"

config TEST_PM_DEVICE_SYNC
bool "Use synchronous PM for the test"
160 changes: 83 additions & 77 deletions tests/subsys/pm/device_runtime_api/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,105 +141,111 @@ ZTEST(device_runtime_api, test_api)
ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
zassert_equal(ret, 0);

(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);

/* usage: 0, -1, suspend: no (unbalanced call) */
ret = pm_device_runtime_put(test_dev);
zassert_equal(ret, -EALREADY);

/* usage: 0, -1, suspend: no (unbalanced call) */
ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
zassert_equal(ret, -EALREADY);
if (IS_ENABLED(CONFIG_TEST_PM_DEVICE_SYNC)) {
/* In sync mode async put is equivalent as normal put. */
(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);
} else {
(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);

/* usage: 0, -1, suspend: no (unbalanced call) */
ret = pm_device_runtime_put(test_dev);
zassert_equal(ret, -EALREADY);

/* usage: 0, -1, suspend: no (unbalanced call) */
ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
zassert_equal(ret, -EALREADY);

/* unblock test driver and let it finish */
test_driver_pm_done(test_dev);
k_yield();

/* unblock test driver and let it finish */
test_driver_pm_done(test_dev);
k_yield();
(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);

(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);
/*** get + asynchronous put + get (while suspend still ongoing) ***/

/*** get + asynchronous put + get (while suspend still ongoing) ***/
/* usage: 0, +1, resume: yes */
ret = pm_device_runtime_get(test_dev);
zassert_equal(ret, 0);

/* usage: 0, +1, resume: yes */
ret = pm_device_runtime_get(test_dev);
zassert_equal(ret, 0);
(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_ACTIVE);

(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_ACTIVE);
test_driver_pm_async(test_dev);

test_driver_pm_async(test_dev);
/* usage: 1, -1, suspend: yes (queued) */
ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
zassert_equal(ret, 0);

/* usage: 1, -1, suspend: yes (queued) */
ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
zassert_equal(ret, 0);
(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);

(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
/* let suspension start */
k_yield();

/* let suspension start */
k_yield();
/* create and start get_runner thread
* get_runner thread is used to test synchronous path while asynchronous
* is ongoing. It is important to set its priority >= to the system work
* queue to make sure sync path run by the thread is forced to wait.
*/
k_thread_create(&get_runner_td, get_runner_stack,
K_THREAD_STACK_SIZEOF(get_runner_stack), get_runner,
NULL, NULL, NULL, CONFIG_SYSTEM_WORKQUEUE_PRIORITY, 0,
K_NO_WAIT);
k_yield();

/* create and start get_runner thread
* get_runner thread is used to test synchronous path while asynchronous
* is ongoing. It is important to set its priority >= to the system work
* queue to make sure sync path run by the thread is forced to wait.
*/
k_thread_create(&get_runner_td, get_runner_stack,
K_THREAD_STACK_SIZEOF(get_runner_stack), get_runner,
NULL, NULL, NULL, CONFIG_SYSTEM_WORKQUEUE_PRIORITY, 0,
K_NO_WAIT);
k_yield();

/* let driver suspend to finish and wait until get_runner finishes
* resuming the driver
*/
test_driver_pm_done(test_dev);
k_thread_join(&get_runner_td, K_FOREVER);
/* let driver suspend to finish and wait until get_runner finishes
* resuming the driver
*/
test_driver_pm_done(test_dev);
k_thread_join(&get_runner_td, K_FOREVER);

(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_ACTIVE);
(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_ACTIVE);

/* Test if getting a device before an async operation starts does
* not trigger any device pm action.
*/
size_t count = test_driver_pm_count(test_dev);
/* Test if getting a device before an async operation starts does
* not trigger any device pm action.
*/
size_t count = test_driver_pm_count(test_dev);

ret = pm_device_runtime_put_async(test_dev, K_MSEC(10));
zassert_equal(ret, 0);
ret = pm_device_runtime_put_async(test_dev, K_MSEC(10));
zassert_equal(ret, 0);

(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);

ret = pm_device_runtime_get(test_dev);
zassert_equal(ret, 0);
ret = pm_device_runtime_get(test_dev);
zassert_equal(ret, 0);

/* Now lets check if the calls above have triggered a device
* pm action
*/
zassert_equal(count, test_driver_pm_count(test_dev));
/* Now lets check if the calls above have triggered a device
* pm action
*/
zassert_equal(count, test_driver_pm_count(test_dev));

/*
* test if async put with a delay respects the given time.
*/
ret = pm_device_runtime_put_async(test_dev, K_MSEC(100));
/*
* test if async put with a delay respects the given time.
*/
ret = pm_device_runtime_put_async(test_dev, K_MSEC(100));

(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);

k_sleep(K_MSEC(80));
k_sleep(K_MSEC(80));

/* It should still be suspending since we have waited less than
* the delay we've set.
*/
(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
/* It should still be suspending since we have waited less than
* the delay we've set.
*/
(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);

k_sleep(K_MSEC(30));
k_sleep(K_MSEC(30));

/* Now it should be already suspended */
(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);
/* Now it should be already suspended */
(void)pm_device_state_get(test_dev, &state);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);
}

/* Put operation should fail due the state be locked. */
ret = pm_device_runtime_disable(test_dev);
Expand Down
18 changes: 12 additions & 6 deletions tests/subsys/pm/device_runtime_api/src/test_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ static int test_driver_action(const struct device *dev,
{
struct test_driver_data *data = dev->data;

data->ongoing = true;
if (!IS_ENABLED(CONFIG_TEST_PM_DEVICE_SYNC)) {
data->ongoing = true;

if (data->async) {
k_sem_take(&data->sync, K_FOREVER);
data->async = false;
}
if (data->async) {
k_sem_take(&data->sync, K_FOREVER);
data->async = false;
}

data->ongoing = false;
data->ongoing = false;
}

data->count++;

Expand Down Expand Up @@ -72,7 +74,11 @@ int test_driver_init(const struct device *dev)
return 0;
}

#if CONFIG_TEST_PM_DEVICE_SYNC
PM_DEVICE_SYNC_DEFINE(test_driver, test_driver_action);
#else
PM_DEVICE_DEFINE(test_driver, test_driver_action);
#endif

static struct test_driver_data data;

Expand Down
6 changes: 6 additions & 0 deletions tests/subsys/pm/device_runtime_api/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ tests:
tags: pm
integration_platforms:
- native_sim
pm.device_runtime.sync.api:
tags: pm
integration_platforms:
- native_sim
extra_configs:
- CONFIG_TEST_PM_DEVICE_SYNC=y

0 comments on commit db501ed

Please sign in to comment.