You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/09/13 01:26:41 UTC

(nuttx) branch master updated: rpmsgblk: split multi_cmd only when it is too large to be placed into payload buffer

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


The following commit(s) were added to refs/heads/master by this push:
     new e4ad92cb03 rpmsgblk: split multi_cmd only when it is too large to be placed into payload buffer
e4ad92cb03 is described below

commit e4ad92cb0321f251a4fba9acd1f5401985991630
Author: liaoao <li...@xiaomi.com>
AuthorDate: Wed Jan 24 14:00:55 2024 +0800

    rpmsgblk: split multi_cmd only when it is too large to be placed into payload buffer
    
    Signed-off-by: liaoao <li...@xiaomi.com>
---
 drivers/misc/rpmsgblk.c        | 166 ++++++++++++++++++++++++++++++++++-------
 drivers/misc/rpmsgblk_server.c | 134 ++++++++++++++++++++++++++++++---
 2 files changed, 260 insertions(+), 40 deletions(-)

diff --git a/drivers/misc/rpmsgblk.c b/drivers/misc/rpmsgblk.c
index 5817994ae3..0db857ef1a 100644
--- a/drivers/misc/rpmsgblk.c
+++ b/drivers/misc/rpmsgblk.c
@@ -536,25 +536,30 @@ static int rpmsgblk_mmc_cmd_ioctl(FAR struct inode *inode, unsigned long arg)
   FAR struct mmc_ioc_cmd *ioc = (FAR struct mmc_ioc_cmd *)(uintptr_t)arg;
   FAR struct rpmsgblk_ioctl_s *msg;
   uint32_t space;
-  ssize_t msglen;
+  size_t arglen;
+  size_t msglen;
 
-  msglen = sizeof(*msg) + sizeof(struct mmc_ioc_cmd) +
-           ioc->blksz * ioc->blocks - 1;
+  arglen = sizeof(struct mmc_ioc_cmd);
+  if (ioc->write_flag)
+    {
+      arglen += ioc->blksz * ioc->blocks;
+    }
 
+  msglen = sizeof(*msg) + arglen - 1;
   msg = rpmsgblk_get_tx_payload_buffer(priv, &space);
   if (msg == NULL)
     {
       return -ENOMEM;
     }
 
-  DEBUGASSERT(space > msglen);
+  DEBUGASSERT(space >= msglen);
 
   msg->request = MMC_IOC_CMD;
   msg->arg     = arg;
-  msg->arglen  = sizeof(struct mmc_ioc_cmd) + ioc->blksz * ioc->blocks;
+  msg->arglen  = arglen;
 
   memcpy(msg->buf, ioc, sizeof(*ioc));
