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;