Mesa (main): freedreno/drm/virtio: Async ccmd batching

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Apr 27 23:33:33 UTC 2022


Module: Mesa
Branch: main
Commit: 0aab31043979bc478f2d2a2a35bbe882154f457e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=0aab31043979bc478f2d2a2a35bbe882154f457e

Author: Rob Clark <robdclark at chromium.org>
Date:   Mon Apr 18 14:23:13 2022 -0700

freedreno/drm/virtio: Async ccmd batching

This could be a bit more clever an avoid extra memcpy.. but that seems
to be in the noise at this point.

Signed-off-by: Rob Clark <robdclark at chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16086>

---

 src/freedreno/drm/virtio/virtio_bo.c     |   8 +++
 src/freedreno/drm/virtio/virtio_device.c | 108 +++++++++++++++++++++++++------
 src/freedreno/drm/virtio/virtio_priv.h   |   5 ++
 3 files changed, 100 insertions(+), 21 deletions(-)

diff --git a/src/freedreno/drm/virtio/virtio_bo.c b/src/freedreno/drm/virtio/virtio_bo.c
index 36cf8c9e364..2fc7cb079bc 100644
--- a/src/freedreno/drm/virtio/virtio_bo.c
+++ b/src/freedreno/drm/virtio/virtio_bo.c
@@ -221,8 +221,16 @@ virtio_bo_destroy(struct fd_bo *bo)
    /* Release iova by setting to zero: */
    if (bo->iova) {
       set_iova(bo, 0);
+
       virtio_dev_free_iova(bo->dev, bo->iova, bo->size);
+
+      /* Need to flush batched ccmds to ensure the host sees the iova
+       * release before the GEM handle is closed (ie. detach_resource()
+       * on the host side)
+       */
+      virtio_execbuf_flush(bo->dev);
    }
+
    free(virtio_bo);
 }
 
diff --git a/src/freedreno/drm/virtio/virtio_device.c b/src/freedreno/drm/virtio/virtio_device.c
index dddabe76a49..4c395b8b6d5 100644
--- a/src/freedreno/drm/virtio/virtio_device.c
+++ b/src/freedreno/drm/virtio/virtio_device.c
@@ -238,6 +238,38 @@ virtio_alloc_rsp(struct fd_device *dev, struct msm_ccmd_req *req, uint32_t sz)
    return rsp;
 }
 
