You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by pk...@apache.org on 2022/03/30 07:00:20 UTC

[incubator-nuttx] 06/13: rptun: add rpmsg_wait/post support for recursive dispatch

This is an automated email from the ASF dual-hosted git repository.

pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit be49f6b87c40248a93129458c34e02a1cf5a126e
Author: ligd <li...@xiaomi.com>
AuthorDate: Tue Jan 18 15:51:24 2022 +0800

    rptun: add rpmsg_wait/post support for recursive dispatch
    
    Signed-off-by: ligd <li...@xiaomi.com>
---
 drivers/rptun/Kconfig         |   4 --
 drivers/rptun/rptun.c         | 152 +++++++++++++++++++++++++++++++++---------
 include/nuttx/rptun/openamp.h |   3 +
 3 files changed, 125 insertions(+), 34 deletions(-)

diff --git a/drivers/rptun/Kconfig b/drivers/rptun/Kconfig
index d7bf6b5..a3e4487 100644
--- a/drivers/rptun/Kconfig
+++ b/drivers/rptun/Kconfig
@@ -34,10 +34,6 @@ config RPTUN_STACKSIZE
 	depends on RPTUN_THREAD
 	default 4096
 
-config RPTUN_RECURSIVE_DISPATCH
-	bool "rptun recursive dispatch"
-	default y
-
 config RPTUN_LOADER
 	bool "rptun loader support"
 	default n
diff --git a/drivers/rptun/rptun.c b/drivers/rptun/rptun.c
index 3323e66..f016b02 100644
--- a/drivers/rptun/rptun.c
+++ b/drivers/rptun/rptun.c
@@ -69,10 +69,10 @@ struct rptun_priv_s
   struct rpmsg_virtio_shm_pool shm_pool;
   struct metal_list            bind;
   struct metal_list            node;
+  sem_t                        sem;
 #ifdef CONFIG_RPTUN_WORKQUEUE
   struct work_s                work;
 #else
-  sem_t                        sem;
   int                          tid;
 #endif
   unsigned long                cmd;
@@ -119,7 +119,7 @@ rptun_get_mem(FAR struct remoteproc *rproc,
               metal_phys_addr_t da,
               FAR void *va, size_t size,
               FAR struct remoteproc_mem *buf);
-static int rptun_can_recursive(FAR struct remoteproc *rproc);
+static int rptun_wait_tx_buffer(FAR struct remoteproc *rproc);
 
 static void rptun_ns_bind(FAR struct rpmsg_device *rdev,
                           FAR const char *name, uint32_t dest);
@@ -152,14 +152,14 @@ static metal_phys_addr_t rptun_da_to_pa(FAR struct rptun_dev_s *dev,
 
 static struct remoteproc_ops g_rptun_ops =
 {
-  .init          = rptun_init,
-  .remove        = rptun_remove,
-  .config        = rptun_config,
-  .start         = rptun_start,
-  .stop          = rptun_stop,
-  .notify        = rptun_notify,
-  .get_mem       = rptun_get_mem,
-  .can_recursive = rptun_can_recursive,
+  .init           = rptun_init,
+  .remove         = rptun_remove,
+  .config         = rptun_config,
+  .start          = rptun_start,
+  .stop           = rptun_stop,
+  .notify         = rptun_notify,
+  .get_mem        = rptun_get_mem,
+  .wait_tx_buffer = rptun_wait_tx_buffer,
 };
 
 static const struct file_operations g_rptun_devops =
@@ -274,11 +274,39 @@ static void rptun_worker(FAR void *arg)
   remoteproc_get_notification(&priv->rproc, RPTUN_NOTIFY_ALL);
 }
 
+static void rptun_post(FAR struct rptun_priv_s *priv)
+{
+  int semcount;
+
+  nxsem_get_value(&priv->sem, &semcount);
+  while (semcount++ < 1)
+    {
+      nxsem_post(&priv->sem);
+    }
+}
+
 #ifdef CONFIG_RPTUN_WORKQUEUE
 static void rptun_wakeup(FAR struct rptun_priv_s *priv)
 {
   work_queue(HPWORK, &priv->work, rptun_worker, priv, 0);
+  rptun_post(priv);
+}
+
+static void rptun_in_recursive(int tid, FAR void *arg)
+{
+  if (gettid() == tid)
+    {
+      *((FAR bool *)arg) = true;
+    }
+}
+
+static bool rptun_is_recursive(FAR struct rptun_priv_s *priv)
+{
+  bool in = false;
+  work_foreach(HPWORK, rptun_in_recursive, &in);
+  return in;
 }
