Mesa (main): freedreno/drm/virtio: Drop blocking in host

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


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

Author: Rob Clark <robdclark at chromium.org>
Date:   Fri Apr  8 14:48:03 2022 -0700

freedreno/drm/virtio: Drop blocking in host

These paths should be corner cases, but still it is a bad idea to block
in the host (because it is single threaded), so instead just turn waits
in the host into polling in the guest.

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

---

 src/freedreno/drm/virtio/msm_proto.h   | 26 ++++++--------------------
 src/freedreno/drm/virtio/virtio_bo.c   | 14 ++++++++------
 src/freedreno/drm/virtio/virtio_pipe.c | 19 +++++++++++++------
 3 files changed, 27 insertions(+), 32 deletions(-)

diff --git a/src/freedreno/drm/virtio/msm_proto.h b/src/freedreno/drm/virtio/msm_proto.h
index dbf09d61b4b..c0671d8a282 100644
--- a/src/freedreno/drm/virtio/msm_proto.h
+++ b/src/freedreno/drm/virtio/msm_proto.h
@@ -184,22 +184,15 @@ struct msm_ccmd_gem_info_rsp {
  *
  * Maps to DRM_MSM_GEM_CPU_PREP
  *
- * Note: currently this uses a relative timeout mapped to absolute timeout
- * on the host, because I don't think we can rely on monotonic time being
- * aligned between host and guest.  This has the slight drawback of not
- * handling interrupted syscalls on the guest side, but since the actual
- * waiting happens on the host side (after guest execbuf ioctl returns)
- * this shouldn't be *that* much of a problem.
- *
- * If we could rely on host and guest times being aligned, we could use
- * MSM_CCMD_IOCTL_SIMPLE instead
+ * Note: Since we don't want to block the single threaded host, this returns
+ * immediately with -EBUSY if the fence is not yet signaled.  The guest
+ * should poll if needed.
  */
 struct msm_ccmd_gem_cpu_prep_req {
    struct msm_ccmd_req hdr;
 
    uint32_t host_handle;
    uint32_t op;
-   uint64_t timeout;
 };
 DEFINE_CAST(msm_ccmd_req, msm_ccmd_gem_cpu_prep_req)
 
@@ -326,22 +319,15 @@ struct msm_ccmd_submitqueue_query_rsp {
  *
  * Maps to DRM_MSM_WAIT_FENCE
  *
- * Note: currently this uses a relative timeout mapped to absolute timeout
- * on the host, because I don't think we can rely on monotonic time being
- * aligned between host and guest.  This has the slight drawback of not
- * handling interrupted syscalls on the guest side, but since the actual
- * waiting happens on the host side (after guest execbuf ioctl returns)
- * this shouldn't be *that* much of a problem.
- *
- * If we could rely on host and guest times being aligned, we could use
- * MSM_CCMD_IOCTL_SIMPLE instead
+ * Note: Since we don't want to block the single threaded host, this returns
+ * immediately with -ETIMEDOUT if the fence is not yet signaled.  The guest
+ * should poll if needed.
  */
 struct msm_ccmd_wait_fence_req {
    struct msm_ccmd_req hdr;
 
    uint32_t queue_id;
    uint32_t fence;
-   uint64_t timeout;
 };
 DEFINE_CAST(msm_ccmd_req, msm_ccmd_wait_fence_req)
 
diff --git a/src/freedreno/drm/virtio/virtio_bo.c b/src/freedreno/drm/virtio/virtio_bo.c
index 3ac31a52ff3..ff111685ca9 100644
--- a/src/freedreno/drm/virtio/virtio_bo.c
+++ b/src/freedreno/drm/virtio/virtio_bo.c
@@ -106,17 +106,19 @@ virtio_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op)
          .hdr = MSM_CCMD(GEM_CPU_PREP, sizeof(req)),
          .host_handle = virtio_bo_host_handle(bo),
          .op = op,
-         .timeout = 5000000000,
    };
    struct msm_ccmd_gem_cpu_prep_rsp *rsp;
 
-   rsp = virtio_alloc_rsp(bo->dev, &req.hdr, sizeof(*rsp));
+   /* We can't do a blocking wait in the host, so we have to poll: */
+   do {
+      rsp = virtio_alloc_rsp(bo->dev, &req.hdr, sizeof(*rsp));
 
-   ret = virtio_execbuf(bo->dev, &req.hdr, true);
-   if (ret)
-      goto out;
+      ret = virtio_execbuf(bo->dev, &req.hdr, true);
+      if (ret)
+         goto out;
 
-   ret = rsp->ret;
+      ret = rsp->ret;
+   } while (ret == -EBUSY);
 
 out:
    return ret;
diff --git a/src/freedreno/drm/virtio/virtio_pipe.c b/src/freedreno/drm/virtio/virtio_pipe.c
index f2987261a11..ac0ef586456 100644
--- a/src/freedreno/drm/virtio/virtio_pipe.c
+++ b/src/freedreno/drm/virtio/virtio_pipe.c
@@ -115,17 +115,24 @@ virtio_pipe_wait(struct fd_pipe *pipe, const struct fd_fence *fence, uint64_t ti
          .hdr = MSM_CCMD(WAIT_FENCE, sizeof(req)),
          .queue_id = to_virtio_pipe(pipe)->queue_id,
          .fence = fence->kfence,
-         .timeout = timeout,
    };
    struct msm_ccmd_submitqueue_query_rsp *rsp;
+   int64_t end_time = os_time_get_nano() + timeout;
+   int ret;
 
-   rsp = virtio_alloc_rsp(pipe->dev, &req.hdr, sizeof(*rsp));
+   do {
+      rsp = virtio_alloc_rsp(pipe->dev, &req.hdr, sizeof(*rsp));
 
-   int ret = virtio_execbuf(pipe->dev, &req.hdr, true);
-   if (ret)
-      goto out;
+      ret = virtio_execbuf(pipe->dev, &req.hdr, true);
+      if (ret)
+         goto out;
 
-   ret = rsp->ret;
+      if ((timeout != PIPE_TIMEOUT_INFINITE) &&
+          (os_time_get_nano() >= end_time))
+         break;
+
+      ret = rsp->ret;
+   } while (ret == -ETIMEDOUT);
 
 out:
    return ret;



More information about the mesa-commit mailing list