forked from openvela/nuttx
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>
|
||
|---|---|---|
| .. | ||
| CMakeLists.txt | ||
| Kconfig | ||
| Make.defs | ||
| rpmsg.c | ||
| rpmsg.h | ||
| rpmsg_char.c | ||
| rpmsg_char.h | ||
| rpmsg_ping.c | ||
| rpmsg_ping.h | ||
| rpmsg_port.c | ||
| rpmsg_port.h | ||
| rpmsg_port_spi.c | ||
| rpmsg_port_spi_slave.c | ||
| rpmsg_port_uart.c | ||
| rpmsg_procfs.c | ||
| rpmsg_procfs.h | ||
| rpmsg_router.h | ||
| rpmsg_router_edge.c | ||
| rpmsg_router_hub.c | ||
| rpmsg_test.c | ||
| rpmsg_test.h | ||
| rpmsg_trace.c | ||
| rpmsg_trace.h | ||
| rpmsg_virtio.c | ||
| rpmsg_wakelock.c | ||
| rpmsg_wakelock.h | ||