Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2015 Red Hat, Inc.
3 : : * All Rights Reserved.
4 : : *
5 : : * Authors:
6 : : * Dave Airlie <airlied@redhat.com>
7 : : * Gerd Hoffmann <kraxel@redhat.com>
8 : : *
9 : : * Permission is hereby granted, free of charge, to any person obtaining a
10 : : * copy of this software and associated documentation files (the "Software"),
11 : : * to deal in the Software without restriction, including without limitation
12 : : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 : : * and/or sell copies of the Software, and to permit persons to whom the
14 : : * Software is furnished to do so, subject to the following conditions:
15 : : *
16 : : * The above copyright notice and this permission notice (including the next
17 : : * paragraph) shall be included in all copies or substantial portions of the
18 : : * Software.
19 : : *
20 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : : * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 : : * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 : : * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 : : * OTHER DEALINGS IN THE SOFTWARE.
27 : : */
28 : :
29 : : #include <linux/dma-mapping.h>
30 : : #include <linux/virtio.h>
31 : : #include <linux/virtio_config.h>
32 : : #include <linux/virtio_ring.h>
33 : :
34 : : #include "virtgpu_drv.h"
35 : : #include "virtgpu_trace.h"
36 : :
37 : : #define MAX_INLINE_CMD_SIZE 96
38 : : #define MAX_INLINE_RESP_SIZE 24
39 : : #define VBUFFER_SIZE (sizeof(struct virtio_gpu_vbuffer) \
40 : : + MAX_INLINE_CMD_SIZE \
41 : : + MAX_INLINE_RESP_SIZE)
42 : :
43 : 0 : static void convert_to_hw_box(struct virtio_gpu_box *dst,
44 : : const struct drm_virtgpu_3d_box *src)
45 : : {
46 : 0 : dst->x = cpu_to_le32(src->x);
47 : 0 : dst->y = cpu_to_le32(src->y);
48 : 0 : dst->z = cpu_to_le32(src->z);
49 : 0 : dst->w = cpu_to_le32(src->w);
50 : 0 : dst->h = cpu_to_le32(src->h);
51 : 0 : dst->d = cpu_to_le32(src->d);
52 : : }
53 : :
54 : 0 : void virtio_gpu_ctrl_ack(struct virtqueue *vq)
55 : : {
56 : 0 : struct drm_device *dev = vq->vdev->priv;
57 : 0 : struct virtio_gpu_device *vgdev = dev->dev_private;
58 : :
59 : 0 : schedule_work(&vgdev->ctrlq.dequeue_work);
60 : 0 : }
61 : :
62 : 0 : void virtio_gpu_cursor_ack(struct virtqueue *vq)
63 : : {
64 : 0 : struct drm_device *dev = vq->vdev->priv;
65 : 0 : struct virtio_gpu_device *vgdev = dev->dev_private;
66 : :
67 : 0 : schedule_work(&vgdev->cursorq.dequeue_work);
68 : 0 : }
69 : :
70 : 0 : int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev)
71 : : {
72 : 0 : vgdev->vbufs = kmem_cache_create("virtio-gpu-vbufs",
73 : : VBUFFER_SIZE,
74 : : __alignof__(struct virtio_gpu_vbuffer),
75 : : 0, NULL);
76 [ # # ]: 0 : if (!vgdev->vbufs)
77 : 0 : return -ENOMEM;
78 : : return 0;
79 : : }
80 : :
81 : 0 : void virtio_gpu_free_vbufs(struct virtio_gpu_device *vgdev)
82 : : {
83 : 0 : kmem_cache_destroy(vgdev->vbufs);
84 : 0 : vgdev->vbufs = NULL;
85 : 0 : }
86 : :
87 : : static struct virtio_gpu_vbuffer*
88 : : virtio_gpu_get_vbuf(struct virtio_gpu_device *vgdev,
89 : : int size, int resp_size, void *resp_buf,
90 : : virtio_gpu_resp_cb resp_cb)
91 : : {
92 : : struct virtio_gpu_vbuffer *vbuf;
93 : :
94 : : vbuf = kmem_cache_zalloc(vgdev->vbufs, GFP_KERNEL);
95 : : if (!vbuf)
96 : : return ERR_PTR(-ENOMEM);
97 : :
98 : : BUG_ON(size > MAX_INLINE_CMD_SIZE);
99 : : vbuf->buf = (void *)vbuf + sizeof(*vbuf);
100 : : vbuf->size = size;
101 : :
102 : : vbuf->resp_cb = resp_cb;
103 : : vbuf->resp_size = resp_size;
104 : : if (resp_size <= MAX_INLINE_RESP_SIZE)
105 : : vbuf->resp_buf = (void *)vbuf->buf + size;
106 : : else
107 : : vbuf->resp_buf = resp_buf;
108 : : BUG_ON(!vbuf->resp_buf);
109 : : return vbuf;
110 : : }
111 : :
112 : 0 : static void *virtio_gpu_alloc_cmd(struct virtio_gpu_device *vgdev,
113 : : struct virtio_gpu_vbuffer **vbuffer_p,
114 : : int size)
115 : : {
116 : 0 : struct virtio_gpu_vbuffer *vbuf;
117 : :
118 : 0 : vbuf = virtio_gpu_get_vbuf(vgdev, size,
119 : : sizeof(struct virtio_gpu_ctrl_hdr),
120 : : NULL, NULL);
121 [ # # # # : 0 : if (IS_ERR(vbuf)) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
122 : : *vbuffer_p = NULL;
123 : : return ERR_CAST(vbuf);
124 : : }
125 : 0 : *vbuffer_p = vbuf;
126 : 0 : return vbuf->buf;
127 : : }
128 : :
129 : : static struct virtio_gpu_update_cursor*
130 : 0 : virtio_gpu_alloc_cursor(struct virtio_gpu_device *vgdev,
131 : : struct virtio_gpu_vbuffer **vbuffer_p)
132 : : {
133 : 0 : struct virtio_gpu_vbuffer *vbuf;
134 : :
135 : 0 : vbuf = virtio_gpu_get_vbuf
136 : : (vgdev, sizeof(struct virtio_gpu_update_cursor),
137 : : 0, NULL, NULL);
138 [ # # ]: 0 : if (IS_ERR(vbuf)) {
139 : 0 : *vbuffer_p = NULL;
140 : 0 : return ERR_CAST(vbuf);
141 : : }
142 : 0 : *vbuffer_p = vbuf;
143 : 0 : return (struct virtio_gpu_update_cursor *)vbuf->buf;
144 : : }
145 : :
146 : 0 : static void *virtio_gpu_alloc_cmd_resp(struct virtio_gpu_device *vgdev,
147 : : virtio_gpu_resp_cb cb,
148 : : struct virtio_gpu_vbuffer **vbuffer_p,
149 : : int cmd_size, int resp_size,
150 : : void *resp_buf)
151 : : {
152 : 0 : struct virtio_gpu_vbuffer *vbuf;
153 : :
154 : 0 : vbuf = virtio_gpu_get_vbuf(vgdev, cmd_size,
155 : : resp_size, resp_buf, cb);
156 [ # # # # : 0 : if (IS_ERR(vbuf)) {
# # # # ]
157 : : *vbuffer_p = NULL;
158 : : return ERR_CAST(vbuf);
159 : : }
160 : 0 : *vbuffer_p = vbuf;
161 : 0 : return (struct virtio_gpu_command *)vbuf->buf;
162 : : }
163 : :
164 : : static void free_vbuf(struct virtio_gpu_device *vgdev,
165 : : struct virtio_gpu_vbuffer *vbuf)
166 : : {
167 : : if (vbuf->resp_size > MAX_INLINE_RESP_SIZE)
168 : : kfree(vbuf->resp_buf);
169 : : kvfree(vbuf->data_buf);
170 : : kmem_cache_free(vgdev->vbufs, vbuf);
171 : : }
172 : :
173 : 0 : static void reclaim_vbufs(struct virtqueue *vq, struct list_head *reclaim_list)
174 : : {
175 : 0 : struct virtio_gpu_vbuffer *vbuf;
176 : 0 : unsigned int len;
177 : 0 : int freed = 0;
178 : :
179 [ # # ]: 0 : while ((vbuf = virtqueue_get_buf(vq, &len))) {
180 : 0 : list_add_tail(&vbuf->list, reclaim_list);
181 : 0 : freed++;
182 : : }
183 [ # # ]: 0 : if (freed == 0)
184 : 0 : DRM_DEBUG("Huh? zero vbufs reclaimed");
185 : 0 : }
186 : :
187 : 0 : void virtio_gpu_dequeue_ctrl_func(struct work_struct *work)
188 : : {
189 : 0 : struct virtio_gpu_device *vgdev =
190 : 0 : container_of(work, struct virtio_gpu_device,
191 : : ctrlq.dequeue_work);
192 : 0 : struct list_head reclaim_list;
193 : 0 : struct virtio_gpu_vbuffer *entry, *tmp;
194 : 0 : struct virtio_gpu_ctrl_hdr *resp;
195 : 0 : u64 fence_id = 0;
196 : :
197 : 0 : INIT_LIST_HEAD(&reclaim_list);
198 : 0 : spin_lock(&vgdev->ctrlq.qlock);
199 : 0 : do {
200 : 0 : virtqueue_disable_cb(vgdev->ctrlq.vq);
201 : 0 : reclaim_vbufs(vgdev->ctrlq.vq, &reclaim_list);
202 : :
203 [ # # ]: 0 : } while (!virtqueue_enable_cb(vgdev->ctrlq.vq));
204 : 0 : spin_unlock(&vgdev->ctrlq.qlock);
205 : :
206 [ # # ]: 0 : list_for_each_entry(entry, &reclaim_list, list) {
207 : 0 : resp = (struct virtio_gpu_ctrl_hdr *)entry->resp_buf;
208 : :
209 : 0 : trace_virtio_gpu_cmd_response(vgdev->ctrlq.vq, resp);
210 : :
211 [ # # ]: 0 : if (resp->type != cpu_to_le32(VIRTIO_GPU_RESP_OK_NODATA)) {
212 [ # # ]: 0 : if (resp->type >= cpu_to_le32(VIRTIO_GPU_RESP_ERR_UNSPEC)) {
213 : 0 : struct virtio_gpu_ctrl_hdr *cmd;
214 : 0 : cmd = (struct virtio_gpu_ctrl_hdr *)entry->buf;
215 : 0 : DRM_ERROR("response 0x%x (command 0x%x)\n",
216 : : le32_to_cpu(resp->type),
217 : : le32_to_cpu(cmd->type));
218 : : } else
219 : 0 : DRM_DEBUG("response 0x%x\n", le32_to_cpu(resp->type));
220 : : }
221 [ # # ]: 0 : if (resp->flags & cpu_to_le32(VIRTIO_GPU_FLAG_FENCE)) {
222 : 0 : u64 f = le64_to_cpu(resp->fence_id);
223 : :
224 [ # # ]: 0 : if (fence_id > f) {
225 : 0 : DRM_ERROR("%s: Oops: fence %llx -> %llx\n",
226 : : __func__, fence_id, f);
227 : : } else {
228 : : fence_id = f;
229 : : }
230 : : }
231 [ # # ]: 0 : if (entry->resp_cb)
232 : 0 : entry->resp_cb(vgdev, entry);
233 : : }
234 : 0 : wake_up(&vgdev->ctrlq.ack_queue);
235 : :
236 [ # # ]: 0 : if (fence_id)
237 : 0 : virtio_gpu_fence_event_process(vgdev, fence_id);
238 : :
239 [ # # ]: 0 : list_for_each_entry_safe(entry, tmp, &reclaim_list, list) {
240 [ # # ]: 0 : if (entry->objs)
241 : 0 : virtio_gpu_array_put_free_delayed(vgdev, entry->objs);
242 : 0 : list_del(&entry->list);
243 : 0 : free_vbuf(vgdev, entry);
244 : : }
245 : 0 : }
246 : :
247 : 0 : void virtio_gpu_dequeue_cursor_func(struct work_struct *work)
248 : : {
249 : 0 : struct virtio_gpu_device *vgdev =
250 : 0 : container_of(work, struct virtio_gpu_device,
251 : : cursorq.dequeue_work);
252 : 0 : struct list_head reclaim_list;
253 : 0 : struct virtio_gpu_vbuffer *entry, *tmp;
254 : :
255 : 0 : INIT_LIST_HEAD(&reclaim_list);
256 : 0 : spin_lock(&vgdev->cursorq.qlock);
257 : 0 : do {
258 : 0 : virtqueue_disable_cb(vgdev->cursorq.vq);
259 : 0 : reclaim_vbufs(vgdev->cursorq.vq, &reclaim_list);
260 [ # # ]: 0 : } while (!virtqueue_enable_cb(vgdev->cursorq.vq));
261 : 0 : spin_unlock(&vgdev->cursorq.qlock);
262 : :
263 [ # # ]: 0 : list_for_each_entry_safe(entry, tmp, &reclaim_list, list) {
264 : 0 : list_del(&entry->list);
265 : 0 : free_vbuf(vgdev, entry);
266 : : }
267 : 0 : wake_up(&vgdev->cursorq.ack_queue);
268 : 0 : }
269 : :
270 : : /* Create sg_table from a vmalloc'd buffer. */
271 : 0 : static struct sg_table *vmalloc_to_sgt(char *data, uint32_t size, int *sg_ents)
272 : : {
273 : 0 : int ret, s, i;
274 : 0 : struct sg_table *sgt;
275 : 0 : struct scatterlist *sg;
276 : 0 : struct page *pg;
277 : :
278 [ # # # # ]: 0 : if (WARN_ON(!PAGE_ALIGNED(data)))
279 : : return NULL;
280 : :
281 : 0 : sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
282 [ # # ]: 0 : if (!sgt)
283 : : return NULL;
284 : :
285 : 0 : *sg_ents = DIV_ROUND_UP(size, PAGE_SIZE);
286 : 0 : ret = sg_alloc_table(sgt, *sg_ents, GFP_KERNEL);
287 [ # # ]: 0 : if (ret) {
288 : 0 : kfree(sgt);
289 : 0 : return NULL;
290 : : }
291 : :
292 [ # # ]: 0 : for_each_sg(sgt->sgl, sg, *sg_ents, i) {
293 : 0 : pg = vmalloc_to_page(data);
294 [ # # ]: 0 : if (!pg) {
295 : 0 : sg_free_table(sgt);
296 : 0 : kfree(sgt);
297 : 0 : return NULL;
298 : : }
299 : :
300 : 0 : s = min_t(int, PAGE_SIZE, size);
301 [ # # ]: 0 : sg_set_page(sg, pg, s, 0);
302 : :
303 : 0 : size -= s;
304 : 0 : data += s;
305 : : }
306 : :
307 : : return sgt;
308 : : }
309 : :
310 : 0 : static bool virtio_gpu_queue_ctrl_buffer_locked(struct virtio_gpu_device *vgdev,
311 : : struct virtio_gpu_vbuffer *vbuf,
312 : : struct scatterlist *vout)
313 : : __releases(&vgdev->ctrlq.qlock)
314 : : __acquires(&vgdev->ctrlq.qlock)
315 : : {
316 : 0 : struct virtqueue *vq = vgdev->ctrlq.vq;
317 : 0 : struct scatterlist *sgs[3], vcmd, vresp;
318 : 0 : int outcnt = 0, incnt = 0;
319 : 0 : bool notify = false;
320 : 0 : int ret;
321 : :
322 [ # # ]: 0 : if (!vgdev->vqs_ready)
323 : : return notify;
324 : :
325 : 0 : sg_init_one(&vcmd, vbuf->buf, vbuf->size);
326 : 0 : sgs[outcnt + incnt] = &vcmd;
327 : 0 : outcnt++;
328 : :
329 [ # # ]: 0 : if (vout) {
330 : 0 : sgs[outcnt + incnt] = vout;
331 : 0 : outcnt++;
332 : : }
333 : :
334 [ # # ]: 0 : if (vbuf->resp_size) {
335 : 0 : sg_init_one(&vresp, vbuf->resp_buf, vbuf->resp_size);
336 : 0 : sgs[outcnt + incnt] = &vresp;
337 : 0 : incnt++;
338 : : }
339 : :
340 : 0 : retry:
341 : 0 : ret = virtqueue_add_sgs(vq, sgs, outcnt, incnt, vbuf, GFP_ATOMIC);
342 [ # # ]: 0 : if (ret == -ENOSPC) {
343 : 0 : spin_unlock(&vgdev->ctrlq.qlock);
344 [ # # # # ]: 0 : wait_event(vgdev->ctrlq.ack_queue, vq->num_free >= outcnt + incnt);
345 : 0 : spin_lock(&vgdev->ctrlq.qlock);
346 : 0 : goto retry;
347 : : } else {
348 : 0 : trace_virtio_gpu_cmd_queue(vq,
349 : 0 : (struct virtio_gpu_ctrl_hdr *)vbuf->buf);
350 : :
351 : 0 : notify = virtqueue_kick_prepare(vq);
352 : : }
353 : 0 : return notify;
354 : : }
355 : :
356 : 0 : static void virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev,
357 : : struct virtio_gpu_vbuffer *vbuf,
358 : : struct virtio_gpu_ctrl_hdr *hdr,
359 : : struct virtio_gpu_fence *fence)
360 : : {
361 : 0 : struct virtqueue *vq = vgdev->ctrlq.vq;
362 : 0 : struct scatterlist *vout = NULL, sg;
363 : 0 : struct sg_table *sgt = NULL;
364 : 0 : bool notify;
365 : 0 : int outcnt = 0;
366 : :
367 [ # # ]: 0 : if (vbuf->data_size) {
368 [ # # ]: 0 : if (is_vmalloc_addr(vbuf->data_buf)) {
369 : 0 : sgt = vmalloc_to_sgt(vbuf->data_buf, vbuf->data_size,
370 : : &outcnt);
371 [ # # ]: 0 : if (!sgt)
372 : 0 : return;
373 : 0 : vout = sgt->sgl;
374 : : } else {
375 : 0 : sg_init_one(&sg, vbuf->data_buf, vbuf->data_size);
376 : 0 : vout = &sg;
377 : 0 : outcnt = 1;
378 : : }
379 : : }
380 : :
381 : 0 : again:
382 : 0 : spin_lock(&vgdev->ctrlq.qlock);
383 : :
384 : : /*
385 : : * Make sure we have enouth space in the virtqueue. If not
386 : : * wait here until we have.
387 : : *
388 : : * Without that virtio_gpu_queue_ctrl_buffer_nolock might have
389 : : * to wait for free space, which can result in fence ids being
390 : : * submitted out-of-order.
391 : : */
392 [ # # ]: 0 : if (vq->num_free < 2 + outcnt) {
393 : 0 : spin_unlock(&vgdev->ctrlq.qlock);
394 [ # # # # ]: 0 : wait_event(vgdev->ctrlq.ack_queue, vq->num_free >= 3);
395 : 0 : goto again;
396 : : }
397 : :
398 [ # # ]: 0 : if (hdr && fence) {
399 : 0 : virtio_gpu_fence_emit(vgdev, hdr, fence);
400 [ # # ]: 0 : if (vbuf->objs) {
401 : 0 : virtio_gpu_array_add_fence(vbuf->objs, &fence->f);
402 : 0 : virtio_gpu_array_unlock_resv(vbuf->objs);
403 : : }
404 : : }
405 : 0 : notify = virtio_gpu_queue_ctrl_buffer_locked(vgdev, vbuf, vout);
406 : 0 : spin_unlock(&vgdev->ctrlq.qlock);
407 [ # # ]: 0 : if (notify) {
408 [ # # ]: 0 : if (vgdev->disable_notify)
409 : 0 : vgdev->pending_notify = true;
410 : : else
411 : 0 : virtqueue_notify(vgdev->ctrlq.vq);
412 : : }
413 : :
414 [ # # ]: 0 : if (sgt) {
415 : 0 : sg_free_table(sgt);
416 : 0 : kfree(sgt);
417 : : }
418 : : }
419 : :
420 : 0 : void virtio_gpu_disable_notify(struct virtio_gpu_device *vgdev)
421 : : {
422 : 0 : vgdev->disable_notify = true;
423 : 0 : }
424 : :
425 : 0 : void virtio_gpu_enable_notify(struct virtio_gpu_device *vgdev)
426 : : {
427 : 0 : vgdev->disable_notify = false;
428 : :
429 [ # # ]: 0 : if (!vgdev->pending_notify)
430 : : return;
431 : 0 : vgdev->pending_notify = false;
432 : 0 : virtqueue_notify(vgdev->ctrlq.vq);
433 : : }
434 : :
435 : 0 : static void virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev,
436 : : struct virtio_gpu_vbuffer *vbuf)
437 : : {
438 : 0 : virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, NULL, NULL);
439 : : }
440 : :
441 : 0 : static void virtio_gpu_queue_cursor(struct virtio_gpu_device *vgdev,
442 : : struct virtio_gpu_vbuffer *vbuf)
443 : : {
444 : 0 : struct virtqueue *vq = vgdev->cursorq.vq;
445 : 0 : struct scatterlist *sgs[1], ccmd;
446 : 0 : bool notify;
447 : 0 : int ret;
448 : 0 : int outcnt;
449 : :
450 [ # # ]: 0 : if (!vgdev->vqs_ready)
451 : 0 : return;
452 : :
453 : 0 : sg_init_one(&ccmd, vbuf->buf, vbuf->size);
454 : 0 : sgs[0] = &ccmd;
455 : 0 : outcnt = 1;
456 : :
457 : 0 : spin_lock(&vgdev->cursorq.qlock);
458 : 0 : retry:
459 : 0 : ret = virtqueue_add_sgs(vq, sgs, outcnt, 0, vbuf, GFP_ATOMIC);
460 [ # # ]: 0 : if (ret == -ENOSPC) {
461 : 0 : spin_unlock(&vgdev->cursorq.qlock);
462 [ # # # # ]: 0 : wait_event(vgdev->cursorq.ack_queue, vq->num_free >= outcnt);
463 : 0 : spin_lock(&vgdev->cursorq.qlock);
464 : 0 : goto retry;
465 : : } else {
466 : 0 : trace_virtio_gpu_cmd_queue(vq,
467 : 0 : (struct virtio_gpu_ctrl_hdr *)vbuf->buf);
468 : :
469 : 0 : notify = virtqueue_kick_prepare(vq);
470 : : }
471 : :
472 : 0 : spin_unlock(&vgdev->cursorq.qlock);
473 : :
474 [ # # ]: 0 : if (notify)
475 : 0 : virtqueue_notify(vq);
476 : : }
477 : :
478 : : /* just create gem objects for userspace and long lived objects,
479 : : * just use dma_alloced pages for the queue objects?
480 : : */
481 : :
482 : : /* create a basic resource */
483 : 0 : void virtio_gpu_cmd_create_resource(struct virtio_gpu_device *vgdev,
484 : : struct virtio_gpu_object *bo,
485 : : struct virtio_gpu_object_params *params,
486 : : struct virtio_gpu_object_array *objs,
487 : : struct virtio_gpu_fence *fence)
488 : : {
489 : 0 : struct virtio_gpu_resource_create_2d *cmd_p;
490 : 0 : struct virtio_gpu_vbuffer *vbuf;
491 : :
492 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
493 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
494 : 0 : vbuf->objs = objs;
495 : :
496 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_CREATE_2D);
497 : 0 : cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
498 : 0 : cmd_p->format = cpu_to_le32(params->format);
499 : 0 : cmd_p->width = cpu_to_le32(params->width);
500 : 0 : cmd_p->height = cpu_to_le32(params->height);
501 : :
502 : 0 : virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
503 : 0 : bo->created = true;
504 : 0 : }
505 : :
506 : 0 : void virtio_gpu_cmd_unref_resource(struct virtio_gpu_device *vgdev,
507 : : uint32_t resource_id)
508 : : {
509 : 0 : struct virtio_gpu_resource_unref *cmd_p;
510 : 0 : struct virtio_gpu_vbuffer *vbuf;
511 : :
512 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
513 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
514 : :
515 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_UNREF);
516 : 0 : cmd_p->resource_id = cpu_to_le32(resource_id);
517 : :
518 : 0 : virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
519 : 0 : }
520 : :
521 : 0 : static void virtio_gpu_cmd_resource_inval_backing(struct virtio_gpu_device *vgdev,
522 : : uint32_t resource_id,
523 : : struct virtio_gpu_fence *fence)
524 : : {
525 : 0 : struct virtio_gpu_resource_detach_backing *cmd_p;
526 : 0 : struct virtio_gpu_vbuffer *vbuf;
527 : :
528 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
529 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
530 : :
531 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING);
532 : 0 : cmd_p->resource_id = cpu_to_le32(resource_id);
533 : :
534 : 0 : virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
535 : 0 : }
536 : :
537 : 0 : void virtio_gpu_cmd_set_scanout(struct virtio_gpu_device *vgdev,
538 : : uint32_t scanout_id, uint32_t resource_id,
539 : : uint32_t width, uint32_t height,
540 : : uint32_t x, uint32_t y)
541 : : {
542 : 0 : struct virtio_gpu_set_scanout *cmd_p;
543 : 0 : struct virtio_gpu_vbuffer *vbuf;
544 : :
545 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
546 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
547 : :
548 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_SET_SCANOUT);
549 : 0 : cmd_p->resource_id = cpu_to_le32(resource_id);
550 : 0 : cmd_p->scanout_id = cpu_to_le32(scanout_id);
551 : 0 : cmd_p->r.width = cpu_to_le32(width);
552 : 0 : cmd_p->r.height = cpu_to_le32(height);
553 : 0 : cmd_p->r.x = cpu_to_le32(x);
554 : 0 : cmd_p->r.y = cpu_to_le32(y);
555 : :
556 : 0 : virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
557 : 0 : }
558 : :
559 : 0 : void virtio_gpu_cmd_resource_flush(struct virtio_gpu_device *vgdev,
560 : : uint32_t resource_id,
561 : : uint32_t x, uint32_t y,
562 : : uint32_t width, uint32_t height)
563 : : {
564 : 0 : struct virtio_gpu_resource_flush *cmd_p;
565 : 0 : struct virtio_gpu_vbuffer *vbuf;
566 : :
567 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
568 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
569 : :
570 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_FLUSH);
571 : 0 : cmd_p->resource_id = cpu_to_le32(resource_id);
572 : 0 : cmd_p->r.width = cpu_to_le32(width);
573 : 0 : cmd_p->r.height = cpu_to_le32(height);
574 : 0 : cmd_p->r.x = cpu_to_le32(x);
575 : 0 : cmd_p->r.y = cpu_to_le32(y);
576 : :
577 : 0 : virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
578 : 0 : }
579 : :
580 : 0 : void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
581 : : uint64_t offset,
582 : : uint32_t width, uint32_t height,
583 : : uint32_t x, uint32_t y,
584 : : struct virtio_gpu_object_array *objs,
585 : : struct virtio_gpu_fence *fence)
586 : : {
587 : 0 : struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
588 : 0 : struct virtio_gpu_transfer_to_host_2d *cmd_p;
589 : 0 : struct virtio_gpu_vbuffer *vbuf;
590 : 0 : bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev);
591 : :
592 [ # # ]: 0 : if (use_dma_api)
593 : 0 : dma_sync_sg_for_device(vgdev->vdev->dev.parent,
594 : 0 : bo->pages->sgl, bo->pages->nents,
595 : : DMA_TO_DEVICE);
596 : :
597 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
598 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
599 : 0 : vbuf->objs = objs;
600 : :
601 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D);
602 : 0 : cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
603 : 0 : cmd_p->offset = cpu_to_le64(offset);
604 : 0 : cmd_p->r.width = cpu_to_le32(width);
605 : 0 : cmd_p->r.height = cpu_to_le32(height);
606 : 0 : cmd_p->r.x = cpu_to_le32(x);
607 : 0 : cmd_p->r.y = cpu_to_le32(y);
608 : :
609 : 0 : virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
610 : 0 : }
611 : :
612 : : static void
613 : 0 : virtio_gpu_cmd_resource_attach_backing(struct virtio_gpu_device *vgdev,
614 : : uint32_t resource_id,
615 : : struct virtio_gpu_mem_entry *ents,
616 : : uint32_t nents,
617 : : struct virtio_gpu_fence *fence)
618 : : {
619 : 0 : struct virtio_gpu_resource_attach_backing *cmd_p;
620 : 0 : struct virtio_gpu_vbuffer *vbuf;
621 : :
622 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
623 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
624 : :
625 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING);
626 : 0 : cmd_p->resource_id = cpu_to_le32(resource_id);
627 : 0 : cmd_p->nr_entries = cpu_to_le32(nents);
628 : :
629 : 0 : vbuf->data_buf = ents;
630 : 0 : vbuf->data_size = sizeof(*ents) * nents;
631 : :
632 : 0 : virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
633 : 0 : }
634 : :
635 : 0 : static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
636 : : struct virtio_gpu_vbuffer *vbuf)
637 : : {
638 : 0 : struct virtio_gpu_resp_display_info *resp =
639 : : (struct virtio_gpu_resp_display_info *)vbuf->resp_buf;
640 : 0 : int i;
641 : :
642 : 0 : spin_lock(&vgdev->display_info_lock);
643 [ # # ]: 0 : for (i = 0; i < vgdev->num_scanouts; i++) {
644 : 0 : vgdev->outputs[i].info = resp->pmodes[i];
645 [ # # ]: 0 : if (resp->pmodes[i].enabled) {
646 : 0 : DRM_DEBUG("output %d: %dx%d+%d+%d", i,
647 : : le32_to_cpu(resp->pmodes[i].r.width),
648 : : le32_to_cpu(resp->pmodes[i].r.height),
649 : : le32_to_cpu(resp->pmodes[i].r.x),
650 : : le32_to_cpu(resp->pmodes[i].r.y));
651 : : } else {
652 : 0 : DRM_DEBUG("output %d: disabled", i);
653 : : }
654 : : }
655 : :
656 : 0 : vgdev->display_info_pending = false;
657 : 0 : spin_unlock(&vgdev->display_info_lock);
658 : 0 : wake_up(&vgdev->resp_wq);
659 : :
660 [ # # ]: 0 : if (!drm_helper_hpd_irq_event(vgdev->ddev))
661 : 0 : drm_kms_helper_hotplug_event(vgdev->ddev);
662 : 0 : }
663 : :
664 : 0 : static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
665 : : struct virtio_gpu_vbuffer *vbuf)
666 : : {
667 : 0 : struct virtio_gpu_get_capset_info *cmd =
668 : : (struct virtio_gpu_get_capset_info *)vbuf->buf;
669 : 0 : struct virtio_gpu_resp_capset_info *resp =
670 : : (struct virtio_gpu_resp_capset_info *)vbuf->resp_buf;
671 : 0 : int i = le32_to_cpu(cmd->capset_index);
672 : :
673 : 0 : spin_lock(&vgdev->display_info_lock);
674 : 0 : vgdev->capsets[i].id = le32_to_cpu(resp->capset_id);
675 : 0 : vgdev->capsets[i].max_version = le32_to_cpu(resp->capset_max_version);
676 : 0 : vgdev->capsets[i].max_size = le32_to_cpu(resp->capset_max_size);
677 : 0 : spin_unlock(&vgdev->display_info_lock);
678 : 0 : wake_up(&vgdev->resp_wq);
679 : 0 : }
680 : :
681 : 0 : static void virtio_gpu_cmd_capset_cb(struct virtio_gpu_device *vgdev,
682 : : struct virtio_gpu_vbuffer *vbuf)
683 : : {
684 : 0 : struct virtio_gpu_get_capset *cmd =
685 : : (struct virtio_gpu_get_capset *)vbuf->buf;
686 : 0 : struct virtio_gpu_resp_capset *resp =
687 : : (struct virtio_gpu_resp_capset *)vbuf->resp_buf;
688 : 0 : struct virtio_gpu_drv_cap_cache *cache_ent;
689 : :
690 : 0 : spin_lock(&vgdev->display_info_lock);
691 [ # # ]: 0 : list_for_each_entry(cache_ent, &vgdev->cap_cache, head) {
692 [ # # ]: 0 : if (cache_ent->version == le32_to_cpu(cmd->capset_version) &&
693 : : cache_ent->id == le32_to_cpu(cmd->capset_id)) {
694 : 0 : memcpy(cache_ent->caps_cache, resp->capset_data,
695 : 0 : cache_ent->size);
696 : : /* Copy must occur before is_valid is signalled. */
697 : 0 : smp_wmb();
698 : 0 : atomic_set(&cache_ent->is_valid, 1);
699 : : break;
700 : : }
701 : : }
702 : 0 : spin_unlock(&vgdev->display_info_lock);
703 : 0 : wake_up_all(&vgdev->resp_wq);
704 : 0 : }
705 : :
706 : 0 : static int virtio_get_edid_block(void *data, u8 *buf,
707 : : unsigned int block, size_t len)
708 : : {
709 : 0 : struct virtio_gpu_resp_edid *resp = data;
710 : 0 : size_t start = block * EDID_LENGTH;
711 : :
712 [ # # ]: 0 : if (start + len > le32_to_cpu(resp->size))
713 : : return -1;
714 : 0 : memcpy(buf, resp->edid + start, len);
715 : 0 : return 0;
716 : : }
717 : :
718 : 0 : static void virtio_gpu_cmd_get_edid_cb(struct virtio_gpu_device *vgdev,
719 : : struct virtio_gpu_vbuffer *vbuf)
720 : : {
721 : 0 : struct virtio_gpu_cmd_get_edid *cmd =
722 : : (struct virtio_gpu_cmd_get_edid *)vbuf->buf;
723 : 0 : struct virtio_gpu_resp_edid *resp =
724 : : (struct virtio_gpu_resp_edid *)vbuf->resp_buf;
725 : 0 : uint32_t scanout = le32_to_cpu(cmd->scanout);
726 : 0 : struct virtio_gpu_output *output;
727 : 0 : struct edid *new_edid, *old_edid;
728 : :
729 [ # # ]: 0 : if (scanout >= vgdev->num_scanouts)
730 : : return;
731 : 0 : output = vgdev->outputs + scanout;
732 : :
733 : 0 : new_edid = drm_do_get_edid(&output->conn, virtio_get_edid_block, resp);
734 : 0 : drm_connector_update_edid_property(&output->conn, new_edid);
735 : :
736 : 0 : spin_lock(&vgdev->display_info_lock);
737 : 0 : old_edid = output->edid;
738 : 0 : output->edid = new_edid;
739 : 0 : spin_unlock(&vgdev->display_info_lock);
740 : :
741 : 0 : kfree(old_edid);
742 : 0 : wake_up(&vgdev->resp_wq);
743 : : }
744 : :
745 : 0 : int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev)
746 : : {
747 : 0 : struct virtio_gpu_ctrl_hdr *cmd_p;
748 : 0 : struct virtio_gpu_vbuffer *vbuf;
749 : 0 : void *resp_buf;
750 : :
751 : 0 : resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_display_info),
752 : : GFP_KERNEL);
753 [ # # ]: 0 : if (!resp_buf)
754 : : return -ENOMEM;
755 : :
756 : 0 : cmd_p = virtio_gpu_alloc_cmd_resp
757 : : (vgdev, &virtio_gpu_cmd_get_display_info_cb, &vbuf,
758 : : sizeof(*cmd_p), sizeof(struct virtio_gpu_resp_display_info),
759 : : resp_buf);
760 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
761 : :
762 : 0 : vgdev->display_info_pending = true;
763 : 0 : cmd_p->type = cpu_to_le32(VIRTIO_GPU_CMD_GET_DISPLAY_INFO);
764 : 0 : virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
765 : 0 : return 0;
766 : : }
767 : :
768 : 0 : int virtio_gpu_cmd_get_capset_info(struct virtio_gpu_device *vgdev, int idx)
769 : : {
770 : 0 : struct virtio_gpu_get_capset_info *cmd_p;
771 : 0 : struct virtio_gpu_vbuffer *vbuf;
772 : 0 : void *resp_buf;
773 : :
774 : 0 : resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_capset_info),
775 : : GFP_KERNEL);
776 [ # # ]: 0 : if (!resp_buf)
777 : : return -ENOMEM;
778 : :
779 : 0 : cmd_p = virtio_gpu_alloc_cmd_resp
780 : : (vgdev, &virtio_gpu_cmd_get_capset_info_cb, &vbuf,
781 : : sizeof(*cmd_p), sizeof(struct virtio_gpu_resp_capset_info),
782 : : resp_buf);
783 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
784 : :
785 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_CAPSET_INFO);
786 : 0 : cmd_p->capset_index = cpu_to_le32(idx);
787 : 0 : virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
788 : 0 : return 0;
789 : : }
790 : :
791 : 0 : int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
792 : : int idx, int version,
793 : : struct virtio_gpu_drv_cap_cache **cache_p)
794 : : {
795 : 0 : struct virtio_gpu_get_capset *cmd_p;
796 : 0 : struct virtio_gpu_vbuffer *vbuf;
797 : 0 : int max_size;
798 : 0 : struct virtio_gpu_drv_cap_cache *cache_ent;
799 : 0 : struct virtio_gpu_drv_cap_cache *search_ent;
800 : 0 : void *resp_buf;
801 : :
802 : 0 : *cache_p = NULL;
803 : :
804 [ # # ]: 0 : if (idx >= vgdev->num_capsets)
805 : : return -EINVAL;
806 : :
807 [ # # ]: 0 : if (version > vgdev->capsets[idx].max_version)
808 : : return -EINVAL;
809 : :
810 : 0 : cache_ent = kzalloc(sizeof(*cache_ent), GFP_KERNEL);
811 [ # # ]: 0 : if (!cache_ent)
812 : : return -ENOMEM;
813 : :
814 : 0 : max_size = vgdev->capsets[idx].max_size;
815 [ # # ]: 0 : cache_ent->caps_cache = kmalloc(max_size, GFP_KERNEL);
816 [ # # ]: 0 : if (!cache_ent->caps_cache) {
817 : 0 : kfree(cache_ent);
818 : 0 : return -ENOMEM;
819 : : }
820 : :
821 : 0 : resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_capset) + max_size,
822 : : GFP_KERNEL);
823 [ # # ]: 0 : if (!resp_buf) {
824 : 0 : kfree(cache_ent->caps_cache);
825 : 0 : kfree(cache_ent);
826 : 0 : return -ENOMEM;
827 : : }
828 : :
829 : 0 : cache_ent->version = version;
830 : 0 : cache_ent->id = vgdev->capsets[idx].id;
831 : 0 : atomic_set(&cache_ent->is_valid, 0);
832 : 0 : cache_ent->size = max_size;
833 : 0 : spin_lock(&vgdev->display_info_lock);
834 : : /* Search while under lock in case it was added by another task. */
835 [ # # ]: 0 : list_for_each_entry(search_ent, &vgdev->cap_cache, head) {
836 [ # # ]: 0 : if (search_ent->id == vgdev->capsets[idx].id &&
837 [ # # ]: 0 : search_ent->version == version) {
838 : 0 : *cache_p = search_ent;
839 : 0 : break;
840 : : }
841 : : }
842 [ # # ]: 0 : if (!*cache_p)
843 : 0 : list_add_tail(&cache_ent->head, &vgdev->cap_cache);
844 : 0 : spin_unlock(&vgdev->display_info_lock);
845 : :
846 [ # # ]: 0 : if (*cache_p) {
847 : : /* Entry was found, so free everything that was just created. */
848 : 0 : kfree(resp_buf);
849 : 0 : kfree(cache_ent->caps_cache);
850 : 0 : kfree(cache_ent);
851 : 0 : return 0;
852 : : }
853 : :
854 : 0 : cmd_p = virtio_gpu_alloc_cmd_resp
855 : : (vgdev, &virtio_gpu_cmd_capset_cb, &vbuf, sizeof(*cmd_p),
856 : 0 : sizeof(struct virtio_gpu_resp_capset) + max_size,
857 : : resp_buf);
858 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_CAPSET);
859 : 0 : cmd_p->capset_id = cpu_to_le32(vgdev->capsets[idx].id);
860 : 0 : cmd_p->capset_version = cpu_to_le32(version);
861 : 0 : *cache_p = cache_ent;
862 : 0 : virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
863 : :
864 : 0 : return 0;
865 : : }
866 : :
867 : 0 : int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev)
868 : : {
869 : 0 : struct virtio_gpu_cmd_get_edid *cmd_p;
870 : 0 : struct virtio_gpu_vbuffer *vbuf;
871 : 0 : void *resp_buf;
872 : 0 : int scanout;
873 : :
874 [ # # # # ]: 0 : if (WARN_ON(!vgdev->has_edid))
875 : : return -EINVAL;
876 : :
877 [ # # ]: 0 : for (scanout = 0; scanout < vgdev->num_scanouts; scanout++) {
878 : 0 : resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_edid),
879 : : GFP_KERNEL);
880 [ # # ]: 0 : if (!resp_buf)
881 : : return -ENOMEM;
882 : :
883 : 0 : cmd_p = virtio_gpu_alloc_cmd_resp
884 : : (vgdev, &virtio_gpu_cmd_get_edid_cb, &vbuf,
885 : : sizeof(*cmd_p), sizeof(struct virtio_gpu_resp_edid),
886 : : resp_buf);
887 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_EDID);
888 : 0 : cmd_p->scanout = cpu_to_le32(scanout);
889 : 0 : virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
890 : : }
891 : :
892 : : return 0;
893 : : }
894 : :
895 : 0 : void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
896 : : uint32_t nlen, const char *name)
897 : : {
898 : 0 : struct virtio_gpu_ctx_create *cmd_p;
899 : 0 : struct virtio_gpu_vbuffer *vbuf;
900 : :
901 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
902 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
903 : :
904 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_CREATE);
905 : 0 : cmd_p->hdr.ctx_id = cpu_to_le32(id);
906 : 0 : cmd_p->nlen = cpu_to_le32(nlen);
907 : 0 : strncpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name) - 1);
908 : 0 : cmd_p->debug_name[sizeof(cmd_p->debug_name) - 1] = 0;
909 : 0 : virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
910 : 0 : }
911 : :
912 : 0 : void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev,
913 : : uint32_t id)
914 : : {
915 : 0 : struct virtio_gpu_ctx_destroy *cmd_p;
916 : 0 : struct virtio_gpu_vbuffer *vbuf;
917 : :
918 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
919 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
920 : :
921 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_DESTROY);
922 : 0 : cmd_p->hdr.ctx_id = cpu_to_le32(id);
923 : 0 : virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
924 : 0 : }
925 : :
926 : 0 : void virtio_gpu_cmd_context_attach_resource(struct virtio_gpu_device *vgdev,
927 : : uint32_t ctx_id,
928 : : struct virtio_gpu_object_array *objs)
929 : : {
930 : 0 : struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
931 : 0 : struct virtio_gpu_ctx_resource *cmd_p;
932 : 0 : struct virtio_gpu_vbuffer *vbuf;
933 : :
934 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
935 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
936 : 0 : vbuf->objs = objs;
937 : :
938 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE);
939 : 0 : cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
940 : 0 : cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
941 : 0 : virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
942 : :
943 : 0 : }
944 : :
945 : 0 : void virtio_gpu_cmd_context_detach_resource(struct virtio_gpu_device *vgdev,
946 : : uint32_t ctx_id,
947 : : struct virtio_gpu_object_array *objs)
948 : : {
949 : 0 : struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
950 : 0 : struct virtio_gpu_ctx_resource *cmd_p;
951 : 0 : struct virtio_gpu_vbuffer *vbuf;
952 : :
953 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
954 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
955 : 0 : vbuf->objs = objs;
956 : :
957 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE);
958 : 0 : cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
959 : 0 : cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
960 : 0 : virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
961 : 0 : }
962 : :
963 : : void
964 : 0 : virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev,
965 : : struct virtio_gpu_object *bo,
966 : : struct virtio_gpu_object_params *params,
967 : : struct virtio_gpu_object_array *objs,
968 : : struct virtio_gpu_fence *fence)
969 : : {
970 : 0 : struct virtio_gpu_resource_create_3d *cmd_p;
971 : 0 : struct virtio_gpu_vbuffer *vbuf;
972 : :
973 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
974 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
975 : 0 : vbuf->objs = objs;
976 : :
977 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_CREATE_3D);
978 : 0 : cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
979 : 0 : cmd_p->format = cpu_to_le32(params->format);
980 : 0 : cmd_p->width = cpu_to_le32(params->width);
981 : 0 : cmd_p->height = cpu_to_le32(params->height);
982 : :
983 : 0 : cmd_p->target = cpu_to_le32(params->target);
984 : 0 : cmd_p->bind = cpu_to_le32(params->bind);
985 : 0 : cmd_p->depth = cpu_to_le32(params->depth);
986 : 0 : cmd_p->array_size = cpu_to_le32(params->array_size);
987 : 0 : cmd_p->last_level = cpu_to_le32(params->last_level);
988 : 0 : cmd_p->nr_samples = cpu_to_le32(params->nr_samples);
989 : 0 : cmd_p->flags = cpu_to_le32(params->flags);
990 : :
991 : 0 : virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
992 : 0 : bo->created = true;
993 : 0 : }
994 : :
995 : 0 : void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
996 : : uint32_t ctx_id,
997 : : uint64_t offset, uint32_t level,
998 : : struct drm_virtgpu_3d_box *box,
999 : : struct virtio_gpu_object_array *objs,
1000 : : struct virtio_gpu_fence *fence)
1001 : : {
1002 : 0 : struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
1003 : 0 : struct virtio_gpu_transfer_host_3d *cmd_p;
1004 : 0 : struct virtio_gpu_vbuffer *vbuf;
1005 : 0 : bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev);
1006 : :
1007 [ # # ]: 0 : if (use_dma_api)
1008 : 0 : dma_sync_sg_for_device(vgdev->vdev->dev.parent,
1009 : 0 : bo->pages->sgl, bo->pages->nents,
1010 : : DMA_TO_DEVICE);
1011 : :
1012 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
1013 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
1014 : :
1015 : 0 : vbuf->objs = objs;
1016 : :
1017 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D);
1018 : 0 : cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
1019 : 0 : cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
1020 : 0 : convert_to_hw_box(&cmd_p->box, box);
1021 : 0 : cmd_p->offset = cpu_to_le64(offset);
1022 : 0 : cmd_p->level = cpu_to_le32(level);
1023 : :
1024 : 0 : virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
1025 : 0 : }
1026 : :
1027 : 0 : void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev,
1028 : : uint32_t ctx_id,
1029 : : uint64_t offset, uint32_t level,
1030 : : struct drm_virtgpu_3d_box *box,
1031 : : struct virtio_gpu_object_array *objs,
1032 : : struct virtio_gpu_fence *fence)
1033 : : {
1034 : 0 : struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
1035 : 0 : struct virtio_gpu_transfer_host_3d *cmd_p;
1036 : 0 : struct virtio_gpu_vbuffer *vbuf;
1037 : :
1038 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
1039 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
1040 : :
1041 : 0 : vbuf->objs = objs;
1042 : :
1043 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D);
1044 : 0 : cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
1045 : 0 : cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
1046 : 0 : convert_to_hw_box(&cmd_p->box, box);
1047 : 0 : cmd_p->offset = cpu_to_le64(offset);
1048 : 0 : cmd_p->level = cpu_to_le32(level);
1049 : :
1050 : 0 : virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
1051 : 0 : }
1052 : :
1053 : 0 : void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev,
1054 : : void *data, uint32_t data_size,
1055 : : uint32_t ctx_id,
1056 : : struct virtio_gpu_object_array *objs,
1057 : : struct virtio_gpu_fence *fence)
1058 : : {
1059 : 0 : struct virtio_gpu_cmd_submit *cmd_p;
1060 : 0 : struct virtio_gpu_vbuffer *vbuf;
1061 : :
1062 : 0 : cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
1063 : 0 : memset(cmd_p, 0, sizeof(*cmd_p));
1064 : :
1065 : 0 : vbuf->data_buf = data;
1066 : 0 : vbuf->data_size = data_size;
1067 : 0 : vbuf->objs = objs;
1068 : :
1069 : 0 : cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_SUBMIT_3D);
1070 : 0 : cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
1071 : 0 : cmd_p->size = cpu_to_le32(data_size);
1072 : :
1073 : 0 : virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
1074 : 0 : }
1075 : :
1076 : 0 : int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev,
1077 : : struct virtio_gpu_object *obj,
1078 : : struct virtio_gpu_fence *fence)
1079 : : {
1080 : 0 : bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev);
1081 : 0 : struct virtio_gpu_mem_entry *ents;
1082 : 0 : struct scatterlist *sg;
1083 : 0 : int si, nents, ret;
1084 : :
1085 [ # # # # ]: 0 : if (WARN_ON_ONCE(!obj->created))
1086 : : return -EINVAL;
1087 [ # # # # ]: 0 : if (WARN_ON_ONCE(obj->pages))
1088 : : return -EINVAL;
1089 : :
1090 : 0 : ret = drm_gem_shmem_pin(&obj->base.base);
1091 [ # # ]: 0 : if (ret < 0)
1092 : : return -EINVAL;
1093 : :
1094 : 0 : obj->pages = drm_gem_shmem_get_sg_table(&obj->base.base);
1095 [ # # ]: 0 : if (obj->pages == NULL) {
1096 : 0 : drm_gem_shmem_unpin(&obj->base.base);
1097 : 0 : return -EINVAL;
1098 : : }
1099 : :
1100 [ # # ]: 0 : if (use_dma_api) {
1101 : 0 : obj->mapped = dma_map_sg(vgdev->vdev->dev.parent,
1102 : : obj->pages->sgl, obj->pages->nents,
1103 : : DMA_TO_DEVICE);
1104 : 0 : nents = obj->mapped;
1105 : : } else {
1106 : 0 : nents = obj->pages->nents;
1107 : : }
1108 : :
1109 : : /* gets freed when the ring has consumed it */
1110 : 0 : ents = kmalloc_array(nents, sizeof(struct virtio_gpu_mem_entry),
1111 : : GFP_KERNEL);
1112 [ # # ]: 0 : if (!ents) {
1113 : 0 : DRM_ERROR("failed to allocate ent list\n");
1114 : 0 : return -ENOMEM;
1115 : : }
1116 : :
1117 [ # # ]: 0 : for_each_sg(obj->pages->sgl, sg, nents, si) {
1118 [ # # ]: 0 : ents[si].addr = cpu_to_le64(use_dma_api
1119 : : ? sg_dma_address(sg)
1120 : : : sg_phys(sg));
1121 : 0 : ents[si].length = cpu_to_le32(sg->length);
1122 : 0 : ents[si].padding = 0;
1123 : : }
1124 : :
1125 : 0 : virtio_gpu_cmd_resource_attach_backing(vgdev, obj->hw_res_handle,
1126 : : ents, nents,
1127 : : fence);
1128 : 0 : return 0;
1129 : : }
1130 : :
1131 : 0 : void virtio_gpu_object_detach(struct virtio_gpu_device *vgdev,
1132 : : struct virtio_gpu_object *obj)
1133 : : {
1134 : 0 : bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev);
1135 : :
1136 [ # # # # ]: 0 : if (WARN_ON_ONCE(!obj->pages))
1137 : : return;
1138 : :
1139 [ # # # # ]: 0 : if (use_dma_api && obj->mapped) {
1140 : 0 : struct virtio_gpu_fence *fence = virtio_gpu_fence_alloc(vgdev);
1141 : : /* detach backing and wait for the host process it ... */
1142 : 0 : virtio_gpu_cmd_resource_inval_backing(vgdev, obj->hw_res_handle, fence);
1143 : 0 : dma_fence_wait(&fence->f, true);
1144 : 0 : dma_fence_put(&fence->f);
1145 : :
1146 : : /* ... then tear down iommu mappings */
1147 : 0 : dma_unmap_sg(vgdev->vdev->dev.parent,
1148 : : obj->pages->sgl, obj->mapped,
1149 : : DMA_TO_DEVICE);
1150 : 0 : obj->mapped = 0;
1151 : : } else {
1152 : 0 : virtio_gpu_cmd_resource_inval_backing(vgdev, obj->hw_res_handle, NULL);
1153 : : }
1154 : :
1155 : 0 : sg_free_table(obj->pages);
1156 : 0 : obj->pages = NULL;
1157 : :
1158 : 0 : drm_gem_shmem_unpin(&obj->base.base);
1159 : : }
1160 : :
1161 : 0 : void virtio_gpu_cursor_ping(struct virtio_gpu_device *vgdev,
1162 : : struct virtio_gpu_output *output)
1163 : : {
1164 : 0 : struct virtio_gpu_vbuffer *vbuf;
1165 : 0 : struct virtio_gpu_update_cursor *cur_p;
1166 : :
1167 : 0 : output->cursor.pos.scanout_id = cpu_to_le32(output->index);
1168 : 0 : cur_p = virtio_gpu_alloc_cursor(vgdev, &vbuf);
1169 : 0 : memcpy(cur_p, &output->cursor, sizeof(output->cursor));
1170 : 0 : virtio_gpu_queue_cursor(vgdev, vbuf);
1171 : 0 : }
|