+static int execbuf_flush_locked(struct fd_device *dev, int *out_fence_fd);
+
+static int
+execbuf_locked(struct fd_device *dev, void *cmd, uint32_t cmd_size,
+               uint32_t *handles, uint32_t num_handles,
+               int in_fence_fd, int *out_fence_fd, int ring_idx)
+{
+#define COND(bool, val) ((bool) ? (val) : 0)
+   struct drm_virtgpu_execbuffer eb = {
+         .flags = COND(out_fence_fd, VIRTGPU_EXECBUF_FENCE_FD_OUT) |
+                  COND(in_fence_fd != -1, VIRTGPU_EXECBUF_FENCE_FD_IN) |
+                  VIRTGPU_EXECBUF_RING_IDX,
+         .fence_fd = in_fence_fd,
+         .size  = cmd_size,
+         .command = VOID2U64(cmd),
+         .ring_idx = ring_idx,
+         .bo_handles = VOID2U64(handles),
+         .num_bo_handles = num_handles,
+   };
+
+   int ret = drmIoctl(dev->fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &eb);
+   if (ret) {
+      ERROR_MSG("EXECBUFFER failed: %s", strerror(errno));
+      return ret;
+   }
+
+   if (out_fence_fd)
+      *out_fence_fd = eb.fence_fd;
+
+   return 0;
+}
+
 /**
  * Helper for "execbuf" ioctl.. note that in virtgpu execbuf is just
  * a generic "send commands to host", not necessarily specific to
@@ -252,42 +284,76 @@ virtio_execbuf_fenced(struct fd_device *dev, struct msm_ccmd_req *req,
                       int in_fence_fd, int *out_fence_fd, int ring_idx)
 {
    struct virtio_device *virtio_dev = to_virtio_device(dev);
+   int ret;
 
    simple_mtx_lock(&virtio_dev->eb_lock);
+   execbuf_flush_locked(dev, NULL);
    req->seqno = ++virtio_dev->next_seqno;
 
-#define COND(bool, val) ((bool) ? (val) : 0)
-   struct drm_virtgpu_execbuffer eb = {
-         .flags = COND(out_fence_fd, VIRTGPU_EXECBUF_FENCE_FD_OUT) |
-                  COND(in_fence_fd != -1, VIRTGPU_EXECBUF_FENCE_FD_IN) |
-                  VIRTGPU_EXECBUF_RING_IDX,
-         .fence_fd = in_fence_fd,
-         .size  = req->len,
-         .command = VOID2U64(req),
-         .ring_idx = ring_idx,
-         .bo_handles = VOID2U64(handles),
-         .num_bo_handles = num_handles,
-   };
+   ret = execbuf_locked(dev, req, req->len, handles, num_handles,
+                        in_fence_fd, out_fence_fd, ring_idx);
 
-   int ret = drmIoctl(dev->fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &eb);
    simple_mtx_unlock(&virtio_dev->eb_lock);
-   if (ret) {
-      ERROR_MSG("EXECBUFFER failed: %s", strerror(errno));
+
+   return ret;
+}
+
+static int
+execbuf_flush_locked(struct fd_device *dev, int *out_fence_fd)
+{
+   struct virtio_device *virtio_dev = to_virtio_device(dev);
+   int ret;
+
+   if (!virtio_dev->reqbuf_len)
+      return 0;
+
+   ret = execbuf_locked(dev, virtio_dev->reqbuf, virtio_dev->reqbuf_len,
+                        NULL, 0, -1, out_fence_fd, 0);
+   if (ret)
       return ret;
-   }
 
-   if (out_fence_fd)
-      *out_fence_fd = eb.fence_fd;
+   virtio_dev->reqbuf_len = 0;
+   virtio_dev->reqbuf_cnt = 0;
 
    return 0;
 }
 
+int
+virtio_execbuf_flush(struct fd_device *dev)
+{
+   struct virtio_device *virtio_dev = to_virtio_device(dev);
+   simple_mtx_lock(&virtio_dev->eb_lock);
+   int ret = execbuf_flush_locked(dev, NULL);
+   simple_mtx_unlock(&virtio_dev->eb_lock);
+   return ret;
+}
+
 int
 virtio_execbuf(struct fd_device *dev, struct msm_ccmd_req *req, bool sync)
 {
-   int fence_fd;
-   int ret = virtio_execbuf_fenced(dev, req, NULL, 0, -1,
-                                   sync ? &fence_fd : NULL, 0);
+   struct virtio_device *virtio_dev = to_virtio_device(dev);
+   int fence_fd, ret = 0;
+
+   simple_mtx_lock(&virtio_dev->eb_lock);
+   req->seqno = ++virtio_dev->next_seqno;
+
+   if ((virtio_dev->reqbuf_len + req->len) > sizeof(virtio_dev->reqbuf)) {
+      ret = execbuf_flush_locked(dev, NULL);
+      if (ret)
+         goto out_unlock;
+   }
+
+   memcpy(&virtio_dev->reqbuf[virtio_dev->reqbuf_len], req, req->len);
+   virtio_dev->reqbuf_len += req->len;
+   virtio_dev->reqbuf_cnt++;
+
+   if (!sync)
+      goto out_unlock;
+
+   ret = execbuf_flush_locked(dev, &fence_fd);
+
+out_unlock:
+   simple_mtx_unlock(&virtio_dev->eb_lock);
 
    if (ret)
       return ret;
diff --git a/src/freedreno/drm/virtio/virtio_priv.h b/src/freedreno/drm/virtio/virtio_priv.h
index 0effae6744c..2387ab516ff 100644
--- a/src/freedreno/drm/virtio/virtio_priv.h
+++ b/src/freedreno/drm/virtio/virtio_priv.h
@@ -79,6 +79,10 @@ struct virtio_device {
     */
    struct util_vma_heap address_space;
    simple_mtx_t address_space_lock;
+
+   uint32_t reqbuf_len;
+   uint32_t reqbuf_cnt;
+   uint8_t reqbuf[0x4000];
 };
 FD_DEFINE_CAST(fd_device, virtio_device);
 
@@ -175,6 +179,7 @@ void *virtio_alloc_rsp(struct fd_device *dev, struct msm_ccmd_req *hdr, uint32_t
 int virtio_execbuf_fenced(struct fd_device *dev, struct msm_ccmd_req *req,
                           uint32_t *handles, uint32_t num_handles,
                           int in_fence_fd, int *out_fence_fd, int ring_idx);
+int virtio_execbuf_flush(struct fd_device *dev);
 int virtio_execbuf(struct fd_device *dev, struct msm_ccmd_req *req, bool sync);
 void virtio_host_sync(struct fd_device *dev, const struct msm_ccmd_req *req);
 int virtio_simple_ioctl(struct fd_device *dev, unsigned cmd, void *req);



More information about the mesa-commit mailing list