From 068353bba735e84656c4a30ce75261be683e6268 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Thu, 15 Jul 2021 15:47:42 +0800 Subject: [PATCH] drivers/rptun: Start/stop remote processor in the background thread to avoid blocking the main thread initialization process Signed-off-by: Xiang Xiao Change-Id: Ib8ab2a661ee9540bb03d9d4d851a8d8ee212404e --- drivers/rptun/rptun.c | 94 +++++++++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/drivers/rptun/rptun.c b/drivers/rptun/rptun.c index 14a115ba0d..3711952c0f 100644 --- a/drivers/rptun/rptun.c +++ b/drivers/rptun/rptun.c @@ -48,6 +48,8 @@ # define ALIGN_UP(s, a) (((s) + (a) - 1) & ~((a) - 1)) #endif +#define RPTUNIOC_NONE 0 + /**************************************************************************** * Private Types ****************************************************************************/ @@ -61,6 +63,7 @@ struct rptun_priv_s struct metal_list bind; struct metal_list node; sem_t sem; + unsigned long cmd; }; struct rptun_bind_s @@ -169,19 +172,37 @@ static int rptun_thread(int argc, FAR char *argv[]) FAR struct rptun_priv_s *priv; priv = (FAR struct rptun_priv_s *)((uintptr_t)strtoul(argv[2], NULL, 0)); + remoteproc_init(&priv->rproc, &g_rptun_ops, priv); while (1) { nxsem_wait_uninterruptible(&priv->sem); - remoteproc_get_notification(&priv->rproc, RPTUN_NOTIFY_ALL); + switch (priv->cmd) + { + case RPTUNIOC_START: + if (priv->rproc.state == RPROC_OFFLINE) + { + rptun_dev_start(&priv->rproc); + } + break; + + case RPTUNIOC_STOP: + if (priv->rproc.state != RPROC_OFFLINE) + { + rptun_dev_stop(&priv->rproc); + } + break; + } + + priv->cmd = RPTUNIOC_NONE; + remoteproc_get_notification(&priv->rproc, RPTUN_NOTIFY_ALL); } return 0; } -static int rptun_callback(FAR void *arg, uint32_t vqid) +static void rptun_wakeup(FAR struct rptun_priv_s *priv) { - FAR struct rptun_priv_s *priv = arg; int semcount; nxsem_get_value(&priv->sem, &semcount); @@ -189,7 +210,11 @@ static int rptun_callback(FAR void *arg, uint32_t vqid) { nxsem_post(&priv->sem); } +} +static int rptun_callback(FAR void *arg, uint32_t vqid) +{ + rptun_wakeup(arg); return OK; } @@ -553,22 +578,18 @@ static int rptun_dev_ioctl(FAR struct file *filep, int cmd, { FAR struct inode *inode = filep->f_inode; FAR struct rptun_priv_s *priv = inode->i_private; - int ret = -ENOTTY; + int ret = OK; switch (cmd) { case RPTUNIOC_START: - if (priv->rproc.state == RPROC_OFFLINE) - { - ret = rptun_dev_start(&priv->rproc); - } + case RPTUNIOC_STOP: + priv->cmd = cmd; + rptun_wakeup(priv); break; - case RPTUNIOC_STOP: - if (priv->rproc.state != RPROC_OFFLINE) - { - ret = rptun_dev_stop(&priv->rproc); - } + default: + ret = -ENOTTY; break; } @@ -802,7 +823,7 @@ int rptun_initialize(FAR struct rptun_dev_s *dev) int ret; ret = metal_init(¶ms); - if (ret) + if (ret < 0) { return ret; } @@ -810,18 +831,32 @@ int rptun_initialize(FAR struct rptun_dev_s *dev) priv = kmm_zalloc(sizeof(struct rptun_priv_s)); if (priv == NULL) { - return -ENOMEM; + ret = -ENOMEM; + goto err_mem; + } + + priv->dev = dev; + if (RPTUN_IS_AUTOSTART(dev)) + { + priv->cmd = RPTUNIOC_START; + } + + metal_list_init(&priv->bind); + nxsem_init(&priv->sem, 0, RPTUN_IS_AUTOSTART(dev) ? 1 : 0); + nxsem_set_protocol(&priv->sem, SEM_PRIO_NONE); + + snprintf(name, 32, "/dev/rptun/%s", RPTUN_GET_CPUNAME(dev)); + ret = register_driver(name, &g_rptun_devops, 0666, priv); + if (ret < 0) + { + goto err_driver; } snprintf(arg1, 16, "0x%" PRIxPTR, (uintptr_t)priv); - argv[0] = (void *)RPTUN_GET_CPUNAME(dev); argv[1] = arg1; argv[2] = NULL; - nxsem_init(&priv->sem, 0, 0); - nxsem_set_protocol(&priv->sem, SEM_PRIO_NONE); - ret = kthread_create("rptun", CONFIG_RPTUN_PRIORITY, CONFIG_RPTUN_STACKSIZE, @@ -829,22 +864,21 @@ int rptun_initialize(FAR struct rptun_dev_s *dev) argv); if (ret < 0) { - kmm_free(priv); - return ret; + goto err_thread; } - priv->dev = dev; + return OK; - metal_list_init(&priv->bind); - remoteproc_init(&priv->rproc, &g_rptun_ops, priv); +err_thread: + unregister_driver(name); - if (RPTUN_IS_AUTOSTART(dev)) - { - rptun_dev_start(&priv->rproc); - } +err_driver: + nxsem_destroy(&priv->sem); + kmm_free(priv); - snprintf(name, 32, "/dev/rptun/%s", RPTUN_GET_CPUNAME(dev)); - return register_driver(name, &g_rptun_devops, 0666, priv); +err_mem: + metal_finish(); + return ret; } int rptun_boot(FAR const char *cpuname)