Re: [PATCH] PM: runtime: Allocate pm_wq with WQ_HIGHPRI
From: Rafael J. Wysocki (Intel)
Date: Tue Oct 27 2026 - 07:14:08 EST
On Tue, Oct 27, 2026 at 10:06 AM Chung-Kai (Michael) Mei
<chungkai@xxxxxxxxxx> wrote:
>
> Asynchronous runtime PM work (pm_runtime_work()) and genpd power-off
> work (genpd_power_off_work_fn()) run on pm_wq. While such a work item
> executes a ->runtime_suspend() or ->runtime_resume() callback, the
> device's runtime_status is RPM_SUSPENDING or RPM_RESUMING with
> dev->power.lock dropped, and genpd_power_off_work_fn() holds the genpd
> lock.
>
> If another task calls pm_runtime_get_sync() on the device in that
> window, rpm_resume() sleeps on dev->power.wait_queue in
> TASK_UNINTERRUPTIBLE until the work item completes. A wait queue has
> no owner, so the waiter cannot lend its priority to the kworker, and
> its latency is bounded by how quickly the pm_wq worker gets CPU time.
> Because asynchronous runtime PM work is queued onto pm_wq by the PM
> core, individual drivers cannot select a different workqueue.
>
> pm_wq workers run at nice 0 and can be kept off the CPU for a long
> time by higher-weight CFS tasks. On an arm64 Android device whose GPU
> driver uses runtime PM autosuspend, render threads were observed
> blocked in rpm_resume() for 5 to 19 ms while the runtime PM callback
> itself needed less than 60 us of CPU time. For more than 99% of that
> time the pm_wq worker was runnable, preempted by nice -20 tasks.
Interesting.
> Allocate pm_wq with WQ_HIGHPRI so that its work items are served by the
> unbound high-priority worker pools (nice -20), like other
> latency-sensitive kernel workqueues such as kblockd. This does not
> change the ordering or concurrency semantics of pm_wq. It only reduces
> the time a runtime PM transition spends waiting for CPU time, and with
> it the latency seen by synchronous runtime PM callers.
I suppose that there is a measurable performance benefit from this
change, so it would be good to say what it is (say, an increased frame
rate or similar).
Essentially, we're talking about redistributing CPU time between
tasks, so some tasks will get more latency as a result of this change,
which means that it is not an obviously right thing to do.
> Signed-off-by: Chung-Kai (Michael) Mei <chungkai@xxxxxxxxxx>
> ---
> kernel/power/main.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kernel/power/main.c b/kernel/power/main.c
> index 5429e9f19b655..1e8ae76356b23 100644
> --- a/kernel/power/main.c
> +++ b/kernel/power/main.c
> @@ -1125,7 +1125,7 @@ EXPORT_SYMBOL_GPL(pm_wq);
>
> static int __init pm_start_workqueues(void)
> {
> - pm_wq = alloc_workqueue("pm", WQ_UNBOUND, 0);
> + pm_wq = alloc_workqueue("pm", WQ_UNBOUND | WQ_HIGHPRI, 0);
> if (!pm_wq)
> return -ENOMEM;
>
>
> base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
> --
> 2.56.0.307.g5fe7bd680c-goog
>
>