*
* 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)
*
* 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)
.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;
.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;