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 6ea3dcace4 misc/rpmsgdev: fix block mode read/write bug in rpmsgdev
6ea3dcace4 is described below
commit 6ea3dcace44bece9b7a5f91f6080fdbd3030d9f9
Author: Bowen Wang <[email protected]>
AuthorDate: Fri Jul 12 19:33:41 2024 +0800
misc/rpmsgdev: fix block mode read/write bug in rpmsgdev
Rpmsg dev server always open the real char device with nonblock mode,
so let client try to read/wrtie the read device every read/write
operation.
Signed-off-by: Bowen Wang <[email protected]>
---
drivers/misc/rpmsgdev.c | 114 ++++++++++++++++++-----------------------
drivers/misc/rpmsgdev_server.c | 11 ++--
2 files changed, 59 insertions(+), 66 deletions(-)
diff --git a/drivers/misc/rpmsgdev.c b/drivers/misc/rpmsgdev.c
index 1a10fcee79..a203b6b5b5 100644
--- a/drivers/misc/rpmsgdev.c
+++ b/drivers/misc/rpmsgdev.c
@@ -404,20 +404,6 @@ static ssize_t rpmsgdev_read(FAR struct file *filep, FAR
char *buffer,
priv = filep->f_priv;
DEBUGASSERT(dev != NULL && priv != NULL);
- /* If the open flags is not nonblock, should poll the device for
- * read ready first to avoid the server rptun thread blocked in
- * device read operation.
- */
-
- if (priv->nonblock == false)
- {
- ret = rpmsgdev_wait(filep, POLLIN);
- if (ret < 0)
- {
- return ret;
- }
- }
-
/* Call the host to perform the read */
read.iov_base = buffer;
@@ -428,8 +414,27 @@ static ssize_t rpmsgdev_read(FAR struct file *filep, FAR
char *buffer,
command = dev->flags & RPMSGDEV_NOFRAG_READ ?
RPMSGDEV_READ_NOFRAG : RPMSGDEV_READ;
- ret = rpmsgdev_send_recv(dev, command, true, &msg.header,
- sizeof(msg) - 1, &read);
+ for (; ; )
+ {
+ ret = rpmsgdev_send_recv(dev, command, true, &msg.header,
+ sizeof(msg) - 1, &read);
+ if (ret != -EAGAIN || priv->nonblock)
+ {
+ break;
+ }
+
+ /* If open with block mode and return -EAGAIN, should wait the
+ * perr device ready and try again until read success or some
+ * other errors occur.
+ */
+
+ ret = rpmsgdev_wait(filep, POLLIN);
+ if (ret < 0)
+ {
+ rpmsgdeverr("read wait failed, ret=%d\n", ret);
+ break;
+ }
+ }
return read.iov_len ? read.iov_len : ret;
}
@@ -459,10 +464,9 @@ static ssize_t rpmsgdev_write(FAR struct file *filep,
const char *buffer,
FAR struct rpmsgdev_s *dev;
FAR struct rpmsgdev_priv_s *priv;
FAR struct rpmsgdev_write_s *msg;
- struct rpmsgdev_cookie_s cookie;
uint32_t space;
size_t written = 0;
- int ret;
+ int ret = 0;
if (buffer == NULL)
{
@@ -475,81 +479,60 @@ static ssize_t rpmsgdev_write(FAR struct file *filep,
const char *buffer,
priv = filep->f_priv;
DEBUGASSERT(dev != NULL && priv != NULL);
- /* If the open flags is not nonblock, should poll the device for
- * write ready first to avoid the server rptun thread blocked in
- * device write operation.
- */
-
- if (priv->nonblock == false)
- {
- ret = rpmsgdev_wait(filep, POLLOUT);
- if (ret < 0)
- {
- return ret;
- }
- }
-
/* Perform the rpmsg write */
- memset(&cookie, 0, sizeof(cookie));
- nxsem_init(&cookie.sem, 0, 0);
-
while (written < buflen)
{
msg = rpmsgdev_get_tx_payload_buffer(dev, &space);
if (msg == NULL)
{
ret = -ENOMEM;
- goto out;
+ break;
}
space -= sizeof(*msg) - 1;
if (space >= buflen - written)
{
- /* Send complete, set cookie is valid, need ack */
-
space = buflen - written;
- msg->header.cookie = (uintptr_t)&cookie;
}
else if ((dev->flags & RPMSGDEV_NOFRAG_WRITE) != 0)
{
rpmsg_release_tx_buffer(&dev->ept, msg);
ret = -EMSGSIZE;
- goto out;
+ break;
}
- else
+
+ msg->filep = priv->filep;
+ msg->count = space;
+ memcpy(msg->buf, buffer + written, space);
+
+ ret = rpmsgdev_send_recv(dev, RPMSGDEV_WRITE, false, &msg->header,
+ sizeof(*msg) - 1 + space, NULL);
+ if (ret >= 0)
{
- /* Not send complete, set cookie invalid, do not need ack */
+ written += ret;
+ continue;
+ }
- msg->header.cookie = 0;
+ if (ret != -EAGAIN || priv->nonblock || written != 0)
+ {
+ break;
}
- msg->header.command = RPMSGDEV_WRITE;
- msg->header.result = -ENXIO;
- msg->filep = priv->filep;
- msg->count = space;
- memcpy(msg->buf, buffer + written, space);
+ /* If open with block mode and return -EAGAIN and no data
+ * written to this device, should wait peer device ready and
+ * try again.
+ */
- ret = rpmsg_send_nocopy(&dev->ept, msg, sizeof(*msg) - 1 + space);
+ ret = rpmsgdev_wait(filep, POLLOUT);
if (ret < 0)
{
- goto out;
+ rpmsgerr("write wait failed, ret=%d\n", ret);
+ break;
}
-
- written += space;
- }
-
- ret = rpmsg_wait(&dev->ept, &cookie.sem);
- if (ret < 0)
- {
- goto out;
}
- ret = cookie.result;
-
-out:
- nxsem_destroy(&cookie.sem);
- return ret < 0 ? ret : buflen;
+ return written != 0 ? written : ret;
}
/****************************************************************************
@@ -838,6 +821,11 @@ static int rpmsgdev_send_recv(FAR struct rpmsgdev_s *priv,
if (ret < 0)
{
+ if (copy == false)
+ {
+ rpmsg_release_tx_buffer(&priv->ept, msg);
+ }
+
goto fail;
}
diff --git a/drivers/misc/rpmsgdev_server.c b/drivers/misc/rpmsgdev_server.c
index 03345266b3..8d596764a1 100644
--- a/drivers/misc/rpmsgdev_server.c
+++ b/drivers/misc/rpmsgdev_server.c
@@ -272,11 +272,16 @@ static int rpmsgdev_write_handler(FAR struct
rpmsg_endpoint *ept,
written += ret;
}
- if (msg->header.cookie != 0)
+ if (written != 0)
{
- msg->header.result = ret < 0 ? ret : written;
- rpmsg_send(ept, msg, sizeof(*msg) - 1);
+ msg->header.result = written;
}
+ else
+ {
+ msg->header.result = ret;
+ }
+
+ rpmsg_send(ept, msg, sizeof(*msg) - 1);
return 0;
}