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

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

commit 36f7c85610df91391ece91135470b1f1cfdb9443
Author: wangyongrong <[email protected]>
AuthorDate: Mon Jul 6 19:22:50 2026 +0800

    drivers/virtio/virtio-rng: map the user buffer instead of copying it
    
    virtio-rng allocated a scratch buffer via virtio_zalloc_buf and
    memcpy'd it back to the caller, adding a copy on MMIO/PCI where the
    device can write the user buffer directly. Switch to virtio_map_buf
    and virtio_unmap_buf so MMIO/PCI is zero-copy (map returns the buffer
    as is), while rptun keeps bouncing through shared memory unchanged.
    
    Signed-off-by: wangyongrong <[email protected]>
    Signed-off-by: Bowen Wang <[email protected]>
---
 drivers/virtio/virtio-rng.c | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/drivers/virtio/virtio-rng.c b/drivers/virtio/virtio-rng.c
index ea9cb1397ae..3f217e588c5 100644
--- a/drivers/virtio/virtio-rng.c
+++ b/drivers/virtio/virtio-rng.c
@@ -152,6 +152,7 @@ static ssize_t virtio_rng_read(FAR struct file *filep, FAR 
char *buffer,
   FAR struct virtqueue *vq = priv->vdev->vrings_info[0].vq;
   struct virtio_rng_cookie_s cookie;
   struct virtqueue_buf vb;
+  FAR void *mapped;
   irqstate_t flags;
   int ret;
 
@@ -160,23 +161,34 @@ static ssize_t virtio_rng_read(FAR struct file *filep, 
FAR char *buffer,
   cookie.len = 0;
   nxsem_init(&cookie.sem, 0, 0);
 
+  /* Map the user buffer so the device side can access it. On MMIO/PCI
+   * map returns the buffer itself and the device writes the entropy straight
+   * into it (zero copy); a transport that cannot reach it (rptun, or a user
+   * buffer with CONFIG_ARCH_ADDRENV) bounces it and unmap copies the result
+   * back below.
+   */
+
+  ret = virtio_map_buf(priv->vdev, buffer, buflen, VIRTIO_DMA_FROM_DEVICE,
+                       &mapped);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
   /* Add the input buffer to the virtqueue, and the cookie as the virtqueue
    * cookie. (virtqueue_get_buffer() will return cookie).
    */
 
   vb.len = buflen;
-  vb.buf = virtio_zalloc_buf(priv->vdev, buflen, 16);
-  if (vb.buf == NULL)
-    {
-      return -ENOMEM;
-    }
+  vb.buf = mapped;
 
   flags = spin_lock_irqsave(&priv->lock);
   ret = virtqueue_add_buffer(vq, &vb, 0, 1, &cookie);
   if (ret < 0)
     {
       spin_unlock_irqrestore(&priv->lock, flags);
-      virtio_free_buf(priv->vdev, vb.buf);
+      virtio_unmap_buf(priv->vdev, buffer, 0, VIRTIO_DMA_FROM_DEVICE,
+                       mapped);
       return ret;
     }
 
@@ -188,8 +200,13 @@ static ssize_t virtio_rng_read(FAR struct file *filep, FAR 
char *buffer,
   /* Wait for completion */
 
   nxsem_wait_uninterruptible(&cookie.sem);
-  memcpy(buffer, vb.buf, cookie.len);
-  virtio_free_buf(priv->vdev, vb.buf);
+
+  /* Unmap copies a bounce back into the user buffer and is a no-op when the
+   * device wrote it directly. Only cookie.len bytes are valid.
+   */
+
+  virtio_unmap_buf(priv->vdev, buffer, cookie.len, VIRTIO_DMA_FROM_DEVICE,
+                   mapped);
   return cookie.len;
 }
 

Reply via email to