-  if (ioc->data_ptr)
+  if (ioc->data_ptr && ioc->write_flag)
     {
       memcpy(msg->buf + sizeof(*ioc), (FAR void *)(uintptr_t)ioc->data_ptr,
              ioc->blksz * ioc->blocks);
@@ -578,22 +583,85 @@ static int rpmsgblk_mmc_cmd_ioctl(FAR struct inode *inode, unsigned long arg)
 static int rpmsgblk_mmc_multi_cmd_ioctl(FAR struct inode *inode,
                                         unsigned long arg)
 {
+  FAR struct rpmsgblk_s *priv = inode->i_private;
   FAR struct mmc_ioc_multi_cmd *mioc =
     (FAR struct mmc_ioc_multi_cmd *)(uintptr_t)arg;
-  int ret = 0;
+  FAR struct rpmsgblk_ioctl_s *msg;
+  size_t arglen;
+  size_t msglen;
+  size_t rsplen;
   uint64_t i;
 
+  arglen = sizeof(struct mmc_ioc_multi_cmd) +
+           mioc->num_of_cmds * sizeof(struct mmc_ioc_cmd);
+  rsplen = arglen;
   for (i = 0; i < mioc->num_of_cmds; i++)
     {
-      ret = rpmsgblk_mmc_cmd_ioctl(inode,
-        (unsigned long)(uintptr_t)&mioc->cmds[i]);
-      if (ret < 0)
+      if (mioc->cmds[i].data_ptr && mioc->cmds[i].write_flag)
         {
-          return ret;
+          arglen += mioc->cmds[i].blksz * mioc->cmds[i].blocks;
+        }
+      else
+        {
+          rsplen += mioc->cmds[i].blksz * mioc->cmds[i].blocks;
         }
     }
 
-  return ret;
+  /* When multi cmds are read cmd, it also needs to be split if the rsp
+   * msg is too large.
+   */
+
+  msglen = sizeof(*msg) + arglen - 1;
+  rsplen += sizeof(*msg) - 1;
+  if (MAX(msglen, rsplen) > rpmsg_virtio_get_buffer_size(priv->ept.rdev))
+    {
+      int ret = 0;
+
+      for (i = 0; i < mioc->num_of_cmds; i++)
+        {
+          ret = rpmsgblk_mmc_cmd_ioctl(inode,
+            (unsigned long)(uintptr_t)&mioc->cmds[i]);
+          if (ret < 0)
+            {
+              return ret;
+            }
+        }
+
+      return ret;
+    }
+  else
+    {
+      size_t off = sizeof(struct mmc_ioc_multi_cmd) +
+                   mioc->num_of_cmds * sizeof(struct mmc_ioc_cmd);
+      uint32_t space;
+
+      msg = rpmsgblk_get_tx_payload_buffer(priv, &space);
+      if (msg == NULL)
+        {
+          return -ENOMEM;
+        }
+
+      DEBUGASSERT(space >= msglen);
+
+      msg->request = MMC_IOC_MULTI_CMD;
+      msg->arg     = arg;
+      msg->arglen  = arglen;
+
+      memcpy(msg->buf, mioc, off);
+      for (i = 0; i < mioc->num_of_cmds; i++)
+        {
+          if (mioc->cmds[i].data_ptr && mioc->cmds[i].write_flag)
+            {
+              memcpy(msg->buf + off,
+                     (FAR void *)(uintptr_t)mioc->cmds[i].data_ptr,
+                     mioc->cmds[i].blksz * mioc->cmds[i].blocks);
+              off += mioc->cmds[i].blksz * mioc->cmds[i].blocks;
+            }
+        }
+
+      return rpmsgblk_send_recv(priv, RPMSGBLK_IOCTL, false, &msg->header,
+                                msglen, (FAR void *)arg);
+    }
 }
 
 /****************************************************************************
@@ -625,7 +693,7 @@ static int rpmsgblk_default_ioctl(FAR struct inode *inode, int cmd,
       return -ENOMEM;
     }
 
-  DEBUGASSERT(space > msglen);
+  DEBUGASSERT(space >= msglen);
 
   msg->request = cmd;
   msg->arg     = arg;
@@ -925,6 +993,57 @@ static int rpmsgblk_geometry_handler(FAR struct rpmsg_endpoint *ept,
   return rpmsg_post(ept, &cookie->sem);
 }
 
+/****************************************************************************
+ * Name: rpmsgblk_mmc_cmd_handler
+ ****************************************************************************/
+
+static void rpmsgblk_mmc_cmd_handler(FAR struct rpmsgblk_cookie_s *cookie,
+                                     FAR struct rpmsgblk_ioctl_s *rsp)
+{
+  FAR struct mmc_ioc_cmd *ioc =
+    (FAR struct mmc_ioc_cmd *)(uintptr_t)cookie->data;
+
+  /* Copy struct mmc_ioc_cmd back to the usrspace buffer
+   * except data_ptr which is another buffer pointer
+   */
+
+  memcpy(ioc, rsp->buf, sizeof(*ioc) - sizeof(ioc->data_ptr));
+  if (ioc->data_ptr && !ioc->write_flag)
+    {
+      memcpy((FAR void *)(uintptr_t)ioc->data_ptr, rsp->buf + sizeof(*ioc),
+             ioc->blksz * ioc->blocks);
+    }
+}
+
+/****************************************************************************
+ * Name: rpmsgblk_mmc_multi_cmd_handler
+ ****************************************************************************/
+
+static void
+rpmsgblk_mmc_multi_cmd_handler(FAR struct rpmsgblk_cookie_s *cookie,
+                               FAR struct rpmsgblk_ioctl_s *rsp)
+{
+  FAR struct mmc_ioc_multi_cmd *mioc =
+    (FAR struct mmc_ioc_multi_cmd *)(uintptr_t)cookie->data;
+  FAR struct mmc_ioc_multi_cmd *mioc_rsp =
+    (FAR struct mmc_ioc_multi_cmd *)(uintptr_t)rsp->buf;
+  size_t off = sizeof(struct mmc_ioc_multi_cmd) +
+               mioc->num_of_cmds * sizeof(struct mmc_ioc_cmd);
+  uint64_t i;
+
+  for (i = 0; i < mioc->num_of_cmds; i++)
+    {
+      memcpy(&mioc->cmds[i], &mioc_rsp->cmds[i],
+             sizeof(struct mmc_ioc_cmd) - sizeof(mioc->cmds[i].data_ptr));
+      if (mioc->cmds[i].data_ptr && !mioc->cmds[i].write_flag)
+        {
+          memcpy((FAR void *)(uintptr_t)mioc->cmds[i].data_ptr,
+                 rsp->buf + off, mioc->cmds[i].blksz * mioc->cmds[i].blocks);
+          off += mioc->cmds[i].blksz * mioc->cmds[i].blocks;
+        }
+    }
+}
+
 /****************************************************************************
  * Name: rpmsgblk_ioctl_handler
  *
@@ -959,22 +1078,11 @@ static int rpmsgblk_ioctl_handler(FAR struct rpmsg_endpoint *ept,
       switch (rsp->request)
         {
           case MMC_IOC_CMD:
-            {
-              FAR struct mmc_ioc_cmd *ioc =
-                (FAR struct mmc_ioc_cmd *)(uintptr_t)cookie->data;
-
-              /* Copy struct mmc_ioc_cmd back to the usrspace buffer
-               * except data_ptr which is another buffer pointer
-               */
-
-              memcpy(ioc, rsp->buf, sizeof(*ioc) - sizeof(ioc->data_ptr));
-              if (ioc->data_ptr)
-                {
-                  memcpy((FAR void *)(uintptr_t)ioc->data_ptr,
-                         rsp->buf + sizeof(*ioc),
-                         ioc->blksz * ioc->blocks);
-                }
-            }
+            rpmsgblk_mmc_cmd_handler(cookie, rsp);
+            break;
+
+          case MMC_IOC_MULTI_CMD:
+            rpmsgblk_mmc_multi_cmd_handler(cookie, rsp);
             break;
 
           default:
diff --git a/drivers/misc/rpmsgblk_server.c b/drivers/misc/rpmsgblk_server.c
index 0cb7cbac48..6d0cfed985 100644
--- a/drivers/misc/rpmsgblk_server.c
+++ b/drivers/misc/rpmsgblk_server.c
@@ -312,6 +312,125 @@ static int rpmsgblk_geometry_handler(FAR struct rpmsg_endpoint *ept,
   return rpmsg_send(ept, msg, len);
 }
 
+/****************************************************************************
+ * Name: rpmsgblk_mmc_cmd_handler
+ ****************************************************************************/
+
+static int rpmsgblk_mmc_cmd_handler(FAR struct rpmsg_endpoint *ept,
+                                    FAR struct rpmsgblk_ioctl_s *msg)
+{
+  FAR struct rpmsgblk_server_s *server = ept->priv;
+  FAR struct mmc_ioc_cmd *ioc =
+    (FAR struct mmc_ioc_cmd *)(uintptr_t)msg->buf;
+  FAR struct rpmsgblk_ioctl_s *rsp;
+  FAR struct mmc_ioc_cmd *ioc_rsp;
+  size_t rsplen;
+  size_t arglen;
+  uint32_t space;
+
+  arglen = sizeof(struct mmc_ioc_cmd);
+  if (!ioc->write_flag)
+    {
+      arglen += ioc->blksz * ioc->blocks;
+    }
+
+  rsplen = sizeof(*rsp) + arglen - 1;
+  rsp = rpmsg_get_tx_payload_buffer(ept, &space, true);
+  if (msg == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  DEBUGASSERT(space >= rsplen);
+
+  memcpy(rsp, msg, sizeof(*rsp) + sizeof(struct mmc_ioc_cmd) - 1);
+  rsp->arglen = arglen;
+  ioc_rsp = (FAR struct mmc_ioc_cmd *)(uintptr_t)rsp->buf;
+
+  if (ioc_rsp->write_flag)
+    {
+      ioc_rsp->data_ptr = (uint64_t)(uintptr_t)(msg->buf + sizeof(*ioc_rsp));
+    }
+  else
+    {
+      ioc_rsp->data_ptr = (uint64_t)(uintptr_t)(rsp->buf + sizeof(*ioc_rsp));
+    }
+
+  rsp->header.result = server->bops->ioctl(server->blknode, rsp->request,
+                                           (unsigned long)rsp->buf);
+
+  return rpmsg_send_nocopy(ept, rsp, rsplen);
+}
+
+/****************************************************************************
+ * Name: rpmsgblk_mmc_cmd_handler
+ ****************************************************************************/
+
+static int rpmsgblk_mmc_multi_cmd_handler(FAR struct rpmsg_endpoint *ept,
+                                          FAR struct rpmsgblk_ioctl_s *msg)
+{
+  FAR struct rpmsgblk_server_s *server = ept->priv;
+  FAR struct mmc_ioc_multi_cmd *mioc =
+    (FAR struct mmc_ioc_multi_cmd *)(uintptr_t)msg->buf;
+  FAR struct rpmsgblk_ioctl_s *rsp;
+  FAR struct mmc_ioc_multi_cmd *mioc_rsp;
+  size_t rsplen;
+  size_t arglen;
+  size_t off;
+  size_t rsp_off;
+  uint32_t space;
+  uint64_t i;
+
+  arglen = sizeof(struct mmc_ioc_multi_cmd) +
+           mioc->num_of_cmds * sizeof(struct mmc_ioc_cmd);
+  for (i = 0; i < mioc->num_of_cmds; i++)
+    {
+      if (!mioc->cmds[i].write_flag)
+        {
+          arglen += mioc->cmds[i].blksz * mioc->cmds[i].blocks;
+        }
+    }
+
+  rsplen = sizeof(*rsp) + arglen - 1;
+  rsp = rpmsg_get_tx_payload_buffer(ept, &space, true);
+  if (msg == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  DEBUGASSERT(space >= rsplen);
+
+  off = sizeof(struct mmc_ioc_multi_cmd) +
+        mioc->num_of_cmds * sizeof(struct mmc_ioc_cmd);
+
+  /* Consist of the rsp msg */
+
+  memcpy(rsp, msg, sizeof(*rsp) + off - 1);
+  rsp->arglen = arglen;
+  mioc_rsp = (FAR struct mmc_ioc_multi_cmd *)(uintptr_t)rsp->buf;
+  rsp_off = off;
+  for (i = 0; i < mioc_rsp->num_of_cmds; i++)
+    {
+      if (mioc_rsp->cmds[i].write_flag)
+        {
+          mioc_rsp->cmds[i].data_ptr = (uint64_t)(uintptr_t)
+                                       (msg->buf + off);
+          off += mioc_rsp->cmds[i].blksz * mioc_rsp->cmds[i].blocks;
+        }
+      else
+        {
+          mioc_rsp->cmds[i].data_ptr = (uint64_t)(uintptr_t)
+                                       (rsp->buf + rsp_off);
+          rsp_off += mioc_rsp->cmds[i].blksz * mioc_rsp->cmds[i].blocks;
+        }
+    }
+
+  rsp->header.result = server->bops->ioctl(server->blknode, rsp->request,
+                                           (unsigned long)rsp->buf);
+
+  return rpmsg_send_nocopy(ept, rsp, rsplen);
+}
+
 /****************************************************************************
  * Name: rpmsgblk_ioctl_handler
  ****************************************************************************/
@@ -334,17 +453,10 @@ static int rpmsgblk_ioctl_handler(FAR struct rpmsg_endpoint *ept,
   switch (msg->request)
     {
       case MMC_IOC_CMD:
-        {
-          FAR struct mmc_ioc_cmd *ioc =
-            (FAR struct mmc_ioc_cmd *)(uintptr_t)msg->buf;
-
-          if (ioc->data_ptr)
-            {
-              ioc->data_ptr = (uint64_t)(uintptr_t)
-                              ((FAR uint8_t *)ioc + sizeof(*ioc));
-            }
-        }
-        break;
+        return rpmsgblk_mmc_cmd_handler(ept, data);
+
+      case MMC_IOC_MULTI_CMD:
+        return rpmsgblk_mmc_multi_cmd_handler(ept, data);
 
       default:
         break;