An interrupted dma_fence_wait() becomes an -ERESTARTSYS returned to userspace ioctl(DRM_IOCTL_VIRTGPU_EXECBUFFER) calls, prompting to retry the ioctl(), but the passed exbuf->fence_fd has been reset to -1, making the retry attempt fail at sync_file_get_fence(). The uapi for DRM_IOCTL_VIRTGPU_EXECBUFFER is changed to retain the passed value for exbuf->fence_fd when returning ERESTARTSYS or EINTR. Fixes: 2cd7b6f08bc4 ("drm/virtio: add in/out fence support for explicit synchronization") Signed-off-by: Ryan Neph <ryanneph@xxxxxxxxxxxx> --- drivers/gpu/drm/virtio/virtgpu_ioctl.c | 9 ++++++--- include/uapi/drm/virtgpu_drm.h | 3 +++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index 9f4a90493aea..ffce4e2a409a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c @@ -132,6 +132,8 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, uint64_t fence_ctx; uint32_t ring_idx; + exbuf->fence_fd = -1; + fence_ctx = vgdev->fence_drv.context; ring_idx = 0; @@ -152,8 +154,6 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, ring_idx = exbuf->ring_idx; } - exbuf->fence_fd = -1; - virtio_gpu_create_context(dev, file); if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_IN) { struct dma_fence *in_fence; @@ -173,7 +173,7 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, dma_fence_put(in_fence); if (ret) - return ret; + goto out_err; } if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_OUT) { @@ -259,6 +259,9 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, if (out_fence_fd >= 0) put_unused_fd(out_fence_fd); +out_err: + if (ret == -EINTR || ret == -ERESTARTSYS) + exbuf->fence_fd = in_fence_fd; return ret; } diff --git a/include/uapi/drm/virtgpu_drm.h b/include/uapi/drm/virtgpu_drm.h index 0512fde5e697..ac8d1eed12ab 100644 --- a/include/uapi/drm/virtgpu_drm.h +++ b/include/uapi/drm/virtgpu_drm.h @@ -64,6 +64,9 @@ struct drm_virtgpu_map { __u32 pad; }; +/* For ioctl() returning ERESTARTSYS or EINTR, fence_fd is unmodified. + * For all other errors it is set to -1. + */ struct drm_virtgpu_execbuffer { __u32 flags; __u32 size; -- 2.39.1.456.gfc5497dd1b-goog