vmwgfx: Break out and comment vmw_execbuf_copy_fence_user
[linux-2.6-block.git] / drivers / gpu / drm / vmwgfx / vmwgfx_execbuf.c
CommitLineData
fb1d9738
JB
1/**************************************************************************
2 *
3 * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include "vmwgfx_drv.h"
29#include "vmwgfx_reg.h"
30#include "ttm/ttm_bo_api.h"
31#include "ttm/ttm_placement.h"
32
33static int vmw_cmd_invalid(struct vmw_private *dev_priv,
34 struct vmw_sw_context *sw_context,
35 SVGA3dCmdHeader *header)
36{
37 return capable(CAP_SYS_ADMIN) ? : -EINVAL;
38}
39
40static int vmw_cmd_ok(struct vmw_private *dev_priv,
41 struct vmw_sw_context *sw_context,
42 SVGA3dCmdHeader *header)
43{
44 return 0;
45}
46
f18c8840
TH
47static void vmw_resource_to_validate_list(struct vmw_sw_context *sw_context,
48 struct vmw_resource **p_res)
be38ab6e 49{
be38ab6e
TH
50 struct vmw_resource *res = *p_res;
51
f18c8840
TH
52 if (list_empty(&res->validate_head)) {
53 list_add_tail(&res->validate_head, &sw_context->resource_list);
54 *p_res = NULL;
55 } else
56 vmw_resource_unreference(p_res);
be38ab6e
TH
57}
58
e2fa3a76
TH
59/**
60 * vmw_bo_to_validate_list - add a bo to a validate list
61 *
62 * @sw_context: The software context used for this command submission batch.
63 * @bo: The buffer object to add.
64 * @fence_flags: Fence flags to be or'ed with any other fence flags for
65 * this buffer on this submission batch.
66 * @p_val_node: If non-NULL Will be updated with the validate node number
67 * on return.
68 *
69 * Returns -EINVAL if the limit of number of buffer objects per command
70 * submission is reached.
71 */
72static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
73 struct ttm_buffer_object *bo,
74 uint32_t fence_flags,
75 uint32_t *p_val_node)
76{
77 uint32_t val_node;
78 struct ttm_validate_buffer *val_buf;
79
80 val_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf);
81
82 if (unlikely(val_node >= VMWGFX_MAX_VALIDATIONS)) {
83 DRM_ERROR("Max number of DMA buffers per submission"
84 " exceeded.\n");
85 return -EINVAL;
86 }
87
88 val_buf = &sw_context->val_bufs[val_node];
89 if (unlikely(val_node == sw_context->cur_val_buf)) {
90 val_buf->new_sync_obj_arg = NULL;
91 val_buf->bo = ttm_bo_reference(bo);
92 val_buf->usage = TTM_USAGE_READWRITE;
93 list_add_tail(&val_buf->head, &sw_context->validate_nodes);
94 ++sw_context->cur_val_buf;
95 }
96
97 val_buf->new_sync_obj_arg = (void *)
98 ((unsigned long) val_buf->new_sync_obj_arg | fence_flags);
99 sw_context->fence_flags |= fence_flags;
100
101 if (p_val_node)
102 *p_val_node = val_node;
103
104 return 0;
105}
106
fb1d9738
JB
107static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
108 struct vmw_sw_context *sw_context,
109 SVGA3dCmdHeader *header)
110{
be38ab6e
TH
111 struct vmw_resource *ctx;
112
fb1d9738
JB
113 struct vmw_cid_cmd {
114 SVGA3dCmdHeader header;
115 __le32 cid;
116 } *cmd;
117 int ret;
118
119 cmd = container_of(header, struct vmw_cid_cmd, header);
120 if (likely(sw_context->cid_valid && cmd->cid == sw_context->last_cid))
121 return 0;
122
be38ab6e
TH
123 ret = vmw_context_check(dev_priv, sw_context->tfile, cmd->cid,
124 &ctx);
fb1d9738
JB
125 if (unlikely(ret != 0)) {
126 DRM_ERROR("Could not find or use context %u\n",
127 (unsigned) cmd->cid);
128 return ret;
129 }
130
131 sw_context->last_cid = cmd->cid;
132 sw_context->cid_valid = true;
e2fa3a76 133 sw_context->cur_ctx = ctx;
f18c8840
TH
134 vmw_resource_to_validate_list(sw_context, &ctx);
135
136 return 0;
fb1d9738
JB
137}
138
139static int vmw_cmd_sid_check(struct vmw_private *dev_priv,
140 struct vmw_sw_context *sw_context,
7a73ba74 141 uint32_t *sid)
fb1d9738 142{
be38ab6e
TH
143 struct vmw_surface *srf;
144 int ret;
145 struct vmw_resource *res;
146
7a73ba74
TH
147 if (*sid == SVGA3D_INVALID_ID)
148 return 0;
149
be38ab6e
TH
150 if (likely((sw_context->sid_valid &&
151 *sid == sw_context->last_sid))) {
7a73ba74 152 *sid = sw_context->sid_translation;
be38ab6e
TH
153 return 0;
154 }
7a73ba74 155
e2fa3a76
TH
156 ret = vmw_user_surface_lookup_handle(dev_priv,
157 sw_context->tfile,
be38ab6e
TH
158 *sid, &srf);
159 if (unlikely(ret != 0)) {
160 DRM_ERROR("Could ot find or use surface 0x%08x "
161 "address 0x%08lx\n",
162 (unsigned int) *sid,
163 (unsigned long) sid);
164 return ret;
165 }
166
5bb39e81
TH
167 ret = vmw_surface_validate(dev_priv, srf);
168 if (unlikely(ret != 0)) {
169 if (ret != -ERESTARTSYS)
170 DRM_ERROR("Could not validate surface.\n");
171 vmw_surface_unreference(&srf);
172 return ret;
173 }
174
be38ab6e
TH
175 sw_context->last_sid = *sid;
176 sw_context->sid_valid = true;
177 sw_context->sid_translation = srf->res.id;
178 *sid = sw_context->sid_translation;
179
180 res = &srf->res;
f18c8840
TH
181 vmw_resource_to_validate_list(sw_context, &res);
182
183 return 0;
fb1d9738
JB
184}
185
186
187static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
188 struct vmw_sw_context *sw_context,
189 SVGA3dCmdHeader *header)
190{
191 struct vmw_sid_cmd {
192 SVGA3dCmdHeader header;
193 SVGA3dCmdSetRenderTarget body;
194 } *cmd;
195 int ret;
196
197 ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
198 if (unlikely(ret != 0))
199 return ret;
200
201 cmd = container_of(header, struct vmw_sid_cmd, header);
7a73ba74
TH
202 ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.target.sid);
203 return ret;
fb1d9738
JB
204}
205
206static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
207 struct vmw_sw_context *sw_context,
208 SVGA3dCmdHeader *header)
209{
210 struct vmw_sid_cmd {
211 SVGA3dCmdHeader header;
212 SVGA3dCmdSurfaceCopy body;
213 } *cmd;
214 int ret;
215
216 cmd = container_of(header, struct vmw_sid_cmd, header);
7a73ba74 217 ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid);
fb1d9738
JB
218 if (unlikely(ret != 0))
219 return ret;
7a73ba74 220 return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid);
fb1d9738
JB
221}
222
223static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv,
224 struct vmw_sw_context *sw_context,
225 SVGA3dCmdHeader *header)
226{
227 struct vmw_sid_cmd {
228 SVGA3dCmdHeader header;
229 SVGA3dCmdSurfaceStretchBlt body;
230 } *cmd;
231 int ret;
232
233 cmd = container_of(header, struct vmw_sid_cmd, header);
7a73ba74 234 ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid);
fb1d9738
JB
235 if (unlikely(ret != 0))
236 return ret;
7a73ba74 237 return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid);
fb1d9738
JB
238}
239
240static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
241 struct vmw_sw_context *sw_context,
242 SVGA3dCmdHeader *header)
243{
244 struct vmw_sid_cmd {
245 SVGA3dCmdHeader header;
246 SVGA3dCmdBlitSurfaceToScreen body;
247 } *cmd;
248
249 cmd = container_of(header, struct vmw_sid_cmd, header);
0cff60c6
JB
250
251 if (unlikely(!sw_context->kernel)) {
252 DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id);
253 return -EPERM;
254 }
255
7a73ba74 256 return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.srcImage.sid);
fb1d9738
JB
257}
258
259static int vmw_cmd_present_check(struct vmw_private *dev_priv,
260 struct vmw_sw_context *sw_context,
261 SVGA3dCmdHeader *header)
262{
263 struct vmw_sid_cmd {
264 SVGA3dCmdHeader header;
265 SVGA3dCmdPresent body;
266 } *cmd;
267
5bb39e81 268
fb1d9738 269 cmd = container_of(header, struct vmw_sid_cmd, header);
0cff60c6
JB
270
271 if (unlikely(!sw_context->kernel)) {
272 DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id);
273 return -EPERM;
274 }
275
7a73ba74 276 return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.sid);
fb1d9738
JB
277}
278
e2fa3a76
TH
279/**
280 * vmw_query_bo_switch_prepare - Prepare to switch pinned buffer for queries.
281 *
282 * @dev_priv: The device private structure.
283 * @cid: The hardware context for the next query.
284 * @new_query_bo: The new buffer holding query results.
285 * @sw_context: The software context used for this command submission.
286 *
287 * This function checks whether @new_query_bo is suitable for holding
288 * query results, and if another buffer currently is pinned for query
289 * results. If so, the function prepares the state of @sw_context for
290 * switching pinned buffers after successful submission of the current
291 * command batch. It also checks whether we're using a new query context.
292 * In that case, it makes sure we emit a query barrier for the old
293 * context before the current query buffer is fenced.
294 */
295static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
296 uint32_t cid,
297 struct ttm_buffer_object *new_query_bo,
298 struct vmw_sw_context *sw_context)
299{
300 int ret;
301 bool add_cid = false;
302 uint32_t cid_to_add;
303
304 if (unlikely(new_query_bo != sw_context->cur_query_bo)) {
305
306 if (unlikely(new_query_bo->num_pages > 4)) {
307 DRM_ERROR("Query buffer too large.\n");
308 return -EINVAL;
309 }
310
311 if (unlikely(sw_context->cur_query_bo != NULL)) {
312 BUG_ON(!sw_context->query_cid_valid);
313 add_cid = true;
314 cid_to_add = sw_context->cur_query_cid;
315 ret = vmw_bo_to_validate_list(sw_context,
316 sw_context->cur_query_bo,
317 DRM_VMW_FENCE_FLAG_EXEC,
318 NULL);
319 if (unlikely(ret != 0))
320 return ret;
321 }
322 sw_context->cur_query_bo = new_query_bo;
323
324 ret = vmw_bo_to_validate_list(sw_context,
325 dev_priv->dummy_query_bo,
326 DRM_VMW_FENCE_FLAG_EXEC,
327 NULL);
328 if (unlikely(ret != 0))
329 return ret;
330
331 }
332
333 if (unlikely(cid != sw_context->cur_query_cid &&
334 sw_context->query_cid_valid)) {
335 add_cid = true;
336 cid_to_add = sw_context->cur_query_cid;
337 }
338
339 sw_context->cur_query_cid = cid;
340 sw_context->query_cid_valid = true;
341
342 if (add_cid) {
343 struct vmw_resource *ctx = sw_context->cur_ctx;
344
345 if (list_empty(&ctx->query_head))
346 list_add_tail(&ctx->query_head,
347 &sw_context->query_list);
348 ret = vmw_bo_to_validate_list(sw_context,
349 dev_priv->dummy_query_bo,
350 DRM_VMW_FENCE_FLAG_EXEC,
351 NULL);
352 if (unlikely(ret != 0))
353 return ret;
354 }
355 return 0;
356}
357
358
359/**
360 * vmw_query_bo_switch_commit - Finalize switching pinned query buffer
361 *
362 * @dev_priv: The device private structure.
363 * @sw_context: The software context used for this command submission batch.
364 *
365 * This function will check if we're switching query buffers, and will then,
366 * if no other query waits are issued this command submission batch,
367 * issue a dummy occlusion query wait used as a query barrier. When the fence
368 * object following that query wait has signaled, we are sure that all
369 * preseding queries have finished, and the old query buffer can be unpinned.
370 * However, since both the new query buffer and the old one are fenced with
371 * that fence, we can do an asynchronus unpin now, and be sure that the
372 * old query buffer won't be moved until the fence has signaled.
373 *
374 * As mentioned above, both the new - and old query buffers need to be fenced
375 * using a sequence emitted *after* calling this function.
376 */
377static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv,
378 struct vmw_sw_context *sw_context)
379{
380
381 struct vmw_resource *ctx, *next_ctx;
382 int ret;
383
384 /*
385 * The validate list should still hold references to all
386 * contexts here.
387 */
388
389 list_for_each_entry_safe(ctx, next_ctx, &sw_context->query_list,
390 query_head) {
391 list_del_init(&ctx->query_head);
392
f18c8840 393 BUG_ON(list_empty(&ctx->validate_head));
e2fa3a76
TH
394
395 ret = vmw_fifo_emit_dummy_query(dev_priv, ctx->id);
396
397 if (unlikely(ret != 0))
398 DRM_ERROR("Out of fifo space for dummy query.\n");
399 }
400
401 if (dev_priv->pinned_bo != sw_context->cur_query_bo) {
402 if (dev_priv->pinned_bo) {
403 vmw_bo_pin(dev_priv->pinned_bo, false);
404 ttm_bo_unref(&dev_priv->pinned_bo);
405 }
406
407 vmw_bo_pin(sw_context->cur_query_bo, true);
408
409 /*
410 * We pin also the dummy_query_bo buffer so that we
411 * don't need to validate it when emitting
412 * dummy queries in context destroy paths.
413 */
414
415 vmw_bo_pin(dev_priv->dummy_query_bo, true);
416 dev_priv->dummy_query_bo_pinned = true;
417
418 dev_priv->query_cid = sw_context->cur_query_cid;
419 dev_priv->pinned_bo =
420 ttm_bo_reference(sw_context->cur_query_bo);
421 }
422}
423
424/**
425 * vmw_query_switch_backoff - clear query barrier list
426 * @sw_context: The sw context used for this submission batch.
427 *
428 * This function is used as part of an error path, where a previously
429 * set up list of query barriers needs to be cleared.
430 *
431 */
432static void vmw_query_switch_backoff(struct vmw_sw_context *sw_context)
433{
434 struct list_head *list, *next;
435
436 list_for_each_safe(list, next, &sw_context->query_list) {
437 list_del_init(list);
438 }
439}
440
4e4ddd47
TH
441static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
442 struct vmw_sw_context *sw_context,
443 SVGAGuestPtr *ptr,
444 struct vmw_dma_buffer **vmw_bo_p)
fb1d9738 445{
fb1d9738
JB
446 struct vmw_dma_buffer *vmw_bo = NULL;
447 struct ttm_buffer_object *bo;
4e4ddd47 448 uint32_t handle = ptr->gmrId;
fb1d9738 449 struct vmw_relocation *reloc;
4e4ddd47 450 int ret;
fb1d9738 451
fb1d9738
JB
452 ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo);
453 if (unlikely(ret != 0)) {
454 DRM_ERROR("Could not find or use GMR region.\n");
455 return -EINVAL;
456 }
457 bo = &vmw_bo->base;
458
459 if (unlikely(sw_context->cur_reloc >= VMWGFX_MAX_RELOCATIONS)) {
4e4ddd47 460 DRM_ERROR("Max number relocations per submission"
fb1d9738
JB
461 " exceeded\n");
462 ret = -EINVAL;
463 goto out_no_reloc;
464 }
465
466 reloc = &sw_context->relocs[sw_context->cur_reloc++];
4e4ddd47 467 reloc->location = ptr;
fb1d9738 468
e2fa3a76
TH
469 ret = vmw_bo_to_validate_list(sw_context, bo, DRM_VMW_FENCE_FLAG_EXEC,
470 &reloc->index);
471 if (unlikely(ret != 0))
fb1d9738 472 goto out_no_reloc;
fb1d9738 473
4e4ddd47
TH
474 *vmw_bo_p = vmw_bo;
475 return 0;
476
477out_no_reloc:
478 vmw_dmabuf_unreference(&vmw_bo);
479 vmw_bo_p = NULL;
480 return ret;
481}
482
483static int vmw_cmd_end_query(struct vmw_private *dev_priv,
484 struct vmw_sw_context *sw_context,
485 SVGA3dCmdHeader *header)
486{
487 struct vmw_dma_buffer *vmw_bo;
488 struct vmw_query_cmd {
489 SVGA3dCmdHeader header;
490 SVGA3dCmdEndQuery q;
491 } *cmd;
492 int ret;
493
494 cmd = container_of(header, struct vmw_query_cmd, header);
495 ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
496 if (unlikely(ret != 0))
497 return ret;
498
499 ret = vmw_translate_guest_ptr(dev_priv, sw_context,
500 &cmd->q.guestResult,
501 &vmw_bo);
502 if (unlikely(ret != 0))
503 return ret;
504
e2fa3a76
TH
505 ret = vmw_query_bo_switch_prepare(dev_priv, cmd->q.cid,
506 &vmw_bo->base, sw_context);
507
4e4ddd47 508 vmw_dmabuf_unreference(&vmw_bo);
e2fa3a76 509 return ret;
4e4ddd47 510}
fb1d9738 511
4e4ddd47
TH
512static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
513 struct vmw_sw_context *sw_context,
514 SVGA3dCmdHeader *header)
515{
516 struct vmw_dma_buffer *vmw_bo;
517 struct vmw_query_cmd {
518 SVGA3dCmdHeader header;
519 SVGA3dCmdWaitForQuery q;
520 } *cmd;
521 int ret;
e2fa3a76 522 struct vmw_resource *ctx;
4e4ddd47
TH
523
524 cmd = container_of(header, struct vmw_query_cmd, header);
525 ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
526 if (unlikely(ret != 0))
527 return ret;
528
529 ret = vmw_translate_guest_ptr(dev_priv, sw_context,
530 &cmd->q.guestResult,
531 &vmw_bo);
532 if (unlikely(ret != 0))
533 return ret;
534
535 vmw_dmabuf_unreference(&vmw_bo);
e2fa3a76
TH
536
537 /*
538 * This wait will act as a barrier for previous waits for this
539 * context.
540 */
541
542 ctx = sw_context->cur_ctx;
543 if (!list_empty(&ctx->query_head))
544 list_del_init(&ctx->query_head);
545
4e4ddd47
TH
546 return 0;
547}
548
4e4ddd47
TH
549static int vmw_cmd_dma(struct vmw_private *dev_priv,
550 struct vmw_sw_context *sw_context,
551 SVGA3dCmdHeader *header)
552{
553 struct vmw_dma_buffer *vmw_bo = NULL;
554 struct ttm_buffer_object *bo;
555 struct vmw_surface *srf = NULL;
556 struct vmw_dma_cmd {
557 SVGA3dCmdHeader header;
558 SVGA3dCmdSurfaceDMA dma;
559 } *cmd;
560 int ret;
be38ab6e 561 struct vmw_resource *res;
4e4ddd47
TH
562
563 cmd = container_of(header, struct vmw_dma_cmd, header);
564 ret = vmw_translate_guest_ptr(dev_priv, sw_context,
565 &cmd->dma.guest.ptr,
566 &vmw_bo);
567 if (unlikely(ret != 0))
568 return ret;
569
570 bo = &vmw_bo->base;
7a73ba74
TH
571 ret = vmw_user_surface_lookup_handle(dev_priv, sw_context->tfile,
572 cmd->dma.host.sid, &srf);
fb1d9738
JB
573 if (ret) {
574 DRM_ERROR("could not find surface\n");
575 goto out_no_reloc;
576 }
577
5bb39e81
TH
578 ret = vmw_surface_validate(dev_priv, srf);
579 if (unlikely(ret != 0)) {
580 if (ret != -ERESTARTSYS)
581 DRM_ERROR("Culd not validate surface.\n");
582 goto out_no_validate;
583 }
584
be38ab6e 585 /*
7a73ba74
TH
586 * Patch command stream with device SID.
587 */
7a73ba74 588 cmd->dma.host.sid = srf->res.id;
fb1d9738 589 vmw_kms_cursor_snoop(srf, sw_context->tfile, bo, header);
be38ab6e
TH
590
591 vmw_dmabuf_unreference(&vmw_bo);
592
593 res = &srf->res;
f18c8840
TH
594 vmw_resource_to_validate_list(sw_context, &res);
595
596 return 0;
fb1d9738 597
5bb39e81
TH
598out_no_validate:
599 vmw_surface_unreference(&srf);
fb1d9738
JB
600out_no_reloc:
601 vmw_dmabuf_unreference(&vmw_bo);
602 return ret;
603}
604
7a73ba74
TH
605static int vmw_cmd_draw(struct vmw_private *dev_priv,
606 struct vmw_sw_context *sw_context,
607 SVGA3dCmdHeader *header)
608{
609 struct vmw_draw_cmd {
610 SVGA3dCmdHeader header;
611 SVGA3dCmdDrawPrimitives body;
612 } *cmd;
613 SVGA3dVertexDecl *decl = (SVGA3dVertexDecl *)(
614 (unsigned long)header + sizeof(*cmd));
615 SVGA3dPrimitiveRange *range;
616 uint32_t i;
617 uint32_t maxnum;
618 int ret;
619
620 ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
621 if (unlikely(ret != 0))
622 return ret;
623
624 cmd = container_of(header, struct vmw_draw_cmd, header);
625 maxnum = (header->size - sizeof(cmd->body)) / sizeof(*decl);
626
627 if (unlikely(cmd->body.numVertexDecls > maxnum)) {
628 DRM_ERROR("Illegal number of vertex declarations.\n");
629 return -EINVAL;
630 }
631
632 for (i = 0; i < cmd->body.numVertexDecls; ++i, ++decl) {
633 ret = vmw_cmd_sid_check(dev_priv, sw_context,
634 &decl->array.surfaceId);
635 if (unlikely(ret != 0))
636 return ret;
637 }
638
639 maxnum = (header->size - sizeof(cmd->body) -
640 cmd->body.numVertexDecls * sizeof(*decl)) / sizeof(*range);
641 if (unlikely(cmd->body.numRanges > maxnum)) {
642 DRM_ERROR("Illegal number of index ranges.\n");
643 return -EINVAL;
644 }
645
646 range = (SVGA3dPrimitiveRange *) decl;
647 for (i = 0; i < cmd->body.numRanges; ++i, ++range) {
648 ret = vmw_cmd_sid_check(dev_priv, sw_context,
649 &range->indexArray.surfaceId);
650 if (unlikely(ret != 0))
651 return ret;
652 }
653 return 0;
654}
655
656
657static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
658 struct vmw_sw_context *sw_context,
659 SVGA3dCmdHeader *header)
660{
661 struct vmw_tex_state_cmd {
662 SVGA3dCmdHeader header;
663 SVGA3dCmdSetTextureState state;
664 };
665
666 SVGA3dTextureState *last_state = (SVGA3dTextureState *)
667 ((unsigned long) header + header->size + sizeof(header));
668 SVGA3dTextureState *cur_state = (SVGA3dTextureState *)
669 ((unsigned long) header + sizeof(struct vmw_tex_state_cmd));
670 int ret;
671
672 ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
673 if (unlikely(ret != 0))
674 return ret;
675
676 for (; cur_state < last_state; ++cur_state) {
677 if (likely(cur_state->name != SVGA3D_TS_BIND_TEXTURE))
678 continue;
679
680 ret = vmw_cmd_sid_check(dev_priv, sw_context,
681 &cur_state->value);
682 if (unlikely(ret != 0))
683 return ret;
684 }
685
686 return 0;
687}
688
4084fb89
JB
689static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
690 struct vmw_sw_context *sw_context,
691 void *buf)
692{
693 struct vmw_dma_buffer *vmw_bo;
694 int ret;
695
696 struct {
697 uint32_t header;
698 SVGAFifoCmdDefineGMRFB body;
699 } *cmd = buf;
700
701 ret = vmw_translate_guest_ptr(dev_priv, sw_context,
702 &cmd->body.ptr,
703 &vmw_bo);
704 if (unlikely(ret != 0))
705 return ret;
706
707 vmw_dmabuf_unreference(&vmw_bo);
708
709 return ret;
710}
711
712static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
713 struct vmw_sw_context *sw_context,
714 void *buf, uint32_t *size)
715{
716 uint32_t size_remaining = *size;
4084fb89
JB
717 uint32_t cmd_id;
718
719 cmd_id = le32_to_cpu(((uint32_t *)buf)[0]);
720 switch (cmd_id) {
721 case SVGA_CMD_UPDATE:
722 *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdUpdate);
4084fb89
JB
723 break;
724 case SVGA_CMD_DEFINE_GMRFB:
725 *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdDefineGMRFB);
726 break;
727 case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
728 *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen);
729 break;
730 case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
731 *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen);
732 break;
733 default:
734 DRM_ERROR("Unsupported SVGA command: %u.\n", cmd_id);
735 return -EINVAL;
736 }
737
738 if (*size > size_remaining) {
739 DRM_ERROR("Invalid SVGA command (size mismatch):"
740 " %u.\n", cmd_id);
741 return -EINVAL;
742 }
743
0cff60c6 744 if (unlikely(!sw_context->kernel)) {
4084fb89
JB
745 DRM_ERROR("Kernel only SVGA command: %u.\n", cmd_id);
746 return -EPERM;
747 }
748
749 if (cmd_id == SVGA_CMD_DEFINE_GMRFB)
750 return vmw_cmd_check_define_gmrfb(dev_priv, sw_context, buf);
751
752 return 0;
753}
fb1d9738
JB
754
755typedef int (*vmw_cmd_func) (struct vmw_private *,
756 struct vmw_sw_context *,
757 SVGA3dCmdHeader *);
758
759#define VMW_CMD_DEF(cmd, func) \
760 [cmd - SVGA_3D_CMD_BASE] = func
761
762static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = {
763 VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid),
764 VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid),
765 VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_COPY, &vmw_cmd_surface_copy_check),
766 VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_STRETCHBLT, &vmw_cmd_stretch_blt_check),
767 VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DMA, &vmw_cmd_dma),
768 VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DEFINE, &vmw_cmd_invalid),
769 VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DESTROY, &vmw_cmd_invalid),
770 VMW_CMD_DEF(SVGA_3D_CMD_SETTRANSFORM, &vmw_cmd_cid_check),
771 VMW_CMD_DEF(SVGA_3D_CMD_SETZRANGE, &vmw_cmd_cid_check),
772 VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check),
773 VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERTARGET,
774 &vmw_cmd_set_render_target_check),
7a73ba74 775 VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state),
fb1d9738
JB
776 VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check),
777 VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check),
778 VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check),
779 VMW_CMD_DEF(SVGA_3D_CMD_SETVIEWPORT, &vmw_cmd_cid_check),
780 VMW_CMD_DEF(SVGA_3D_CMD_SETCLIPPLANE, &vmw_cmd_cid_check),
781 VMW_CMD_DEF(SVGA_3D_CMD_CLEAR, &vmw_cmd_cid_check),
782 VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check),
783 VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check),
784 VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check),
785 VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_cid_check),
786 VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check),
7a73ba74 787 VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw),
fb1d9738
JB
788 VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check),
789 VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_cid_check),
4e4ddd47
TH
790 VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query),
791 VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query),
fb1d9738
JB
792 VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok),
793 VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN,
794 &vmw_cmd_blt_surf_screen_check)
795};
796
797static int vmw_cmd_check(struct vmw_private *dev_priv,
798 struct vmw_sw_context *sw_context,
799 void *buf, uint32_t *size)
800{
801 uint32_t cmd_id;
7a73ba74 802 uint32_t size_remaining = *size;
fb1d9738
JB
803 SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf;
804 int ret;
805
4084fb89
JB
806 cmd_id = le32_to_cpu(((uint32_t *)buf)[0]);
807 /* Handle any none 3D commands */
808 if (unlikely(cmd_id < SVGA_CMD_MAX))
809 return vmw_cmd_check_not_3d(dev_priv, sw_context, buf, size);
810
fb1d9738
JB
811
812 cmd_id = le32_to_cpu(header->id);
813 *size = le32_to_cpu(header->size) + sizeof(SVGA3dCmdHeader);
814
815 cmd_id -= SVGA_3D_CMD_BASE;
7a73ba74
TH
816 if (unlikely(*size > size_remaining))
817 goto out_err;
818
fb1d9738
JB
819 if (unlikely(cmd_id >= SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE))
820 goto out_err;
821
822 ret = vmw_cmd_funcs[cmd_id](dev_priv, sw_context, header);
823 if (unlikely(ret != 0))
824 goto out_err;
825
826 return 0;
827out_err:
828 DRM_ERROR("Illegal / Invalid SVGA3D command: %d\n",
829 cmd_id + SVGA_3D_CMD_BASE);
830 return -EINVAL;
831}
832
833static int vmw_cmd_check_all(struct vmw_private *dev_priv,
834 struct vmw_sw_context *sw_context,
922ade0d 835 void *buf,
be38ab6e 836 uint32_t size)
fb1d9738
JB
837{
838 int32_t cur_size = size;
839 int ret;
840
841 while (cur_size > 0) {
7a73ba74 842 size = cur_size;
fb1d9738
JB
843 ret = vmw_cmd_check(dev_priv, sw_context, buf, &size);
844 if (unlikely(ret != 0))
845 return ret;
846 buf = (void *)((unsigned long) buf + size);
847 cur_size -= size;
848 }
849
850 if (unlikely(cur_size != 0)) {
851 DRM_ERROR("Command verifier out of sync.\n");
852 return -EINVAL;
853 }
854
855 return 0;
856}
857
858static void vmw_free_relocations(struct vmw_sw_context *sw_context)
859{
860 sw_context->cur_reloc = 0;
861}
862
863static void vmw_apply_relocations(struct vmw_sw_context *sw_context)
864{
865 uint32_t i;
866 struct vmw_relocation *reloc;
867 struct ttm_validate_buffer *validate;
868 struct ttm_buffer_object *bo;
869
870 for (i = 0; i < sw_context->cur_reloc; ++i) {
871 reloc = &sw_context->relocs[i];
872 validate = &sw_context->val_bufs[reloc->index];
873 bo = validate->bo;
135cba0d
TH
874 if (bo->mem.mem_type == TTM_PL_VRAM) {
875 reloc->location->offset += bo->offset;
876 reloc->location->gmrId = SVGA_GMR_FRAMEBUFFER;
877 } else
878 reloc->location->gmrId = bo->mem.start;
fb1d9738
JB
879 }
880 vmw_free_relocations(sw_context);
881}
882
883static void vmw_clear_validations(struct vmw_sw_context *sw_context)
884{
885 struct ttm_validate_buffer *entry, *next;
f18c8840 886 struct vmw_resource *res, *res_next;
fb1d9738 887
be38ab6e
TH
888 /*
889 * Drop references to DMA buffers held during command submission.
890 */
fb1d9738
JB
891 list_for_each_entry_safe(entry, next, &sw_context->validate_nodes,
892 head) {
893 list_del(&entry->head);
894 vmw_dmabuf_validate_clear(entry->bo);
895 ttm_bo_unref(&entry->bo);
896 sw_context->cur_val_buf--;
897 }
898 BUG_ON(sw_context->cur_val_buf != 0);
be38ab6e
TH
899
900 /*
901 * Drop references to resources held during command submission.
902 */
5bb39e81 903 vmw_resource_unreserve(&sw_context->resource_list);
f18c8840
TH
904 list_for_each_entry_safe(res, res_next, &sw_context->resource_list,
905 validate_head) {
906 list_del_init(&res->validate_head);
907 vmw_resource_unreference(&res);
be38ab6e 908 }
fb1d9738
JB
909}
910
911static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
912 struct ttm_buffer_object *bo)
913{
914 int ret;
915
e2fa3a76
TH
916
917 /*
918 * Don't validate pinned buffers.
919 */
920
921 if (bo == dev_priv->pinned_bo ||
922 (bo == dev_priv->dummy_query_bo &&
923 dev_priv->dummy_query_bo_pinned))
924 return 0;
925
8ba5152a 926 /**
135cba0d
TH
927 * Put BO in VRAM if there is space, otherwise as a GMR.
928 * If there is no space in VRAM and GMR ids are all used up,
929 * start evicting GMRs to make room. If the DMA buffer can't be
930 * used as a GMR, this will return -ENOMEM.
8ba5152a
TH
931 */
932
135cba0d 933 ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, true, false, false);
3d3a5b32 934 if (likely(ret == 0 || ret == -ERESTARTSYS))
fb1d9738
JB
935 return ret;
936
8ba5152a
TH
937 /**
938 * If that failed, try VRAM again, this time evicting
939 * previous contents.
940 */
fb1d9738 941
135cba0d 942 DRM_INFO("Falling through to VRAM.\n");
9d87fa21 943 ret = ttm_bo_validate(bo, &vmw_vram_placement, true, false, false);
fb1d9738
JB
944 return ret;
945}
946
947
948static int vmw_validate_buffers(struct vmw_private *dev_priv,
949 struct vmw_sw_context *sw_context)
950{
951 struct ttm_validate_buffer *entry;
952 int ret;
953
954 list_for_each_entry(entry, &sw_context->validate_nodes, head) {
955 ret = vmw_validate_single_buffer(dev_priv, entry->bo);
956 if (unlikely(ret != 0))
957 return ret;
958 }
959 return 0;
960}
961
be38ab6e
TH
962static int vmw_resize_cmd_bounce(struct vmw_sw_context *sw_context,
963 uint32_t size)
964{
965 if (likely(sw_context->cmd_bounce_size >= size))
966 return 0;
967
968 if (sw_context->cmd_bounce_size == 0)
969 sw_context->cmd_bounce_size = VMWGFX_CMD_BOUNCE_INIT_SIZE;
970
971 while (sw_context->cmd_bounce_size < size) {
972 sw_context->cmd_bounce_size =
973 PAGE_ALIGN(sw_context->cmd_bounce_size +
974 (sw_context->cmd_bounce_size >> 1));
975 }
976
977 if (sw_context->cmd_bounce != NULL)
978 vfree(sw_context->cmd_bounce);
979
980 sw_context->cmd_bounce = vmalloc(sw_context->cmd_bounce_size);
981
982 if (sw_context->cmd_bounce == NULL) {
983 DRM_ERROR("Failed to allocate command bounce buffer.\n");
984 sw_context->cmd_bounce_size = 0;
985 return -ENOMEM;
986 }
987
988 return 0;
989}
990
ae2a1040
TH
991/**
992 * vmw_execbuf_fence_commands - create and submit a command stream fence
993 *
994 * Creates a fence object and submits a command stream marker.
995 * If this fails for some reason, We sync the fifo and return NULL.
996 * It is then safe to fence buffers with a NULL pointer.
6070e9fa
JB
997 *
998 * If @p_handle is not NULL @file_priv must also not be NULL. Creates
999 * a userspace handle if @p_handle is not NULL, otherwise not.
ae2a1040
TH
1000 */
1001
1002int vmw_execbuf_fence_commands(struct drm_file *file_priv,
1003 struct vmw_private *dev_priv,
1004 struct vmw_fence_obj **p_fence,
1005 uint32_t *p_handle)
1006{
1007 uint32_t sequence;
1008 int ret;
1009 bool synced = false;
1010
6070e9fa
JB
1011 /* p_handle implies file_priv. */
1012 BUG_ON(p_handle != NULL && file_priv == NULL);
ae2a1040
TH
1013
1014 ret = vmw_fifo_send_fence(dev_priv, &sequence);
1015 if (unlikely(ret != 0)) {
1016 DRM_ERROR("Fence submission error. Syncing.\n");
1017 synced = true;
1018 }
1019
1020 if (p_handle != NULL)
1021 ret = vmw_user_fence_create(file_priv, dev_priv->fman,
1022 sequence,
1023 DRM_VMW_FENCE_FLAG_EXEC,
1024 p_fence, p_handle);
1025 else
1026 ret = vmw_fence_create(dev_priv->fman, sequence,
1027 DRM_VMW_FENCE_FLAG_EXEC,
1028 p_fence);
1029
1030 if (unlikely(ret != 0 && !synced)) {
1031 (void) vmw_fallback_wait(dev_priv, false, false,
1032 sequence, false,
1033 VMW_FENCE_WAIT_TIMEOUT);
1034 *p_fence = NULL;
1035 }
1036
1037 return 0;
1038}
1039
8bf445ce
TH
1040/**
1041 * vmw_execbuf_copy_fence_user - copy fence object information to
1042 * user-space.
1043 *
1044 * @dev_priv: Pointer to a vmw_private struct.
1045 * @vmw_fp: Pointer to the struct vmw_fpriv representing the calling file.
1046 * @ret: Return value from fence object creation.
1047 * @user_fence_rep: User space address of a struct drm_vmw_fence_rep to
1048 * which the information should be copied.
1049 * @fence: Pointer to the fenc object.
1050 * @fence_handle: User-space fence handle.
1051 *
1052 * This function copies fence information to user-space. If copying fails,
1053 * The user-space struct drm_vmw_fence_rep::error member is hopefully
1054 * left untouched, and if it's preloaded with an -EFAULT by user-space,
1055 * the error will hopefully be detected.
1056 * Also if copying fails, user-space will be unable to signal the fence
1057 * object so we wait for it immediately, and then unreference the
1058 * user-space reference.
1059 */
1060static void
1061vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
1062 struct vmw_fpriv *vmw_fp,
1063 int ret,
1064 struct drm_vmw_fence_rep __user *user_fence_rep,
1065 struct vmw_fence_obj *fence,
1066 uint32_t fence_handle)
1067{
1068 struct drm_vmw_fence_rep fence_rep;
1069
1070 if (user_fence_rep == NULL)
1071 return;
1072
1073 fence_rep.error = ret;
1074 if (ret == 0) {
1075 BUG_ON(fence == NULL);
1076
1077 fence_rep.handle = fence_handle;
1078 fence_rep.seqno = fence->seqno;
1079 vmw_update_seqno(dev_priv, &dev_priv->fifo);
1080 fence_rep.passed_seqno = dev_priv->last_read_seqno;
1081 }
1082
1083 /*
1084 * copy_to_user errors will be detected by user space not
1085 * seeing fence_rep::error filled in. Typically
1086 * user-space would have pre-set that member to -EFAULT.
1087 */
1088 ret = copy_to_user(user_fence_rep, &fence_rep,
1089 sizeof(fence_rep));
1090
1091 /*
1092 * User-space lost the fence object. We need to sync
1093 * and unreference the handle.
1094 */
1095 if (unlikely(ret != 0) && (fence_rep.error == 0)) {
1096 ttm_ref_object_base_unref(vmw_fp->tfile,
1097 fence_handle, TTM_REF_USAGE);
1098 DRM_ERROR("Fence copy error. Syncing.\n");
1099 (void) vmw_fence_obj_wait(fence, fence->signal_mask,
1100 false, false,
1101 VMW_FENCE_WAIT_TIMEOUT);
1102 }
1103}
1104
922ade0d
TH
1105int vmw_execbuf_process(struct drm_file *file_priv,
1106 struct vmw_private *dev_priv,
1107 void __user *user_commands,
1108 void *kernel_commands,
1109 uint32_t command_size,
1110 uint64_t throttle_us,
1111 struct drm_vmw_fence_rep __user *user_fence_rep)
fb1d9738 1112{
fb1d9738 1113 struct vmw_sw_context *sw_context = &dev_priv->ctx;
ae2a1040
TH
1114 struct vmw_fence_obj *fence;
1115 uint32_t handle;
922ade0d
TH
1116 void *cmd;
1117 int ret;
fb1d9738 1118
922ade0d 1119 ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
fb1d9738 1120 if (unlikely(ret != 0))
922ade0d 1121 return -ERESTARTSYS;
fb1d9738 1122
922ade0d
TH
1123 if (kernel_commands == NULL) {
1124 sw_context->kernel = false;
fb1d9738 1125
922ade0d
TH
1126 ret = vmw_resize_cmd_bounce(sw_context, command_size);
1127 if (unlikely(ret != 0))
1128 goto out_unlock;
fb1d9738 1129
fb1d9738 1130
922ade0d
TH
1131 ret = copy_from_user(sw_context->cmd_bounce,
1132 user_commands, command_size);
1133
1134 if (unlikely(ret != 0)) {
1135 ret = -EFAULT;
1136 DRM_ERROR("Failed copying commands.\n");
1137 goto out_unlock;
1138 }
1139 kernel_commands = sw_context->cmd_bounce;
1140 } else
1141 sw_context->kernel = true;
fb1d9738
JB
1142
1143 sw_context->tfile = vmw_fpriv(file_priv)->tfile;
1144 sw_context->cid_valid = false;
1145 sw_context->sid_valid = false;
1146 sw_context->cur_reloc = 0;
1147 sw_context->cur_val_buf = 0;
e2fa3a76
TH
1148 sw_context->fence_flags = 0;
1149 INIT_LIST_HEAD(&sw_context->query_list);
f18c8840 1150 INIT_LIST_HEAD(&sw_context->resource_list);
e2fa3a76
TH
1151 sw_context->cur_query_bo = dev_priv->pinned_bo;
1152 sw_context->cur_query_cid = dev_priv->query_cid;
1153 sw_context->query_cid_valid = (dev_priv->pinned_bo != NULL);
fb1d9738
JB
1154
1155 INIT_LIST_HEAD(&sw_context->validate_nodes);
1156
922ade0d
TH
1157 ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands,
1158 command_size);
fb1d9738
JB
1159 if (unlikely(ret != 0))
1160 goto out_err;
be38ab6e 1161
65705962 1162 ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes);
fb1d9738
JB
1163 if (unlikely(ret != 0))
1164 goto out_err;
1165
1166 ret = vmw_validate_buffers(dev_priv, sw_context);
1167 if (unlikely(ret != 0))
1168 goto out_err;
1169
1170 vmw_apply_relocations(sw_context);
1925d456 1171
922ade0d 1172 if (throttle_us) {
6bcd8d3c 1173 ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue,
922ade0d 1174 throttle_us);
1925d456
TH
1175
1176 if (unlikely(ret != 0))
be38ab6e
TH
1177 goto out_throttle;
1178 }
1179
922ade0d 1180 cmd = vmw_fifo_reserve(dev_priv, command_size);
be38ab6e
TH
1181 if (unlikely(cmd == NULL)) {
1182 DRM_ERROR("Failed reserving fifo space for commands.\n");
1183 ret = -ENOMEM;
922ade0d 1184 goto out_throttle;
1925d456
TH
1185 }
1186
922ade0d
TH
1187 memcpy(cmd, kernel_commands, command_size);
1188 vmw_fifo_commit(dev_priv, command_size);
fb1d9738 1189
e2fa3a76 1190 vmw_query_bo_switch_commit(dev_priv, sw_context);
ae2a1040
TH
1191 ret = vmw_execbuf_fence_commands(file_priv, dev_priv,
1192 &fence,
1193 (user_fence_rep) ? &handle : NULL);
fb1d9738
JB
1194 /*
1195 * This error is harmless, because if fence submission fails,
ae2a1040
TH
1196 * vmw_fifo_send_fence will sync. The error will be propagated to
1197 * user-space in @fence_rep
fb1d9738
JB
1198 */
1199
1200 if (ret != 0)
1201 DRM_ERROR("Fence submission error. Syncing.\n");
1202
ae2a1040
TH
1203 ttm_eu_fence_buffer_objects(&sw_context->validate_nodes,
1204 (void *) fence);
fb1d9738 1205
ae2a1040 1206 vmw_clear_validations(sw_context);
8bf445ce
TH
1207 vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
1208 user_fence_rep, fence, handle);
fb1d9738 1209
ae2a1040
TH
1210 if (likely(fence != NULL))
1211 vmw_fence_obj_unreference(&fence);
fb1d9738 1212
922ade0d 1213 mutex_unlock(&dev_priv->cmdbuf_mutex);
fb1d9738 1214 return 0;
922ade0d 1215
fb1d9738
JB
1216out_err:
1217 vmw_free_relocations(sw_context);
be38ab6e 1218out_throttle:
e2fa3a76 1219 vmw_query_switch_backoff(sw_context);
fb1d9738
JB
1220 ttm_eu_backoff_reservation(&sw_context->validate_nodes);
1221 vmw_clear_validations(sw_context);
fb1d9738
JB
1222out_unlock:
1223 mutex_unlock(&dev_priv->cmdbuf_mutex);
922ade0d
TH
1224 return ret;
1225}
1226
e2fa3a76
TH
1227/**
1228 * vmw_execbuf_unpin_panic - Idle the fifo and unpin the query buffer.
1229 *
1230 * @dev_priv: The device private structure.
1231 *
1232 * This function is called to idle the fifo and unpin the query buffer
1233 * if the normal way to do this hits an error, which should typically be
1234 * extremely rare.
1235 */
1236static void vmw_execbuf_unpin_panic(struct vmw_private *dev_priv)
1237{
1238 DRM_ERROR("Can't unpin query buffer. Trying to recover.\n");
1239
1240 (void) vmw_fallback_wait(dev_priv, false, true, 0, false, 10*HZ);
1241 vmw_bo_pin(dev_priv->pinned_bo, false);
1242 vmw_bo_pin(dev_priv->dummy_query_bo, false);
1243 dev_priv->dummy_query_bo_pinned = false;
1244}
1245
1246
1247/**
1248 * vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned
1249 * query bo.
1250 *
1251 * @dev_priv: The device private structure.
1252 * @only_on_cid_match: Only flush and unpin if the current active query cid
1253 * matches @cid.
1254 * @cid: Optional context id to match.
1255 *
1256 * This function should be used to unpin the pinned query bo, or
1257 * as a query barrier when we need to make sure that all queries have
1258 * finished before the next fifo command. (For example on hardware
1259 * context destructions where the hardware may otherwise leak unfinished
1260 * queries).
1261 *
1262 * This function does not return any failure codes, but make attempts
1263 * to do safe unpinning in case of errors.
1264 *
1265 * The function will synchronize on the previous query barrier, and will
1266 * thus not finish until that barrier has executed.
1267 */
1268void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
1269 bool only_on_cid_match, uint32_t cid)
1270{
1271 int ret = 0;
1272 struct list_head validate_list;
1273 struct ttm_validate_buffer pinned_val, query_val;
1274 struct vmw_fence_obj *fence;
1275
1276 mutex_lock(&dev_priv->cmdbuf_mutex);
1277
1278 if (dev_priv->pinned_bo == NULL)
1279 goto out_unlock;
1280
1281 if (only_on_cid_match && cid != dev_priv->query_cid)
1282 goto out_unlock;
1283
1284 INIT_LIST_HEAD(&validate_list);
1285
1286 pinned_val.new_sync_obj_arg = (void *)(unsigned long)
1287 DRM_VMW_FENCE_FLAG_EXEC;
1288 pinned_val.bo = ttm_bo_reference(dev_priv->pinned_bo);
1289 list_add_tail(&pinned_val.head, &validate_list);
1290
1291 query_val.new_sync_obj_arg = pinned_val.new_sync_obj_arg;
1292 query_val.bo = ttm_bo_reference(dev_priv->dummy_query_bo);
1293 list_add_tail(&query_val.head, &validate_list);
1294
1295 do {
1296 ret = ttm_eu_reserve_buffers(&validate_list);
1297 } while (ret == -ERESTARTSYS);
1298
1299 if (unlikely(ret != 0)) {
1300 vmw_execbuf_unpin_panic(dev_priv);
1301 goto out_no_reserve;
1302 }
1303
1304 ret = vmw_fifo_emit_dummy_query(dev_priv, dev_priv->query_cid);
1305 if (unlikely(ret != 0)) {
1306 vmw_execbuf_unpin_panic(dev_priv);
1307 goto out_no_emit;
1308 }
1309
1310 vmw_bo_pin(dev_priv->pinned_bo, false);
1311 vmw_bo_pin(dev_priv->dummy_query_bo, false);
1312 dev_priv->dummy_query_bo_pinned = false;
1313
1314 (void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
1315 ttm_eu_fence_buffer_objects(&validate_list, (void *) fence);
1316
1317 ttm_bo_unref(&query_val.bo);
1318 ttm_bo_unref(&pinned_val.bo);
1319 ttm_bo_unref(&dev_priv->pinned_bo);
1320
1321out_unlock:
1322 mutex_unlock(&dev_priv->cmdbuf_mutex);
1323 return;
1324
1325out_no_emit:
1326 ttm_eu_backoff_reservation(&validate_list);
1327out_no_reserve:
1328 ttm_bo_unref(&query_val.bo);
1329 ttm_bo_unref(&pinned_val.bo);
1330 ttm_bo_unref(&dev_priv->pinned_bo);
1331 mutex_unlock(&dev_priv->cmdbuf_mutex);
1332}
1333
922ade0d
TH
1334
1335int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
1336 struct drm_file *file_priv)
1337{
1338 struct vmw_private *dev_priv = vmw_priv(dev);
1339 struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data;
1340 struct vmw_master *vmaster = vmw_master(file_priv->master);
1341 int ret;
1342
1343 /*
1344 * This will allow us to extend the ioctl argument while
1345 * maintaining backwards compatibility:
1346 * We take different code paths depending on the value of
1347 * arg->version.
1348 */
1349
1350 if (unlikely(arg->version != DRM_VMW_EXECBUF_VERSION)) {
1351 DRM_ERROR("Incorrect execbuf version.\n");
1352 DRM_ERROR("You're running outdated experimental "
1353 "vmwgfx user-space drivers.");
1354 return -EINVAL;
1355 }
1356
1357 ret = ttm_read_lock(&vmaster->lock, true);
1358 if (unlikely(ret != 0))
1359 return ret;
1360
1361 ret = vmw_execbuf_process(file_priv, dev_priv,
1362 (void __user *)(unsigned long)arg->commands,
1363 NULL, arg->command_size, arg->throttle_us,
1364 (void __user *)(unsigned long)arg->fence_rep);
1365
1366 if (unlikely(ret != 0))
1367 goto out_unlock;
1368
1369 vmw_kms_cursor_post_execbuf(dev_priv);
1370
1371out_unlock:
fb1d9738
JB
1372 ttm_read_unlock(&vmaster->lock);
1373 return ret;
1374}