Skip to content

Commit e4812ab

Browse files
committed
drm/virtio: Refactor and optimize job submission code path
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 <[email protected]> Reviewed-by: Emil Velikov <[email protected]> Tested-by: Pierre-Eric Pelloux-Prayer <[email protected]> Signed-off-by: Dmitry Osipenko <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 0fcf8ff commit e4812ab

File tree

4 files changed

+300
-183
lines changed

4 files changed

+300
-183
lines changed

drivers/gpu/drm/virtio/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_gem.o virtgpu_vram.o \
77
virtgpu_display.o virtgpu_vq.o \
88
virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o \
9-
virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o
9+
virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o virtgpu_submit.o
1010

1111
obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio-gpu.o

drivers/gpu/drm/virtio/virtgpu_drv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,4 +486,8 @@ void virtio_gpu_vram_unmap_dma_buf(struct device *dev,
486486
struct sg_table *sgt,
487487
enum dma_data_direction dir);
488488

489+
/* virtgpu_submit.c */
490+
int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
491+
struct drm_file *file);
492+
489493
#endif

drivers/gpu/drm/virtio/virtgpu_ioctl.c

Lines changed: 0 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -38,36 +38,6 @@
3838
VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \
3939
VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)
4040

41-
static int virtio_gpu_fence_event_create(struct drm_device *dev,
42-
struct drm_file *file,
43-
struct virtio_gpu_fence *fence,
44-
uint32_t ring_idx)
45-
{
46-
struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
47-
struct virtio_gpu_fence_event *e = NULL;
48-
int ret;
49-
50-
if (!(vfpriv->ring_idx_mask & BIT_ULL(ring_idx)))
51-
return 0;
52-
53-
e = kzalloc(sizeof(*e), GFP_KERNEL);
54-
if (!e)
55-
return -ENOMEM;
56-
57-
e->event.type = VIRTGPU_EVENT_FENCE_SIGNALED;
58-
e->event.length = sizeof(e->event);
59-
60-
ret = drm_event_reserve_init(dev, file, &e->base, &e->event);
61-
if (ret)
62-
goto free;
63-
64-
fence->e = e;
65-
return 0;
66-
free:
67-
kfree(e);
68-
return ret;
69-
}
70-
7141
/* Must be called with &virtio_gpu_fpriv.struct_mutex held. */
7242
static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev,
7343
struct virtio_gpu_fpriv *vfpriv)
@@ -108,158 +78,6 @@ static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data,
10878
&virtio_gpu_map->offset);
10979
}
11080

