[PATCH] PM: sleep: Use complete() instead of complete_all() in device_pm_sleep_init()

Jiakai Xu posted 1 patch 1 month ago
drivers/base/power/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH] PM: sleep: Use complete() instead of complete_all() in device_pm_sleep_init()
Posted by Jiakai Xu 1 month ago
device_pm_sleep_init() is called during device initialization via
device_initialize(), where no threads can be waiting on
dev->power.completion. Using complete_all() here triggers a false-positive
WARNING from lockdep_assert_RT_in_threaded_ctx() when
CONFIG_PROVE_RAW_LOCK_NESTING is enabled, because holding a raw_spinlock
elsewhere in the call chain makes lockdep_hardirq_context() appear non-zero.

Replace complete_all() with complete(), which is semantically equivalent
when no waiters exist (sets done to 1 instead of UINT_MAX). The completion
is always reinitialized via reinit_completion() in dpm_clear_async_state()
before each suspend/resume phase, so this initialization value has no
effect on later suspend operations.

Signed-off-by: Jiakai Xu <xujiakai24@mails.ucas.ac.cn>
Fixes: 152e1d592071c ("PM: Prevent waiting forever on asynchronous resume after failing suspend")
---
 drivers/base/power/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index e1b550664bab..7a948dd134df 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -115,7 +115,7 @@ void device_pm_sleep_init(struct device *dev)
 	dev->power.is_noirq_suspended = false;
 	dev->power.is_late_suspended = false;
 	init_completion(&dev->power.completion);
-	complete_all(&dev->power.completion);
+	complete(&dev->power.completion);
 	dev->power.wakeup = NULL;
 	INIT_LIST_HEAD(&dev->power.entry);
 }
-- 
2.34.1
Re: [PATCH] PM: sleep: Use complete() instead of complete_all() in device_pm_sleep_init()
Posted by Rafael J. Wysocki 1 month ago
On Sat, May 9, 2026 at 11:27 AM Jiakai Xu <xujiakai24@mails.ucas.ac.cn> wrote:
>
> device_pm_sleep_init() is called during device initialization via
> device_initialize(), where no threads can be waiting on
> dev->power.completion. Using complete_all() here triggers a false-positive
> WARNING from lockdep_assert_RT_in_threaded_ctx() when
> CONFIG_PROVE_RAW_LOCK_NESTING is enabled, because holding a raw_spinlock
> elsewhere in the call chain makes lockdep_hardirq_context() appear non-zero.
>
> Replace complete_all() with complete(), which is semantically equivalent
> when no waiters exist (sets done to 1 instead of UINT_MAX). The completion
> is always reinitialized via reinit_completion() in dpm_clear_async_state()
> before each suspend/resume phase, so this initialization value has no
> effect on later suspend operations.
>
> Signed-off-by: Jiakai Xu <xujiakai24@mails.ucas.ac.cn>
> Fixes: 152e1d592071c ("PM: Prevent waiting forever on asynchronous resume after failing suspend")
> ---
>  drivers/base/power/main.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
> index e1b550664bab..7a948dd134df 100644
> --- a/drivers/base/power/main.c
> +++ b/drivers/base/power/main.c
> @@ -115,7 +115,7 @@ void device_pm_sleep_init(struct device *dev)
>         dev->power.is_noirq_suspended = false;
>         dev->power.is_late_suspended = false;
>         init_completion(&dev->power.completion);
> -       complete_all(&dev->power.completion);
> +       complete(&dev->power.completion);
>         dev->power.wakeup = NULL;
>         INIT_LIST_HEAD(&dev->power.entry);
>  }
> --

sashiko.dev complains about this one:

https://sashiko.dev/#/patchset/20260509092707.3426533-1-xujiakai24%40mails.ucas.ac.cn

and I think that it has a point.

Before this change, dpm_wait() needs to be updated to skip devices
with no PM support.
Re: [PATCH] PM: sleep: Use complete() instead of complete_all() in device_pm_sleep_init()
Posted by Jiakai Xu 1 month ago
> sashiko.dev complains about this one:
> 
> https://sashiko.dev/#/patchset/20260509092707.3426533-1-xujiakai24%40mails.ucas.ac.cn
> 
> and I think that it has a point.
> 
> Before this change, dpm_wait() needs to be updated to skip devices
> with no PM support.

Thanks for your review! I will send a v2 patch later.

Best regards,
Jiakai
Re: [PATCH] PM: sleep: Use complete() instead of complete_all() in device_pm_sleep_init()
Posted by Jiakai Xu 1 month ago
I found this issue through fuzzing.

Here is the full crash report produced by the fuzzer:

WARNING: kernel/sched/completion.c:76 at complete_all+0x1f2/0x264 kernel/sched/completion.c:76, CPU#3: kworker/u16:13/5039
Modules linked in:
CPU: 3 UID: 0 PID: 5039 Comm: kworker/u16:13 Tainted: G        W           7.1.0-rc1-gdb909bd7986c #1 PREEMPT 
Tainted: [W]=WARN
Hardware name: riscv-virtio,qemu (DT)
Workqueue: netns cleanup_net
epc : complete_all+0x1f2/0x264 kernel/sched/completion.c:76
 ra : complete_all+0x1f2/0x264 kernel/sched/completion.c:76