+
 #else
 static int rptun_thread(int argc, FAR char *argv[])
 {
@@ -298,13 +326,12 @@ static int rptun_thread(int argc, FAR char *argv[])
 
 static void rptun_wakeup(FAR struct rptun_priv_s *priv)
 {
-  int semcount;
+  rptun_post(priv);
+}
 
-  nxsem_get_value(&priv->sem, &semcount);
-  if (semcount < 1)
-    {
-      nxsem_post(&priv->sem);
-    }
+static bool rptun_is_recursive(FAR struct rptun_priv_s *priv)
+{
+  return gettid() == priv->tid;
 }
 #endif
 
@@ -434,16 +461,21 @@ rptun_get_mem(FAR struct remoteproc *rproc,
   return buf;
 }
 
-static int rptun_can_recursive(FAR struct remoteproc *rproc)
+static int rptun_wait_tx_buffer(FAR struct remoteproc *rproc)
 {
-#ifndef CONFIG_RPTUN_RECURSIVE_DISPATCH
-  return false;
-#elif defined(CONFIG_RPTUN_WORKQUEUE)
-  return work_in_context(HPWORK);
-#else
   FAR struct rptun_priv_s *priv = rproc->priv;
-  return gettid() == priv->tid;
-#endif
+
+  if (!rptun_is_recursive(priv))
+    {
+      return -EAGAIN;
+    }
+
+  /* Wait to wakeup */
+
+  nxsem_wait(&priv->sem);
+  rptun_worker(priv);
+
+  return 0;
 }
 
 static void *rptun_get_priv_by_rdev(FAR struct rpmsg_device *rdev)
@@ -453,6 +485,11 @@ static void *rptun_get_priv_by_rdev(FAR struct rpmsg_device *rdev)
   struct remoteproc_virtio *rpvdev;
   struct remoteproc *rproc;
 
+  if (!rdev)
+    {
+      return NULL;
+    }
+
   rvdev = metal_container_of(rdev, struct rpmsg_virtio_device, rdev);
   vdev  = rvdev->vdev;
   if (!vdev)
@@ -656,6 +693,10 @@ static int rptun_dev_start(FAR struct remoteproc *rproc)
 
   rptun_lock();
 
+  /* Register callback to mbox for receiving remote message */
+
+  RPTUN_REGISTER_CALLBACK(priv->dev, rptun_callback, priv);
+
   /* Add priv to list */
 
   metal_list_add_tail(&g_rptun_priv, &priv->node);
@@ -673,10 +714,6 @@ static int rptun_dev_start(FAR struct remoteproc *rproc)
 
   rptun_unlock();
 
-  /* Register callback to mbox for receiving remote message */
-
-  RPTUN_REGISTER_CALLBACK(priv->dev, rptun_callback, priv);
-
   return 0;
 }
 
@@ -880,6 +917,60 @@ static metal_phys_addr_t rptun_da_to_pa(FAR struct rptun_dev_s *dev,
  * Public Functions
  ****************************************************************************/
 
+int rpmsg_wait(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem)
+{
+  FAR struct rptun_priv_s *priv;
+  int ret;
+
+  if (!ept)
+    {
+      return -EINVAL;
+    }
+
+  priv = rptun_get_priv_by_rdev(ept->rdev);
+  if (!priv || !rptun_is_recursive(priv))
+    {
+      return nxsem_wait_uninterruptible(sem);
+    }
+
+  while (1)
+    {
+      ret = nxsem_trywait(sem);
+      if (ret >= 0)
+        {
+          break;
+        }
+
+      nxsem_wait(&priv->sem);
+      rptun_worker(priv);
+    }
+
+  return ret;
+}
+
+int rpmsg_post(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem)
+{
+  FAR struct rptun_priv_s *priv;
+  int semcount;
+  int ret;
+
+  if (!ept)
+    {
+      return -EINVAL;
+    }
+
+  nxsem_get_value(sem, &semcount);
+  ret = nxsem_post(sem);
+
+  priv = rptun_get_priv_by_rdev(ept->rdev);
+  if (priv && semcount >= 0)
+    {
+      rptun_post(priv);
+    }
+  
+  return ret;
+}
+
 FAR const char *rpmsg_get_cpuname(FAR struct rpmsg_device *rdev)
 {
   FAR struct rptun_priv_s *priv = rptun_get_priv_by_rdev(rdev);
@@ -1022,6 +1113,8 @@ int rptun_initialize(FAR struct rptun_dev_s *dev)
       priv->cmd = RPTUNIOC_START;
       work_queue(HPWORK, &priv->work, rptun_worker, priv, 0);
     }
+
+  nxsem_init(&priv->sem, 0, 0);
 #else
   if (RPTUN_IS_AUTOSTART(dev))
     {
@@ -1033,8 +1126,6 @@ int rptun_initialize(FAR struct rptun_dev_s *dev)
       nxsem_init(&priv->sem, 0, 0);
     }
 
-  nxsem_set_protocol(&priv->sem, SEM_PRIO_NONE);
-
   snprintf(arg1, sizeof(arg1), "0x%" PRIxPTR, (uintptr_t)priv);
   argv[0] = (void *)RPTUN_GET_CPUNAME(dev);
   argv[1] = arg1;
@@ -1049,6 +1140,7 @@ int rptun_initialize(FAR struct rptun_dev_s *dev)
       goto err_driver;
     }
 #endif
+  nxsem_set_protocol(&priv->sem, SEM_PRIO_NONE);
 
   return OK;
 
diff --git a/include/nuttx/rptun/openamp.h b/include/nuttx/rptun/openamp.h
index 8a96b98..365e2bc 100644
--- a/include/nuttx/rptun/openamp.h
+++ b/include/nuttx/rptun/openamp.h
@@ -54,6 +54,9 @@ extern "C"
 #define EXTERN extern
 #endif
 
+int rpmsg_wait(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem);
+int rpmsg_post(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem);
+
 const char *rpmsg_get_cpuname(FAR struct rpmsg_device *rdev);
 int rpmsg_register_callback(FAR void *priv,
                             rpmsg_dev_cb_t device_created,