111-
/*
112-
* Usage of execbuffer:
113-
* Relocations need to take into account the full VIRTIO_GPUDrawable size.
114-
* However, the command as passed from user space must *not* contain the initial
115-
* VIRTIO_GPUReleaseInfo struct (first XXX bytes)
116-
*/
117-
static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
118-
struct drm_file *file)
119-
{
120-
struct drm_virtgpu_execbuffer *exbuf = data;
121-
struct virtio_gpu_device *vgdev = dev->dev_private;
122-
struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
123-
struct virtio_gpu_fence *out_fence;
124-
int ret;
125-
uint32_t *bo_handles = NULL;
126-
void __user *user_bo_handles = NULL;
127-
struct virtio_gpu_object_array *buflist = NULL;
128-
struct sync_file *sync_file;
129-
int out_fence_fd = -1;
130-
void *buf;
131-
uint64_t fence_ctx;
132-
uint32_t ring_idx;
133-
134-
fence_ctx = vgdev->fence_drv.context;
135-
ring_idx = 0;
136-
137-
if (vgdev->has_virgl_3d == false)
138-
return -ENOSYS;
139-
140-
if ((exbuf->flags & ~VIRTGPU_EXECBUF_FLAGS))
141-
return -EINVAL;
142-
143-
if ((exbuf->flags & VIRTGPU_EXECBUF_RING_IDX)) {
144-
if (exbuf->ring_idx >= vfpriv->num_rings)
145-
return -EINVAL;
146-
147-
if (!vfpriv->base_fence_ctx)
148-
return -EINVAL;
149-
150-
fence_ctx = vfpriv->base_fence_ctx;
151-
ring_idx = exbuf->ring_idx;
152-
}
153-
154-
virtio_gpu_create_context(dev, file);
155-
if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_IN) {
156-
struct dma_fence *in_fence;
157-
158-
in_fence = sync_file_get_fence(exbuf->fence_fd);
159-
160-
if (!in_fence)
161-
return -EINVAL;
162-
163-
/*
164-
* Wait if the fence is from a foreign context, or if the fence
165-
* array contains any fence from a foreign context.
166-
*/
167-
ret = 0;
168-
if (!dma_fence_match_context(in_fence, fence_ctx + ring_idx))
169-
ret = dma_fence_wait(in_fence, true);
170-
171-
dma_fence_put(in_fence);
172-
if (ret)
173-
return ret;
174-
}
175-
176-
if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_OUT) {
177-
out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
178-
if (out_fence_fd < 0)
179-
return out_fence_fd;
180-
}
181-
182-
if (exbuf->num_bo_handles) {
183-
bo_handles = kvmalloc_array(exbuf->num_bo_handles,
184-
sizeof(uint32_t), GFP_KERNEL);
185-
if (!bo_handles) {
186-
ret = -ENOMEM;
187-
goto out_unused_fd;
188-
}
189-
190-
user_bo_handles = u64_to_user_ptr(exbuf->bo_handles);
191-
if (copy_from_user(bo_handles, user_bo_handles,
192-
exbuf->num_bo_handles * sizeof(uint32_t))) {
193-
ret = -EFAULT;
194-
goto out_unused_fd;
195-
}
196-
197-
buflist = virtio_gpu_array_from_handles(file, bo_handles,
198-
exbuf->num_bo_handles);
199-
if (!buflist) {
200-
ret = -ENOENT;
201-
goto out_unused_fd;
202-
}
203-
kvfree(bo_handles);
204-
bo_handles = NULL;
205-
}
206-
207-
buf = vmemdup_user(u64_to_user_ptr(exbuf->command), exbuf->size);
208-
if (IS_ERR(buf)) {
209-
ret = PTR_ERR(buf);
210-
goto out_unused_fd;
211-
}
212-
213-
if (buflist) {
214-
ret = virtio_gpu_array_lock_resv(buflist);
215-
if (ret)
216-
goto out_memdup;
217-
}
218-
219-
out_fence = virtio_gpu_fence_alloc(vgdev, fence_ctx, ring_idx);
220-
if(!out_fence) {
221-
ret = -ENOMEM;
222-
goto out_unresv;
223-
}
224-
225-
ret = virtio_gpu_fence_event_create(dev, file, out_fence, ring_idx);
226-
if (ret)
227-
goto out_unresv;
228-
229-
if (out_fence_fd >= 0) {
230-
sync_file = sync_file_create(&out_fence->f);
231-
if (!sync_file) {
232-
dma_fence_put(&out_fence->f);
233-
ret = -ENOMEM;
234-
goto out_unresv;
235-
}
236-
237-
exbuf->fence_fd = out_fence_fd;
238-
fd_install(out_fence_fd, sync_file->file);
239-
}
240-
241-
virtio_gpu_cmd_submit(vgdev, buf, exbuf->size,
242-
vfpriv->ctx_id, buflist, out_fence);
243-
dma_fence_put(&out_fence->f);
244-
virtio_gpu_notify(vgdev);
245-
return 0;
246-
247-
out_unresv:
248-
if (buflist)
249-
virtio_gpu_array_unlock_resv(buflist);
250-
out_memdup:
251-
kvfree(buf);
252-
out_unused_fd:
253-
kvfree(bo_handles);
254-
if (buflist)
255-
virtio_gpu_array_put_free(buflist);
256-
257-
if (out_fence_fd >= 0)
258-
put_unused_fd(out_fence_fd);
259-
260-
return ret;
261-
}
262-
26381
static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data,
26482
struct drm_file *file)
26583
{

0 commit comments

Comments
 (0)