Problem:
The pm_wakelock_init() was called after rpmsg_queue_work() in rpmsg_virtio_probe(), which creates a race condition. The worker thread (rpmsg_virtio_start_worker) may start executing and access priv->wakelock through rpmsg_virtio_pm_action() before the wakelock is properly initialized.
This race leads to anomalous wakelock behavior where:
- The wakelock count becomes inconsistent (e.g., count=0 when it should be non-zero)
- The wakelock node remains in the PM domain queue (dq) even when count=0, violating the invariant that count=0 implies removal from the queue
Root Cause:
Call chain when worker starts before wakelock init:
rpmsg_virtio_start_worker()
-> rpmsg_init_vdev_with_config()
-> rpmsg_virtio_rx_dispatch()
-> rpmsg_virtio_tx_notify() (via callback)
-> rpmsg_virtio_pm_action()
-> pm_wakelock_stay(&priv->wakelock) // UNINITIALIZED!
Solution:
Move pm_wakelock_init() before rpmsg_queue_work() to ensure the wakelock is fully initialized before the worker thread can access it.
Impact:
Fixes PM wakelock corruption that prevented proper power management state transitions and could lead to system staying awake unnecessarily or entering low-power states prematurely.
Signed-off-by: guanyi3 <guanyi3@xiaomi.com>