Skip to content

Commit 6e02edf

Browse files
committed
pm: device_runtime: Make async optional
Async now uses its own work queue, which means it consumes more resources. Since not all applications need the async API, we can make it optional without any penalty for those applications. Signed-off-by: Flavio Ceolin <[email protected]>
1 parent 4984fc1 commit 6e02edf

File tree

5 files changed

+52
-2
lines changed

5 files changed

+52
-2
lines changed

include/zephyr/pm/device.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,10 @@ struct pm_device {
170170
struct k_sem lock;
171171
/** Event var to listen to the sync request events */
172172
struct k_event event;
173+
#if defined(CONFIG_PM_DEVICE_RUNTIME_ASYNC) || defined(__DOXYGEN__)
173174
/** Work object for asynchronous calls */
174175
struct k_work_delayable work;
176+
#endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
175177
#endif /* CONFIG_PM_DEVICE_RUNTIME */
176178
};
177179

subsys/pm/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,15 @@ if PM_DEVICE_RUNTIME
126126
config PM_DRIVER_NEEDS_DEDICATED_WQ
127127
bool
128128

129+
config PM_DEVICE_RUNTIME_ASYNC
130+
bool "Asynchronous device runtime power management"
131+
default y
132+
help
133+
Use this option to enable support for asynchronous operation
134+
in the power management device runtime.
135+
136+
if PM_DEVICE_RUNTIME_ASYNC
137+
129138
choice PM_DEVICE_RUNTIME_WQ
130139
prompt "Work queue to be used by pm device runtime async"
131140
default PM_DEVICE_RUNTIME_USE_DEDICATED_WQ if PM_DRIVER_NEEDS_DEDICATED_WQ
@@ -164,6 +173,7 @@ config PM_DEVICE_RUNTIME_DEDICATED_WQ_INIT_PRIO
164173
endif #PM_DEVICE_RUNTIME_USE_DEDICATED_WQ
165174
endchoice
166175

176+
endif # PM_DEVICE_RUNTIME_ASYNC
167177
endif # PM_DEVICE_RUNTIME
168178

169179
config PM_DEVICE_SHELL

subsys/pm/device_runtime.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ LOG_MODULE_DECLARE(pm_device, CONFIG_PM_DEVICE_LOG_LEVEL);
2020
#define PM_DOMAIN(_pm) NULL
2121
#endif
2222

23+
#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
2324
#ifdef CONFIG_PM_DEVICE_RUNTIME_USE_DEDICATED_WQ
2425
K_THREAD_STACK_DEFINE(pm_device_runtime_stack, CONFIG_PM_DEVICE_RUNTIME_DEDICATED_WQ_STACK_SIZE);
2526
static struct k_work_q pm_device_runtime_wq;
2627
#endif /* CONFIG_PM_DEVICE_RUNTIME_USE_DEDICATED_WQ */
28+
#endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
2729