epc : ffffffff802db0ac ra : ffffffff802db0ac sp : ff20000003c572a0
 gp : ffffffff8a395420 tp : ff6000008c948000 t0 : ff20000003c56e54
 t1 : ffebffff1ff55119 t2 : 6874206e6920746f s0 : ff20000003c572e0
 s1 : ff600000b34ec8e0 a0 : ff6000008c948008 a1 : ffffffff86f7c300
 a2 : 0000000000000002 a3 : ffffffff80154b18 a4 : 0000000000000000
 a5 : 0000000000000000 a6 : 0000000000000003 a7 : ff600000ffaa88cb
 s2 : ff6000008c949000 s3 : ff600000ffa4c4a8 s4 : ffffffff9176ce88
 s5 : 0000000000000000 s6 : 0000000000000000 s7 : 1fe400000078ae6c
 s8 : ff600000866ed8a0 s9 : ff600000b34ecb88 s10: ff600000866ed8b0
 s11: ffffffff87b9a460 t3 : ffffffff8835de50 t4 : ffebffff1ff55119
 t5 : ffebffff1ff5511a t6 : 0000000000000002 ssp : 0000000000000000
status: 0000000200000120 badaddr: ffffffff802db0ac cause: 0000000000000003
[<ffffffff802db0ac>] complete_all+0x1f2/0x264 kernel/sched/completion.c:76
[<ffffffff82d8e1b4>] device_pm_remove+0x92/0x374 drivers/base/power/main.c:172
[<ffffffff82d36452>] device_del+0x32a/0x898 drivers/base/core.c:3896
[<ffffffff85561bac>] netdev_unregister_kobject+0x2da/0x4de net/core/net-sysfs.c:2314
[<ffffffff85458cdc>] unregister_netdevice_many_notify+0x15ea/0x244a net/core/dev.c:12453
[<ffffffff8545cbd6>] unregister_netdevice_many net/core/dev.c:12481 [inline]
[<ffffffff8545cbd6>] default_device_exit_batch+0x678/0x8b0 net/core/dev.c:13073
[<ffffffff853e8cbe>] ops_exit_list net/core/net_namespace.c:205 [inline]
[<ffffffff853e8cbe>] ops_undo_list+0x3e8/0x9dc net/core/net_namespace.c:252
[<ffffffff853ed65e>] cleanup_net+0x43a/0x8dc net/core/net_namespace.c:702
[<ffffffff801d597e>] process_one_work+0x9a6/0x21ba kernel/workqueue.c:3302
[<ffffffff801d91ec>] process_scheduled_works kernel/workqueue.c:3385 [inline]
[<ffffffff801d91ec>] worker_thread+0x5cc/0xde6 kernel/workqueue.c:3466
[<ffffffff801f7d58>] kthread+0x336/0x47e kernel/kthread.c:436
[<ffffffff8006a302>] ret_from_fork_kernel+0x94/0xfce arch/riscv/kernel/process.c:230
[<ffffffff86726926>] ret_from_fork_kernel_asm+0x16/0x18 arch/riscv/kernel/entry.S:363

<<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>>

[<ffffffff801d597e>] process_one_work+0x9a6/0x21ba
[<ffffffff801d91ec>] worker_thread+0x5cc/0xde6
[<ffffffff801f7d58>] kthread+0x336/0x47e
[<ffffffff8006a302>] ret_from_fork_kernel+0x94/0xfce
[<ffffffff86726926>] ret_from_fork_kernel_asm+0x16/0x18
Kernel panic - not syncing: kernel: panic_on_warn set ...
CPU: 3 UID: 0 PID: 5039 Comm: kworker/u16:13 Tainted: G        W           7.1.0-rc1-gdb909bd7986c #1 PREEMPT 
Tainted: [W]=WARN
Hardware name: riscv-virtio,qemu (DT)
Workqueue: netns cleanup_net
Call Trace:
[<ffffffff8007c91c>] dump_backtrace+0x2e/0x3c
[<ffffffff800032ce>] show_stack+0x30/0x3c
[<ffffffff80060fa0>] dump_stack_lvl+0x10c/0x1a2
[<ffffffff80061052>] dump_stack+0x1c/0x24
[<ffffffff80003afc>] vpanic+0x362/0x7b2
[<ffffffff80003fec>] trace_suspend_resume+0x0/0x418
[<ffffffff801555fc>] check_panic_on_warn+0xc0/0xe4
[<ffffffff80155b08>] __warn+0x348/0x694
[<ffffffff8665bd94>] __report_bug+0x1f4/0x322
[<ffffffff8665c2e4>] report_bug+0xee/0x2be
[<ffffffff8007b8e8>] handle_break+0x134/0x32a
[<ffffffff866fa394>] do_trap_break+0x228/0x440
[<ffffffff867267f6>] handle_exception+0x15e/0x16a
[<ffffffff802db0ac>] complete_all+0x1f2/0x264
[<ffffffff82d8e1b4>] device_pm_remove+0x92/0x374
[<ffffffff82d36452>] device_del+0x32a/0x898
[<ffffffff85561bac>] netdev_unregister_kobject+0x2da/0x4de
[<ffffffff85458cdc>] unregister_netdevice_many_notify+0x15ea/0x244a
[<ffffffff8545cbd6>] default_device_exit_batch+0x678/0x8b0
[<ffffffff853e8cbe>] ops_undo_list+0x3e8/0x9dc
[<ffffffff853ed65e>] cleanup_net+0x43a/0x8dc
[<ffffffff801d597e>] process_one_work+0x9a6/0x21ba
[<ffffffff801d91ec>] worker_thread+0x5cc/0xde6
[<ffffffff801f7d58>] kthread+0x336/0x47e
[<ffffffff8006a302>] ret_from_fork_kernel+0x94/0xfce
[<ffffffff86726926>] ret_from_fork_kernel_asm+0x16/0x18
SMP: stopping secondary CPUs

<<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>>