Skip to content

Commit

Permalink
drm/virtio: Refactor and optimize job submission code path
Browse files Browse the repository at this point in the history
Move virtio_gpu_execbuffer_ioctl() into separate virtgpu_submit.c file,
refactoring and optimizing the code along the way to ease addition of new
features to the ioctl.

The optimization is done by using optimal ordering of the job's submission
steps, reducing code path from the start of the ioctl to the point of
pushing job to virtio queue. Job's initialization is now performed before
in-fence is awaited and out-fence setup is made after sending out job to
virtio.

Reviewed-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
Tested-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230416115237.798604-2-dmitry.osipenko@collabora.com
  • Loading branch information
digetx committed Jun 3, 2023
1 parent 0fcf8ff commit e4812ab
Show file tree
Hide file tree
Showing 4 changed files with 300 additions and 183 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/virtio/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_gem.o virtgpu_vram.o \
virtgpu_display.o virtgpu_vq.o \
virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o \
virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o
virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o virtgpu_submit.o

obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio-gpu.o
4 changes: 4 additions & 0 deletions drivers/gpu/drm/virtio/virtgpu_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,4 +486,8 @@ void virtio_gpu_vram_unmap_dma_buf(struct device *dev,
struct sg_table *sgt,
enum dma_data_direction dir);

/* virtgpu_submit.c */
int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);

#endif
182 changes: 0 additions & 182 deletions drivers/gpu/drm/virtio/virtgpu_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,36 +38,6 @@
VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \
VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)

static int virtio_gpu_fence_event_create(struct drm_device *dev,
struct drm_file *file,
struct virtio_gpu_fence *fence,
uint32_t ring_idx)
{
struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
struct virtio_gpu_fence_event *e = NULL;
int ret;

if (!(vfpriv->ring_idx_mask & BIT_ULL(ring_idx)))
return 0;

e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e)
return -ENOMEM;

e->event.type = VIRTGPU_EVENT_FENCE_SIGNALED;
e->event.length = sizeof(e->event);

ret = drm_event_reserve_init(dev, file, &e->base, &e->event);
if (ret)
goto free;

fence->e = e;
return 0;
free:
kfree(e);
return ret;
}

/* Must be called with &virtio_gpu_fpriv.struct_mutex held. */
static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev,
struct virtio_gpu_fpriv *vfpriv)
Expand Down Expand Up @@ -108,158 +78,6 @@ static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data,
&virtio_gpu_map->offset);
}

/*
* Usage of execbuffer:
* Relocations need to take into account the full VIRTIO_GPUDrawable size.
* However, the command as passed from user space must *not* contain the initial
* VIRTIO_GPUReleaseInfo struct (first XXX bytes)
*/
static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct drm_virtgpu_execbuffer *exbuf = data;
struct virtio_gpu_device *vgdev = dev->dev_private;
struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
struct virtio_gpu_fence *out_fence;
int ret;
uint32_t *bo_handles = NULL;
void __user *user_bo_handles = NULL;
struct virtio_gpu_object_array *buflist = NULL;
struct sync_file *sync_file;
int out_fence_fd = -1;
void *buf;
uint64_t fence_ctx;
uint32_t ring_idx;

fence_ctx = vgdev->fence_drv.context;
ring_idx = 0;

if (vgdev->has_virgl_3d == false)
return -ENOSYS;

if ((exbuf->flags & ~VIRTGPU_EXECBUF_FLAGS))
return -EINVAL;

if ((exbuf->flags & VIRTGPU_EXECBUF_RING_IDX)) {
if (exbuf->ring_idx >= vfpriv->num_rings)
return -EINVAL;

if (!vfpriv->base_fence_ctx)
return -EINVAL;

fence_ctx = vfpriv->base_fence_ctx;
ring_idx = exbuf->ring_idx;
}

virtio_gpu_create_context(dev, file);
if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_IN) {
struct dma_fence *in_fence;

in_fence = sync_file_get_fence(exbuf->fence_fd);

if (!in_fence)
return -EINVAL;

/*
* Wait if the fence is from a foreign context, or if the fence
* array contains any fence from a foreign context.
*/
ret = 0;
if (!dma_fence_match_context(in_fence, fence_ctx + ring_idx))
ret = dma_fence_wait(in_fence, true);

dma_fence_put(in_fence);
if (ret)
return ret;
}

if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_OUT) {
out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
if (out_fence_fd < 0)
return out_fence_fd;
}

if (exbuf->num_bo_handles) {
bo_handles = kvmalloc_array(exbuf->num_bo_handles,
sizeof(uint32_t), GFP_KERNEL);
if (!bo_handles) {
ret = -ENOMEM;
goto out_unused_fd;
}

user_bo_handles = u64_to_user_ptr(exbuf->bo_handles);
if (copy_from_user(bo_handles, user_bo_handles,
exbuf->num_bo_handles * sizeof(uint32_t))) {
ret = -EFAULT;
goto out_unused_fd;
}

buflist = virtio_gpu_array_from_handles(file, bo_handles,
exbuf->num_bo_handles);
if (!buflist) {
ret = -ENOENT;
goto out_unused_fd;
}
kvfree(bo_handles);
bo_handles = NULL;
}

buf = vmemdup_user(u64_to_user_ptr(exbuf->command), exbuf->size);
if (IS_ERR(buf)) {
ret = PTR_ERR(buf);
goto out_unused_fd;
}

if (buflist) {
ret = virtio_gpu_array_lock_resv(buflist);
if (ret)
goto out_memdup;
}

out_fence = virtio_gpu_fence_alloc(vgdev, fence_ctx, ring_idx);
if(!out_fence) {
ret = -ENOMEM;
goto out_unresv;
}

ret = virtio_gpu_fence_event_create(dev, file, out_fence, ring_idx);
if (ret)
goto out_unresv;

if (out_fence_fd >= 0) {
sync_file = sync_file_create(&out_fence->f);
if (!sync_file) {
dma_fence_put(&out_fence->f);
ret = -ENOMEM;
goto out_unresv;
}

exbuf->fence_fd = out_fence_fd;
fd_install(out_fence_fd, sync_file->file);
}

virtio_gpu_cmd_submit(vgdev, buf, exbuf->size,
vfpriv->ctx_id, buflist, out_fence);
dma_fence_put(&out_fence->f);
virtio_gpu_notify(vgdev);
return 0;

out_unresv:
if (buflist)
virtio_gpu_array_unlock_resv(buflist);
out_memdup:
kvfree(buf);
out_unused_fd:
kvfree(bo_handles);
if (buflist)
virtio_gpu_array_put_free(buflist);

if (out_fence_fd >= 0)
put_unused_fd(out_fence_fd);

return ret;
}

static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
Expand Down
Loading

0 comments on commit e4812ab

Please sign in to comment.