2830
#define EVENT_STATE_ACTIVE BIT(PM_DEVICE_STATE_ACTIVE)
2931
#define EVENT_STATE_SUSPENDED BIT(PM_DEVICE_STATE_SUSPENDED)
@@ -84,12 +86,14 @@ static int runtime_suspend(const struct device *dev, bool async,
8486

8587
if (async) {
8688
/* queue suspend */
89+
#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
8790
pm->base.state = PM_DEVICE_STATE_SUSPENDING;
8891
#ifdef CONFIG_PM_DEVICE_RUNTIME_USE_SYSTEM_WQ
8992
(void)k_work_schedule(&pm->work, delay);
9093
#else
9194
(void)k_work_schedule_for_queue(&pm_device_runtime_wq, &pm->work, delay);
9295
#endif /* CONFIG_PM_DEVICE_RUNTIME_USE_SYSTEM_WQ */
96+
#endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
9397
} else {
9498
/* suspend now */
9599
ret = pm->base.action_cb(pm->dev, PM_DEVICE_ACTION_SUSPEND);
@@ -109,6 +113,7 @@ static int runtime_suspend(const struct device *dev, bool async,
109113
return ret;
110114
}
111115

116+
#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
112117
static void runtime_suspend_work(struct k_work *work)
113118
{
114119
int ret;
@@ -138,6 +143,7 @@ static void runtime_suspend_work(struct k_work *work)
138143

139144
__ASSERT(ret == 0, "Could not suspend device (%d)", ret);
140145
}
146+
#endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
141147

142148
static int get_sync_locked(const struct device *dev)
143149
{
@@ -235,6 +241,7 @@ int pm_device_runtime_get(const struct device *dev)
235241

236242
pm->base.usage++;
237243

244+
#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
238245
/*
239246
* Check if the device has a pending suspend operation (not started
240247
* yet) and cancel it. This way we avoid unnecessary operations because
@@ -260,6 +267,7 @@ int pm_device_runtime_get(const struct device *dev)
260267
(void)k_sem_take(&pm->lock, K_FOREVER);
261268
}
262269
}
270+
#endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
263271

264272
if (pm->base.usage > 1U) {
265273
goto unlock;
@@ -358,6 +366,7 @@ int pm_device_runtime_put(const struct device *dev)
358366

359367
int pm_device_runtime_put_async(const struct device *dev, k_timeout_t delay)
360368
{
369+
#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
361370
int ret;
362371

363372
if (dev->pm_base == NULL) {
@@ -378,6 +387,9 @@ int pm_device_runtime_put_async(const struct device *dev, k_timeout_t delay)
378387
SYS_PORT_TRACING_FUNC_EXIT(pm, device_runtime_put_async, dev, delay, ret);
379388

380389
return ret;
390+
#else
391+
return -ENOSYS;
392+
#endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
381393
}
382394

383395
__boot_func
@@ -449,7 +461,9 @@ int pm_device_runtime_enable(const struct device *dev)
449461
/* lazy init of PM fields */
450462
if (pm->dev == NULL) {
451463
pm->dev = dev;
464+
#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
452465
k_work_init_delayable(&pm->work, runtime_suspend_work);
466+
#endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
453467
}
454468

455469
if (pm->base.state == PM_DEVICE_STATE_ACTIVE) {
@@ -522,6 +536,7 @@ int pm_device_runtime_disable(const struct device *dev)
522536
(void)k_sem_take(&pm->lock, K_FOREVER);
523537
}
524538

539+
#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
525540
if (!k_is_pre_kernel()) {
526541
if ((pm->base.state == PM_DEVICE_STATE_SUSPENDING) &&
527542
((k_work_cancel_delayable(&pm->work) & K_WORK_RUNNING) == 0)) {
@@ -539,6 +554,7 @@ int pm_device_runtime_disable(const struct device *dev)
539554
(void)k_sem_take(&pm->lock, K_FOREVER);
540555
}
541556
}
557+
#endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
542558

543559
/* wake up the device if suspended */
544560
if (pm->base.state == PM_DEVICE_STATE_SUSPENDED) {
@@ -549,8 +565,9 @@ int pm_device_runtime_disable(const struct device *dev)
549565

550566
pm->base.state = PM_DEVICE_STATE_ACTIVE;
551567
}
552-
568+
#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
553569
clear_bit:
570+
#endif
554571
atomic_clear_bit(&pm->base.flags, PM_DEVICE_FLAG_RUNTIME_ENABLED);
555572

556573
unlock:
@@ -580,6 +597,7 @@ int pm_device_runtime_usage(const struct device *dev)
580597
return dev->pm_base->usage;
581598
}
582599

600+
#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
583601
#ifdef CONFIG_PM_DEVICE_RUNTIME_USE_DEDICATED_WQ
584602

585603
static int pm_device_runtime_wq_init(void)
@@ -599,3 +617,4 @@ SYS_INIT(pm_device_runtime_wq_init, POST_KERNEL,
599617
CONFIG_PM_DEVICE_RUNTIME_DEDICATED_WQ_INIT_PRIO);
600618

601619
#endif /* CONFIG_PM_DEVICE_RUNTIME_USE_DEDICATED_WQ */
620+
#endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */

tests/subsys/pm/device_runtime_api/src/main.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
#include "test_driver.h"
1212
#include "zephyr/sys/util_macro.h"
1313

14+
1415
static const struct device *test_dev;
16+
17+
#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
1518
static struct k_thread get_runner_td;
1619
K_THREAD_STACK_DEFINE(get_runner_stack, 1024);
1720

@@ -32,6 +35,7 @@ static void get_runner(void *arg1, void *arg2, void *arg3)
3235
ret = pm_device_runtime_get(test_dev);
3336
zassert_equal(ret, 0);
3437
}
38+
#endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
3539

3640
void test_api_setup(void *data)
3741
{
@@ -44,7 +48,11 @@ void test_api_setup(void *data)
4448
ret = pm_device_runtime_put(test_dev);
4549
zassert_equal(ret, 0);
4650
ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
51+
#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
4752
zassert_equal(ret, 0);
53+
#else
54+
zassert_equal(ret, -ENOSYS);
55+
#endif
4856

4957
/* enable runtime PM */
5058
ret = pm_device_runtime_enable(test_dev);
@@ -131,6 +139,7 @@ ZTEST(device_runtime_api, test_api)
131139
zassert_equal(ret, -EALREADY);
132140
zassert_equal(pm_device_runtime_usage(test_dev), 0);
133141

142+
#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
134143
/*** get + asynchronous put until suspended ***/
135144

136145
/* usage: 0, +1, resume: yes */
@@ -262,6 +271,7 @@ ZTEST(device_runtime_api, test_api)
262271
ret = pm_device_runtime_disable(test_dev);
263272
zassert_equal(ret, 0);
264273
zassert_equal(pm_device_runtime_usage(test_dev), -ENOTSUP);
274+
#endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
265275
}
266276

267277
DEVICE_DEFINE(pm_unsupported_device, "PM Unsupported", NULL, NULL, NULL, NULL,
@@ -276,7 +286,11 @@ ZTEST(device_runtime_api, test_unsupported)
276286
zassert_equal(pm_device_runtime_disable(dev), -ENOTSUP, "");
277287
zassert_equal(pm_device_runtime_get(dev), 0, "");
278288
zassert_equal(pm_device_runtime_put(dev), 0, "");
279-
zassert_false(pm_device_runtime_put_async(dev, K_NO_WAIT), "");
289+
#ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
290+
zassert_equal(pm_device_runtime_put_async(dev, K_NO_WAIT), 0, "");
291+
#else
292+
zassert_equal(pm_device_runtime_put_async(dev, K_NO_WAIT), -ENOSYS, "");
293+
#endif
280294
}
281295

282296
int dev_pm_control(const struct device *dev, enum pm_device_action action)

tests/subsys/pm/device_runtime_api/testcase.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,8 @@ tests:
1515
- native_sim
1616
extra_configs:
1717
- CONFIG_PM_DEVICE_RUNTIME_USE_DEDICATED_WQ=y
18+
pm.device_runtime.async_disabled.api:
19+
platform_allow:
20+
- native_sim
21+
extra_configs:
22+
- CONFIG_PM_DEVICE_RUNTIME_ASYNC=n

0 commit comments

Comments
 (0)