Module: Mesa Branch: main Commit: 441f01e778184be8e5f99d3c40f47ee49402dd03 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=441f01e778184be8e5f99d3c40f47ee49402dd03
Author: Rob Clark <[email protected]> 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 <[email protected]> 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;
