diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 337 |
1 files changed, 296 insertions, 41 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 7a5f1eb55c5a..efb575a7996c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | |||
@@ -114,8 +114,10 @@ static void vmw_resource_list_unreserve(struct list_head *list, | |||
114 | * persistent context binding tracker. | 114 | * persistent context binding tracker. |
115 | */ | 115 | */ |
116 | if (unlikely(val->staged_bindings)) { | 116 | if (unlikely(val->staged_bindings)) { |
117 | vmw_context_binding_state_transfer | 117 | if (!backoff) { |
118 | (val->res, val->staged_bindings); | 118 | vmw_context_binding_state_transfer |
119 | (val->res, val->staged_bindings); | ||
120 | } | ||
119 | kfree(val->staged_bindings); | 121 | kfree(val->staged_bindings); |
120 | val->staged_bindings = NULL; | 122 | val->staged_bindings = NULL; |
121 | } | 123 | } |
@@ -178,6 +180,44 @@ static int vmw_resource_val_add(struct vmw_sw_context *sw_context, | |||
178 | } | 180 | } |
179 | 181 | ||
180 | /** | 182 | /** |
183 | * vmw_resource_context_res_add - Put resources previously bound to a context on | ||
184 | * the validation list | ||
185 | * | ||
186 | * @dev_priv: Pointer to a device private structure | ||
187 | * @sw_context: Pointer to a software context used for this command submission | ||
188 | * @ctx: Pointer to the context resource | ||
189 | * | ||
190 | * This function puts all resources that were previously bound to @ctx on | ||
191 | * the resource validation list. This is part of the context state reemission | ||
192 | */ | ||
193 | static int vmw_resource_context_res_add(struct vmw_private *dev_priv, | ||
194 | struct vmw_sw_context *sw_context, | ||
195 | struct vmw_resource *ctx) | ||
196 | { | ||
197 | struct list_head *binding_list; | ||
198 | struct vmw_ctx_binding *entry; | ||
199 | int ret = 0; | ||
200 | struct vmw_resource *res; | ||
201 | |||
202 | mutex_lock(&dev_priv->binding_mutex); | ||
203 | binding_list = vmw_context_binding_list(ctx); | ||
204 | |||
205 | list_for_each_entry(entry, binding_list, ctx_list) { | ||
206 | res = vmw_resource_reference_unless_doomed(entry->bi.res); | ||
207 | if (unlikely(res == NULL)) | ||
208 | continue; | ||
209 | |||
210 | ret = vmw_resource_val_add(sw_context, entry->bi.res, NULL); | ||
211 | vmw_resource_unreference(&res); | ||
212 | if (unlikely(ret != 0)) | ||
213 | break; | ||
214 | } | ||
215 | |||
216 | mutex_unlock(&dev_priv->binding_mutex); | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | /** | ||
181 | * vmw_resource_relocation_add - Add a relocation to the relocation list | 221 | * vmw_resource_relocation_add - Add a relocation to the relocation list |
182 | * | 222 | * |
183 | * @list: Pointer to head of relocation list. | 223 | * @list: Pointer to head of relocation list. |
@@ -233,8 +273,12 @@ static void vmw_resource_relocations_apply(uint32_t *cb, | |||
233 | { | 273 | { |
234 | struct vmw_resource_relocation *rel; | 274 | struct vmw_resource_relocation *rel; |
235 | 275 | ||
236 | list_for_each_entry(rel, list, head) | 276 | list_for_each_entry(rel, list, head) { |
237 | cb[rel->offset] = rel->res->id; | 277 | if (likely(rel->res != NULL)) |
278 | cb[rel->offset] = rel->res->id; | ||
279 | else | ||
280 | cb[rel->offset] = SVGA_3D_CMD_NOP; | ||
281 | } | ||
238 | } | 282 | } |
239 | 283 | ||
240 | static int vmw_cmd_invalid(struct vmw_private *dev_priv, | 284 | static int vmw_cmd_invalid(struct vmw_private *dev_priv, |
@@ -379,22 +423,27 @@ static int vmw_resources_validate(struct vmw_sw_context *sw_context) | |||
379 | } | 423 | } |
380 | 424 | ||
381 | /** | 425 | /** |
382 | * vmw_cmd_res_check - Check that a resource is present and if so, put it | 426 | * vmw_cmd_compat_res_check - Check that a resource is present and if so, put it |
383 | * on the resource validate list unless it's already there. | 427 | * on the resource validate list unless it's already there. |
384 | * | 428 | * |
385 | * @dev_priv: Pointer to a device private structure. | 429 | * @dev_priv: Pointer to a device private structure. |
386 | * @sw_context: Pointer to the software context. | 430 | * @sw_context: Pointer to the software context. |
387 | * @res_type: Resource type. | 431 | * @res_type: Resource type. |
388 | * @converter: User-space visisble type specific information. | 432 | * @converter: User-space visisble type specific information. |
389 | * @id: Pointer to the location in the command buffer currently being | 433 | * @id: user-space resource id handle. |
434 | * @id_loc: Pointer to the location in the command buffer currently being | ||
390 | * parsed from where the user-space resource id handle is located. | 435 | * parsed from where the user-space resource id handle is located. |
436 | * @p_val: Pointer to pointer to resource validalidation node. Populated | ||
437 | * on exit. | ||
391 | */ | 438 | */ |
392 | static int vmw_cmd_res_check(struct vmw_private *dev_priv, | 439 | static int |
393 | struct vmw_sw_context *sw_context, | 440 | vmw_cmd_compat_res_check(struct vmw_private *dev_priv, |
394 | enum vmw_res_type res_type, | 441 | struct vmw_sw_context *sw_context, |
395 | const struct vmw_user_resource_conv *converter, | 442 | enum vmw_res_type res_type, |
396 | uint32_t *id, | 443 | const struct vmw_user_resource_conv *converter, |
397 | struct vmw_resource_val_node **p_val) | 444 | uint32_t id, |
445 | uint32_t *id_loc, | ||
446 | struct vmw_resource_val_node **p_val) | ||
398 | { | 447 | { |
399 | struct vmw_res_cache_entry *rcache = | 448 | struct vmw_res_cache_entry *rcache = |
400 | &sw_context->res_cache[res_type]; | 449 | &sw_context->res_cache[res_type]; |
@@ -402,7 +451,7 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv, | |||
402 | struct vmw_resource_val_node *node; | 451 | struct vmw_resource_val_node *node; |
403 | int ret; | 452 | int ret; |
404 | 453 | ||
405 | if (*id == SVGA3D_INVALID_ID) { | 454 | if (id == SVGA3D_INVALID_ID) { |
406 | if (p_val) | 455 | if (p_val) |
407 | *p_val = NULL; | 456 | *p_val = NULL; |
408 | if (res_type == vmw_res_context) { | 457 | if (res_type == vmw_res_context) { |
@@ -417,7 +466,7 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv, | |||
417 | * resource | 466 | * resource |
418 | */ | 467 | */ |
419 | 468 | ||
420 | if (likely(rcache->valid && *id == rcache->handle)) { | 469 | if (likely(rcache->valid && id == rcache->handle)) { |
421 | const struct vmw_resource *res = rcache->res; | 470 | const struct vmw_resource *res = rcache->res; |
422 | 471 | ||
423 | rcache->node->first_usage = false; | 472 | rcache->node->first_usage = false; |
@@ -426,28 +475,28 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv, | |||
426 | 475 | ||
427 | return vmw_resource_relocation_add | 476 | return vmw_resource_relocation_add |
428 | (&sw_context->res_relocations, res, | 477 | (&sw_context->res_relocations, res, |
429 | id - sw_context->buf_start); | 478 | id_loc - sw_context->buf_start); |
430 | } | 479 | } |
431 | 480 | ||
432 | ret = vmw_user_resource_lookup_handle(dev_priv, | 481 | ret = vmw_user_resource_lookup_handle(dev_priv, |
433 | sw_context->tfile, | 482 | sw_context->fp->tfile, |
434 | *id, | 483 | id, |
435 | converter, | 484 | converter, |
436 | &res); | 485 | &res); |
437 | if (unlikely(ret != 0)) { | 486 | if (unlikely(ret != 0)) { |
438 | DRM_ERROR("Could not find or use resource 0x%08x.\n", | 487 | DRM_ERROR("Could not find or use resource 0x%08x.\n", |
439 | (unsigned) *id); | 488 | (unsigned) id); |
440 | dump_stack(); | 489 | dump_stack(); |
441 | return ret; | 490 | return ret; |
442 | } | 491 | } |
443 | 492 | ||
444 | rcache->valid = true; | 493 | rcache->valid = true; |
445 | rcache->res = res; | 494 | rcache->res = res; |
446 | rcache->handle = *id; | 495 | rcache->handle = id; |
447 | 496 | ||
448 | ret = vmw_resource_relocation_add(&sw_context->res_relocations, | 497 | ret = vmw_resource_relocation_add(&sw_context->res_relocations, |
449 | res, | 498 | res, |
450 | id - sw_context->buf_start); | 499 | id_loc - sw_context->buf_start); |
451 | if (unlikely(ret != 0)) | 500 | if (unlikely(ret != 0)) |
452 | goto out_no_reloc; | 501 | goto out_no_reloc; |
453 | 502 | ||
@@ -459,7 +508,11 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv, | |||
459 | if (p_val) | 508 | if (p_val) |
460 | *p_val = node; | 509 | *p_val = node; |
461 | 510 | ||
462 | if (node->first_usage && res_type == vmw_res_context) { | 511 | if (dev_priv->has_mob && node->first_usage && |
512 | res_type == vmw_res_context) { | ||
513 | ret = vmw_resource_context_res_add(dev_priv, sw_context, res); | ||
514 | if (unlikely(ret != 0)) | ||
515 | goto out_no_reloc; | ||
463 | node->staged_bindings = | 516 | node->staged_bindings = |
464 | kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL); | 517 | kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL); |
465 | if (node->staged_bindings == NULL) { | 518 | if (node->staged_bindings == NULL) { |
@@ -481,6 +534,59 @@ out_no_reloc: | |||
481 | } | 534 | } |
482 | 535 | ||
483 | /** | 536 | /** |
537 | * vmw_cmd_res_check - Check that a resource is present and if so, put it | ||
538 | * on the resource validate list unless it's already there. | ||
539 | * | ||
540 | * @dev_priv: Pointer to a device private structure. | ||
541 | * @sw_context: Pointer to the software context. | ||
542 | * @res_type: Resource type. | ||
543 | * @converter: User-space visisble type specific information. | ||
544 | * @id_loc: Pointer to the location in the command buffer currently being | ||
545 | * parsed from where the user-space resource id handle is located. | ||
546 | * @p_val: Pointer to pointer to resource validalidation node. Populated | ||
547 | * on exit. | ||
548 | */ | ||
549 | static int | ||
550 | vmw_cmd_res_check(struct vmw_private *dev_priv, | ||
551 | struct vmw_sw_context *sw_context, | ||
552 | enum vmw_res_type res_type, | ||
553 | const struct vmw_user_resource_conv *converter, | ||
554 | uint32_t *id_loc, | ||
555 | struct vmw_resource_val_node **p_val) | ||
556 | { | ||
557 | return vmw_cmd_compat_res_check(dev_priv, sw_context, res_type, | ||
558 | converter, *id_loc, id_loc, p_val); | ||
559 | } | ||
560 | |||
561 | /** | ||
562 | * vmw_rebind_contexts - Rebind all resources previously bound to | ||
563 | * referenced contexts. | ||
564 | * | ||
565 | * @sw_context: Pointer to the software context. | ||
566 | * | ||
567 | * Rebind context binding points that have been scrubbed because of eviction. | ||
568 | */ | ||
569 | static int vmw_rebind_contexts(struct vmw_sw_context *sw_context) | ||
570 | { | ||
571 | struct vmw_resource_val_node *val; | ||
572 | int ret; | ||
573 | |||
574 | list_for_each_entry(val, &sw_context->resource_list, head) { | ||
575 | if (likely(!val->staged_bindings)) | ||
576 | continue; | ||
577 | |||
578 | ret = vmw_context_rebind_all(val->res); | ||
579 | if (unlikely(ret != 0)) { | ||
580 | if (ret != -ERESTARTSYS) | ||
581 | DRM_ERROR("Failed to rebind context.\n"); | ||
582 | return ret; | ||
583 | } | ||
584 | } | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | /** | ||
484 | * vmw_cmd_cid_check - Check a command header for valid context information. | 590 | * vmw_cmd_cid_check - Check a command header for valid context information. |
485 | * | 591 | * |
486 | * @dev_priv: Pointer to a device private structure. | 592 | * @dev_priv: Pointer to a device private structure. |
@@ -496,7 +602,7 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv, | |||
496 | { | 602 | { |
497 | struct vmw_cid_cmd { | 603 | struct vmw_cid_cmd { |
498 | SVGA3dCmdHeader header; | 604 | SVGA3dCmdHeader header; |
499 | __le32 cid; | 605 | uint32_t cid; |
500 | } *cmd; | 606 | } *cmd; |
501 | 607 | ||
502 | cmd = container_of(header, struct vmw_cid_cmd, header); | 608 | cmd = container_of(header, struct vmw_cid_cmd, header); |
@@ -767,7 +873,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, | |||
767 | struct vmw_relocation *reloc; | 873 | struct vmw_relocation *reloc; |
768 | int ret; | 874 | int ret; |
769 | 875 | ||
770 | ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo); | 876 | ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo); |
771 | if (unlikely(ret != 0)) { | 877 | if (unlikely(ret != 0)) { |
772 | DRM_ERROR("Could not find or use MOB buffer.\n"); | 878 | DRM_ERROR("Could not find or use MOB buffer.\n"); |
773 | return -EINVAL; | 879 | return -EINVAL; |
@@ -828,7 +934,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, | |||
828 | struct vmw_relocation *reloc; | 934 | struct vmw_relocation *reloc; |
829 | int ret; | 935 | int ret; |
830 | 936 | ||
831 | ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo); | 937 | ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo); |
832 | if (unlikely(ret != 0)) { | 938 | if (unlikely(ret != 0)) { |
833 | DRM_ERROR("Could not find or use GMR region.\n"); | 939 | DRM_ERROR("Could not find or use GMR region.\n"); |
834 | return -EINVAL; | 940 | return -EINVAL; |
@@ -1127,7 +1233,8 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, | |||
1127 | 1233 | ||
1128 | srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res); | 1234 | srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res); |
1129 | 1235 | ||
1130 | vmw_kms_cursor_snoop(srf, sw_context->tfile, &vmw_bo->base, header); | 1236 | vmw_kms_cursor_snoop(srf, sw_context->fp->tfile, &vmw_bo->base, |
1237 | header); | ||
1131 | 1238 | ||
1132 | out_no_surface: | 1239 | out_no_surface: |
1133 | vmw_dmabuf_unreference(&vmw_bo); | 1240 | vmw_dmabuf_unreference(&vmw_bo); |
@@ -1478,6 +1585,98 @@ static int vmw_cmd_invalidate_gb_surface(struct vmw_private *dev_priv, | |||
1478 | &cmd->body.sid, NULL); | 1585 | &cmd->body.sid, NULL); |
1479 | } | 1586 | } |
1480 | 1587 | ||
1588 | |||
1589 | /** | ||
1590 | * vmw_cmd_shader_define - Validate an SVGA_3D_CMD_SHADER_DEFINE | ||
1591 | * command | ||
1592 | * | ||
1593 | * @dev_priv: Pointer to a device private struct. | ||
1594 | * @sw_context: The software context being used for this batch. | ||
1595 | * @header: Pointer to the command header in the command stream. | ||
1596 | */ | ||
1597 | static int vmw_cmd_shader_define(struct vmw_private *dev_priv, | ||
1598 | struct vmw_sw_context *sw_context, | ||
1599 | SVGA3dCmdHeader *header) | ||
1600 | { | ||
1601 | struct vmw_shader_define_cmd { | ||
1602 | SVGA3dCmdHeader header; | ||
1603 | SVGA3dCmdDefineShader body; | ||
1604 | } *cmd; | ||
1605 | int ret; | ||
1606 | size_t size; | ||
1607 | |||
1608 | cmd = container_of(header, struct vmw_shader_define_cmd, | ||
1609 | header); | ||
1610 | |||
1611 | ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, | ||
1612 | user_context_converter, &cmd->body.cid, | ||
1613 | NULL); | ||
1614 | if (unlikely(ret != 0)) | ||
1615 | return ret; | ||
1616 | |||
1617 | if (unlikely(!dev_priv->has_mob)) | ||
1618 | return 0; | ||
1619 | |||
1620 | size = cmd->header.size - sizeof(cmd->body); | ||
1621 | ret = vmw_compat_shader_add(sw_context->fp->shman, | ||
1622 | cmd->body.shid, cmd + 1, | ||
1623 | cmd->body.type, size, | ||
1624 | sw_context->fp->tfile, | ||
1625 | &sw_context->staged_shaders); | ||
1626 | if (unlikely(ret != 0)) | ||
1627 | return ret; | ||
1628 | |||
1629 | return vmw_resource_relocation_add(&sw_context->res_relocations, | ||
1630 | NULL, &cmd->header.id - | ||
1631 | sw_context->buf_start); | ||
1632 | |||
1633 | return 0; | ||
1634 | } | ||
1635 | |||
1636 | /** | ||
1637 | * vmw_cmd_shader_destroy - Validate an SVGA_3D_CMD_SHADER_DESTROY | ||
1638 | * command | ||
1639 | * | ||
1640 | * @dev_priv: Pointer to a device private struct. | ||
1641 | * @sw_context: The software context being used for this batch. | ||
1642 | * @header: Pointer to the command header in the command stream. | ||
1643 | */ | ||
1644 | static int vmw_cmd_shader_destroy(struct vmw_private *dev_priv, | ||
1645 | struct vmw_sw_context *sw_context, | ||
1646 | SVGA3dCmdHeader *header) | ||
1647 | { | ||
1648 | struct vmw_shader_destroy_cmd { | ||
1649 | SVGA3dCmdHeader header; | ||
1650 | SVGA3dCmdDestroyShader body; | ||
1651 | } *cmd; | ||
1652 | int ret; | ||
1653 | |||
1654 | cmd = container_of(header, struct vmw_shader_destroy_cmd, | ||
1655 | header); | ||
1656 | |||
1657 | ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, | ||
1658 | user_context_converter, &cmd->body.cid, | ||
1659 | NULL); | ||
1660 | if (unlikely(ret != 0)) | ||
1661 | return ret; | ||
1662 | |||
1663 | if (unlikely(!dev_priv->has_mob)) | ||
1664 | return 0; | ||
1665 | |||
1666 | ret = vmw_compat_shader_remove(sw_context->fp->shman, | ||
1667 | cmd->body.shid, | ||
1668 | cmd->body.type, | ||
1669 | &sw_context->staged_shaders); | ||
1670 | if (unlikely(ret != 0)) | ||
1671 | return ret; | ||
1672 | |||
1673 | return vmw_resource_relocation_add(&sw_context->res_relocations, | ||
1674 | NULL, &cmd->header.id - | ||
1675 | sw_context->buf_start); | ||
1676 | |||
1677 | return 0; | ||
1678 | } | ||
1679 | |||
1481 | /** | 1680 | /** |
1482 | * vmw_cmd_set_shader - Validate an SVGA_3D_CMD_SET_SHADER | 1681 | * vmw_cmd_set_shader - Validate an SVGA_3D_CMD_SET_SHADER |
1483 | * command | 1682 | * command |
@@ -1509,10 +1708,18 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv, | |||
1509 | if (dev_priv->has_mob) { | 1708 | if (dev_priv->has_mob) { |
1510 | struct vmw_ctx_bindinfo bi; | 1709 | struct vmw_ctx_bindinfo bi; |
1511 | struct vmw_resource_val_node *res_node; | 1710 | struct vmw_resource_val_node *res_node; |
1512 | 1711 | u32 shid = cmd->body.shid; | |
1513 | ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_shader, | 1712 | |
1514 | user_shader_converter, | 1713 | if (shid != SVGA3D_INVALID_ID) |
1515 | &cmd->body.shid, &res_node); | 1714 | (void) vmw_compat_shader_lookup(sw_context->fp->shman, |
1715 | cmd->body.type, | ||
1716 | &shid); | ||
1717 | |||
1718 | ret = vmw_cmd_compat_res_check(dev_priv, sw_context, | ||
1719 | vmw_res_shader, | ||
1720 | user_shader_converter, | ||
1721 | shid, | ||
1722 | &cmd->body.shid, &res_node); | ||
1516 | if (unlikely(ret != 0)) | 1723 | if (unlikely(ret != 0)) |
1517 | return ret; | 1724 | return ret; |
1518 | 1725 | ||
@@ -1527,6 +1734,39 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv, | |||
1527 | } | 1734 | } |
1528 | 1735 | ||
1529 | /** | 1736 | /** |
1737 | * vmw_cmd_set_shader_const - Validate an SVGA_3D_CMD_SET_SHADER_CONST | ||
1738 | * command | ||
1739 | * | ||
1740 | * @dev_priv: Pointer to a device private struct. | ||
1741 | * @sw_context: The software context being used for this batch. | ||
1742 | * @header: Pointer to the command header in the command stream. | ||
1743 | */ | ||
1744 | static int vmw_cmd_set_shader_const(struct vmw_private *dev_priv, | ||
1745 | struct vmw_sw_context *sw_context, | ||
1746 | SVGA3dCmdHeader *header) | ||
1747 | { | ||
1748 | struct vmw_set_shader_const_cmd { | ||
1749 | SVGA3dCmdHeader header; | ||
1750 | SVGA3dCmdSetShaderConst body; | ||
1751 | } *cmd; | ||
1752 | int ret; | ||
1753 | |||
1754 | cmd = container_of(header, struct vmw_set_shader_const_cmd, | ||
1755 | header); | ||
1756 | |||
1757 | ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, | ||
1758 | user_context_converter, &cmd->body.cid, | ||
1759 | NULL); | ||
1760 | if (unlikely(ret != 0)) | ||
1761 | return ret; | ||
1762 | |||
1763 | if (dev_priv->has_mob) | ||
1764 | header->id = SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE; | ||
1765 | |||
1766 | return 0; | ||
1767 | } | ||
1768 | |||
1769 | /** | ||
1530 | * vmw_cmd_bind_gb_shader - Validate an SVGA_3D_CMD_BIND_GB_SHADER | 1770 | * vmw_cmd_bind_gb_shader - Validate an SVGA_3D_CMD_BIND_GB_SHADER |
1531 | * command | 1771 | * command |
1532 | * | 1772 | * |
@@ -1595,7 +1835,7 @@ static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv, | |||
1595 | return 0; | 1835 | return 0; |
1596 | } | 1836 | } |
1597 | 1837 | ||
1598 | static const struct vmw_cmd_entry const vmw_cmd_entries[SVGA_3D_CMD_MAX] = { | 1838 | static const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = { |
1599 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid, | 1839 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid, |
1600 | false, false, false), | 1840 | false, false, false), |
1601 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid, | 1841 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid, |
@@ -1634,14 +1874,14 @@ static const struct vmw_cmd_entry const vmw_cmd_entries[SVGA_3D_CMD_MAX] = { | |||
1634 | true, false, false), | 1874 | true, false, false), |
1635 | VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check, | 1875 | VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check, |
1636 | false, false, false), | 1876 | false, false, false), |
1637 | VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check, | 1877 | VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_shader_define, |
1638 | true, true, false), | 1878 | true, false, false), |
1639 | VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check, | 1879 | VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_shader_destroy, |
1640 | true, true, false), | 1880 | true, false, false), |
1641 | VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader, | 1881 | VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader, |
1642 | true, false, false), | 1882 | true, false, false), |
1643 | VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check, | 1883 | VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_set_shader_const, |
1644 | true, true, false), | 1884 | true, false, false), |
1645 | VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw, | 1885 | VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw, |
1646 | true, false, false), | 1886 | true, false, false), |
1647 | VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check, | 1887 | VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check, |
@@ -1792,6 +2032,9 @@ static int vmw_cmd_check(struct vmw_private *dev_priv, | |||
1792 | goto out_invalid; | 2032 | goto out_invalid; |
1793 | 2033 | ||
1794 | entry = &vmw_cmd_entries[cmd_id]; | 2034 | entry = &vmw_cmd_entries[cmd_id]; |
2035 | if (unlikely(!entry->func)) | ||
2036 | goto out_invalid; | ||
2037 | |||
1795 | if (unlikely(!entry->user_allow && !sw_context->kernel)) | 2038 | if (unlikely(!entry->user_allow && !sw_context->kernel)) |
1796 | goto out_privileged; | 2039 | goto out_privileged; |
1797 | 2040 | ||
@@ -2171,7 +2414,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, | |||
2171 | } else | 2414 | } else |
2172 | sw_context->kernel = true; | 2415 | sw_context->kernel = true; |
2173 | 2416 | ||
2174 | sw_context->tfile = vmw_fpriv(file_priv)->tfile; | 2417 | sw_context->fp = vmw_fpriv(file_priv); |
2175 | sw_context->cur_reloc = 0; | 2418 | sw_context->cur_reloc = 0; |
2176 | sw_context->cur_val_buf = 0; | 2419 | sw_context->cur_val_buf = 0; |
2177 | sw_context->fence_flags = 0; | 2420 | sw_context->fence_flags = 0; |
@@ -2188,16 +2431,17 @@ int vmw_execbuf_process(struct drm_file *file_priv, | |||
2188 | goto out_unlock; | 2431 | goto out_unlock; |
2189 | sw_context->res_ht_initialized = true; | 2432 | sw_context->res_ht_initialized = true; |
2190 | } | 2433 | } |
2434 | INIT_LIST_HEAD(&sw_context->staged_shaders); | ||
2191 | 2435 | ||
2192 | INIT_LIST_HEAD(&resource_list); | 2436 | INIT_LIST_HEAD(&resource_list); |
2193 | ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands, | 2437 | ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands, |
2194 | command_size); | 2438 | command_size); |
2195 | if (unlikely(ret != 0)) | 2439 | if (unlikely(ret != 0)) |
2196 | goto out_err; | 2440 | goto out_err_nores; |
2197 | 2441 | ||
2198 | ret = vmw_resources_reserve(sw_context); | 2442 | ret = vmw_resources_reserve(sw_context); |
2199 | if (unlikely(ret != 0)) | 2443 | if (unlikely(ret != 0)) |
2200 | goto out_err; | 2444 | goto out_err_nores; |
2201 | 2445 | ||
2202 | ret = ttm_eu_reserve_buffers(&ticket, &sw_context->validate_nodes); | 2446 | ret = ttm_eu_reserve_buffers(&ticket, &sw_context->validate_nodes); |
2203 | if (unlikely(ret != 0)) | 2447 | if (unlikely(ret != 0)) |
@@ -2225,6 +2469,12 @@ int vmw_execbuf_process(struct drm_file *file_priv, | |||
2225 | goto out_err; | 2469 | goto out_err; |
2226 | } | 2470 | } |
2227 | 2471 | ||
2472 | if (dev_priv->has_mob) { | ||
2473 | ret = vmw_rebind_contexts(sw_context); | ||
2474 | if (unlikely(ret != 0)) | ||
2475 | goto out_unlock_binding; | ||
2476 | } | ||
2477 | |||
2228 | cmd = vmw_fifo_reserve(dev_priv, command_size); | 2478 | cmd = vmw_fifo_reserve(dev_priv, command_size); |
2229 | if (unlikely(cmd == NULL)) { | 2479 | if (unlikely(cmd == NULL)) { |
2230 | DRM_ERROR("Failed reserving fifo space for commands.\n"); | 2480 | DRM_ERROR("Failed reserving fifo space for commands.\n"); |
@@ -2276,6 +2526,8 @@ int vmw_execbuf_process(struct drm_file *file_priv, | |||
2276 | } | 2526 | } |
2277 | 2527 | ||
2278 | list_splice_init(&sw_context->resource_list, &resource_list); | 2528 | list_splice_init(&sw_context->resource_list, &resource_list); |
2529 | vmw_compat_shaders_commit(sw_context->fp->shman, | ||
2530 | &sw_context->staged_shaders); | ||
2279 | mutex_unlock(&dev_priv->cmdbuf_mutex); | 2531 | mutex_unlock(&dev_priv->cmdbuf_mutex); |
2280 | 2532 | ||
2281 | /* | 2533 | /* |
@@ -2289,10 +2541,11 @@ int vmw_execbuf_process(struct drm_file *file_priv, | |||
2289 | out_unlock_binding: | 2541 | out_unlock_binding: |
2290 | mutex_unlock(&dev_priv->binding_mutex); | 2542 | mutex_unlock(&dev_priv->binding_mutex); |
2291 | out_err: | 2543 | out_err: |
2292 | vmw_resource_relocations_free(&sw_context->res_relocations); | ||
2293 | vmw_free_relocations(sw_context); | ||
2294 | ttm_eu_backoff_reservation(&ticket, &sw_context->validate_nodes); | 2544 | ttm_eu_backoff_reservation(&ticket, &sw_context->validate_nodes); |
2545 | out_err_nores: | ||
2295 | vmw_resource_list_unreserve(&sw_context->resource_list, true); | 2546 | vmw_resource_list_unreserve(&sw_context->resource_list, true); |
2547 | vmw_resource_relocations_free(&sw_context->res_relocations); | ||
2548 | vmw_free_relocations(sw_context); | ||
2296 | vmw_clear_validations(sw_context); | 2549 | vmw_clear_validations(sw_context); |
2297 | if (unlikely(dev_priv->pinned_bo != NULL && | 2550 | if (unlikely(dev_priv->pinned_bo != NULL && |
2298 | !dev_priv->query_cid_valid)) | 2551 | !dev_priv->query_cid_valid)) |
@@ -2301,6 +2554,8 @@ out_unlock: | |||
2301 | list_splice_init(&sw_context->resource_list, &resource_list); | 2554 | list_splice_init(&sw_context->resource_list, &resource_list); |
2302 | error_resource = sw_context->error_resource; | 2555 | error_resource = sw_context->error_resource; |
2303 | sw_context->error_resource = NULL; | 2556 | sw_context->error_resource = NULL; |
2557 | vmw_compat_shaders_revert(sw_context->fp->shman, | ||
2558 | &sw_context->staged_shaders); | ||
2304 | mutex_unlock(&dev_priv->cmdbuf_mutex); | 2559 | mutex_unlock(&dev_priv->cmdbuf_mutex); |
2305 | 2560 | ||
2306 | /* | 2561 | /* |