This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 43d26e289094346f7a2c7d303716585b15582882 Author: wangshaoxin <[email protected]> AuthorDate: Thu Mar 13 09:50:31 2025 +0800 drivers/rptun: solve the poweroff stuck problem The rpmsg_ioctl() function will first obtain the read lock before traversing g_rpmsg, then the rpmsg_dev_destory function will try to obtain the write lock. At this time, rpmsg_ioctl does not release the read lock, resulting in a deadlock. To solve this problem, add a standardalone list for the rptun instance to avoid hold the rpmsg lock when execute rptun_poweroff() Backtrace: Thread 14 nsh_main 0 0x4412b9da in up_switch_context (tcb=0xeac03380, rtcb=0xe7f02480) at sim/sim_switchcontext.c:95 1 0x43fbe5e4 in nxsem_wait_slow (sem=0x5179d570 <g_rpmsg_lock+16>) at semaphore/sem_wait.c:170 2 0x43fbeacf in nxsem_wait (sem=0x5179d570 <g_rpmsg_lock+16>) at semaphore/sem_wait.c:272 3 0x44671a26 in down_write (rwsem=0x5179d560 <g_rpmsg_lock>) at semaphore/sem_rw.c:248 4 0x4401e255 in rpmsg_device_destory (rpmsg=0xe7b03280) at rpmsg/rpmsg.c:469 5 0x4402f5fe in rptun_dev_stop (rproc=0xe7b033e4, stop_ns=true) at rptun/rptun.c:973 6 0x4402aa28 in rptun_ioctl (rpmsg=0xe7b03280, cmd=11109, arg=0) at rptun/rptun.c:661 7 0x4401ba1e in rpmsg_dev_ioctl_ (rpmsg=0xe7b03280, cmd=11109, arg=0) at rpmsg/rpmsg.c:137 8 0x4401ee88 in rpmsg_ioctl (cpuname=0x0, cmd=11109, arg=0) at rpmsg/rpmsg.c:562 9 0x44030cb0 in rptun_poweroff (cpuname=0x0) at rptun/rptun.c:1183 10 0x43f27be2 in board_power_off (status=0) at sim/sim_head.c:211 11 0x446fd933 in boardctl (cmd=65283, arg=0) at boardctl.c:401 12 0x44313b95 in cmd_poweroff (vtbl=0xe7600e80, argc=1, argv=0xe7824350) at nsh_syscmds.c:368 13 0x442d148c in nsh_command (vtbl=0xe7600e80, argc=1, argv=0xe7824350) at nsh_command.c:1275 14 0x442f65f5 in nsh_execute (vtbl=0xe7600e80, argc=1, argv=0xe7824350, param=0xe78242b0) at nsh_parse.c:716 15 0x44304fb4 in nsh_parse_command (vtbl=0xe7600e80, cmdline=0xe7601338 "poweroff") at nsh_parse.c:2809 16 0x44305a50 in nsh_parse (vtbl=0xe7600e80, cmdline=0xe7601338 "poweroff") at nsh_parse.c:2919 17 0x442bdc91 in nsh_session (pstate=0xe7600e80, login=1, argc=1, argv=0xe7814870) at nsh_session.c:246 18 0x442bbbe5 in nsh_consolemain (argc=1, argv=0xe7814870) at nsh_consolemain.c:75 19 0x4422b4bb in nsh_main (argc=1, argv=0xe7814870) at nsh_main.c:74 20 0x440ee098 in nxtask_startup (entrypt=0x4422b39a <nsh_main>, argc=1, argv=0xe7814870) at sched/task_startup.c:72 21 0x43fa1d6e in nxtask_start () at task/task_start.c:116 22 0x4412982c in pre_start () at sim/sim_initialstate.c:53 23 0x00000000 in ?? () Signed-off-by: wangshaoxin <[email protected]> --- drivers/rptun/rptun.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/drivers/rptun/rptun.c b/drivers/rptun/rptun.c index bdc0a68bf97..05cd4e43a14 100644 --- a/drivers/rptun/rptun.c +++ b/drivers/rptun/rptun.c @@ -62,6 +62,7 @@ struct rptun_priv_s struct rpmsg_virtio_device rvdev; FAR struct rptun_dev_s *dev; struct remoteproc rproc; + struct metal_list node; struct rpmsg_virtio_shm_pool pool[2]; sem_t semtx; sem_t semrx; @@ -165,6 +166,9 @@ static const struct rpmsg_ops_s g_rptun_rpmsg_ops = rptun_get_cpuname, }; +static struct metal_list g_rptun_priv = METAL_INIT_LIST(g_rptun_priv); +static metal_mutex_t g_rptun_lock = METAL_MUTEX_INIT(g_rptun_lock); + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -1161,6 +1165,9 @@ int rptun_initialize(FAR struct rptun_dev_s *dev) pm_wakelock_init(&priv->wakelock, name, PM_IDLE_DOMAIN, PM_IDLE); #endif + metal_mutex_acquire(&g_rptun_lock); + metal_list_add_tail(&g_rptun_priv, &priv->node); + metal_mutex_release(&g_rptun_lock); return OK; err_thread: @@ -1174,17 +1181,53 @@ err_driver: return ret; } +static int rptun_ioctl_foreach(FAR const char *cpuname, int cmd, + unsigned long value) +{ + FAR struct metal_list *node; + bool needlock = !up_interrupt_context() && !sched_idletask(); + int ret = OK; + + if (needlock) + { + metal_mutex_acquire(&g_rptun_lock); + } + + metal_list_for_each(&g_rptun_priv, node) + { + FAR struct rptun_priv_s *priv; + + priv = metal_container_of(node, struct rptun_priv_s, node); + + if (!cpuname || !strcmp(RPTUN_GET_CPUNAME(priv->dev), cpuname)) + { + ret = rptun_ioctl(&priv->rpmsg, cmd, value); + if (ret < 0) + { + break; + } + } + } + + if (needlock) + { + metal_mutex_release(&g_rptun_lock); + } + + return ret; +} + int rptun_boot(FAR const char *cpuname) { - return rpmsg_ioctl(cpuname, RPTUNIOC_START, 0); + return rptun_ioctl_foreach(cpuname, RPTUNIOC_START, 0); } int rptun_poweroff(FAR const char *cpuname) { - return rpmsg_ioctl(cpuname, RPTUNIOC_STOP, 0); + return rptun_ioctl_foreach(cpuname, RPTUNIOC_STOP, 0); } int rptun_reset(FAR const char *cpuname, int value) { - return rpmsg_ioctl(cpuname, RPTUNIOC_RESET, value); + return rptun_ioctl_foreach(cpuname, RPTUNIOC_RESET, value); }
