aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c227
1 files changed, 128 insertions, 99 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 87df0b3674fd..7bfdaa163a33 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -422,28 +422,91 @@ static int vmw_resources_validate(struct vmw_sw_context *sw_context)
422 return 0; 422 return 0;
423} 423}
424 424
425
426/**
427 * vmw_cmd_res_reloc_add - Add a resource to a software context's
428 * relocation- and validation lists.
429 *
430 * @dev_priv: Pointer to a struct vmw_private identifying the device.
431 * @sw_context: Pointer to the software context.
432 * @res_type: Resource type.
433 * @id_loc: Pointer to where the id that needs translation is located.
434 * @res: Valid pointer to a struct vmw_resource.
435 * @p_val: If non null, a pointer to the struct vmw_resource_validate_node
436 * used for this resource is returned here.
437 */
438static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv,
439 struct vmw_sw_context *sw_context,
440 enum vmw_res_type res_type,
441 uint32_t *id_loc,
442 struct vmw_resource *res,
443 struct vmw_resource_val_node **p_val)
444{
445 int ret;
446 struct vmw_resource_val_node *node;
447
448 *p_val = NULL;
449 ret = vmw_resource_relocation_add(&sw_context->res_relocations,
450 res,
451 id_loc - sw_context->buf_start);
452 if (unlikely(ret != 0))
453 goto out_err;
454
455 ret = vmw_resource_val_add(sw_context, res, &node);
456 if (unlikely(ret != 0))
457 goto out_err;
458
459 if (res_type == vmw_res_context && dev_priv->has_mob &&
460 node->first_usage) {
461
462 /*
463 * Put contexts first on the list to be able to exit
464 * list traversal for contexts early.
465 */
466 list_del(&node->head);
467 list_add(&node->head, &sw_context->resource_list);
468
469 ret = vmw_resource_context_res_add(dev_priv, sw_context, res);
470 if (unlikely(ret != 0))
471 goto out_err;
472 node->staged_bindings =
473 kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL);
474 if (node->staged_bindings == NULL) {
475 DRM_ERROR("Failed to allocate context binding "
476 "information.\n");
477 goto out_err;
478 }
479 INIT_LIST_HEAD(&node->staged_bindings->list);
480 }
481
482 if (p_val)
483 *p_val = node;
484
485out_err:
486 return ret;
487}
488
489
425/** 490/**
426 * vmw_cmd_compat_res_check - Check that a resource is present and if so, put it 491 * vmw_cmd_res_check - Check that a resource is present and if so, put it
427 * on the resource validate list unless it's already there. 492 * on the resource validate list unless it's already there.
428 * 493 *
429 * @dev_priv: Pointer to a device private structure. 494 * @dev_priv: Pointer to a device private structure.
430 * @sw_context: Pointer to the software context. 495 * @sw_context: Pointer to the software context.
431 * @res_type: Resource type. 496 * @res_type: Resource type.
432 * @converter: User-space visisble type specific information. 497 * @converter: User-space visisble type specific information.
433 * @id: user-space resource id handle.
434 * @id_loc: Pointer to the location in the command buffer currently being 498 * @id_loc: Pointer to the location in the command buffer currently being
435 * parsed from where the user-space resource id handle is located. 499 * parsed from where the user-space resource id handle is located.
436 * @p_val: Pointer to pointer to resource validalidation node. Populated 500 * @p_val: Pointer to pointer to resource validalidation node. Populated
437 * on exit. 501 * on exit.
438 */ 502 */
439static int 503static int
440vmw_cmd_compat_res_check(struct vmw_private *dev_priv, 504vmw_cmd_res_check(struct vmw_private *dev_priv,
441 struct vmw_sw_context *sw_context, 505 struct vmw_sw_context *sw_context,
442 enum vmw_res_type res_type, 506 enum vmw_res_type res_type,
443 const struct vmw_user_resource_conv *converter, 507 const struct vmw_user_resource_conv *converter,
444 uint32_t id, 508 uint32_t *id_loc,
445 uint32_t *id_loc, 509 struct vmw_resource_val_node **p_val)
446 struct vmw_resource_val_node **p_val)
447{ 510{
448 struct vmw_res_cache_entry *rcache = 511 struct vmw_res_cache_entry *rcache =
449 &sw_context->res_cache[res_type]; 512 &sw_context->res_cache[res_type];
@@ -451,7 +514,7 @@ vmw_cmd_compat_res_check(struct vmw_private *dev_priv,
451 struct vmw_resource_val_node *node; 514 struct vmw_resource_val_node *node;
452 int ret; 515 int ret;
453 516
454 if (id == SVGA3D_INVALID_ID) { 517 if (*id_loc == SVGA3D_INVALID_ID) {
455 if (p_val) 518 if (p_val)
456 *p_val = NULL; 519 *p_val = NULL;
457 if (res_type == vmw_res_context) { 520 if (res_type == vmw_res_context) {
@@ -466,7 +529,7 @@ vmw_cmd_compat_res_check(struct vmw_private *dev_priv,
466 * resource 529 * resource
467 */ 530 */
468 531
469 if (likely(rcache->valid && id == rcache->handle)) { 532 if (likely(rcache->valid && *id_loc == rcache->handle)) {
470 const struct vmw_resource *res = rcache->res; 533 const struct vmw_resource *res = rcache->res;
471 534
472 rcache->node->first_usage = false; 535 rcache->node->first_usage = false;
@@ -480,49 +543,28 @@ vmw_cmd_compat_res_check(struct vmw_private *dev_priv,
480 543
481 ret = vmw_user_resource_lookup_handle(dev_priv, 544 ret = vmw_user_resource_lookup_handle(dev_priv,
482 sw_context->fp->tfile, 545 sw_context->fp->tfile,
483 id, 546 *id_loc,
484 converter, 547 converter,
485 &res); 548 &res);
486 if (unlikely(ret != 0)) { 549 if (unlikely(ret != 0)) {
487 DRM_ERROR("Could not find or use resource 0x%08x.\n", 550 DRM_ERROR("Could not find or use resource 0x%08x.\n",
488 (unsigned) id); 551 (unsigned) *id_loc);
489 dump_stack(); 552 dump_stack();
490 return ret; 553 return ret;
491 } 554 }
492 555
493 rcache->valid = true; 556 rcache->valid = true;
494 rcache->res = res; 557 rcache->res = res;
495 rcache->handle = id; 558 rcache->handle = *id_loc;
496
497 ret = vmw_resource_relocation_add(&sw_context->res_relocations,
498 res,
499 id_loc - sw_context->buf_start);
500 if (unlikely(ret != 0))
501 goto out_no_reloc;
502 559
503 ret = vmw_resource_val_add(sw_context, res, &node); 560 ret = vmw_cmd_res_reloc_add(dev_priv, sw_context, res_type, id_loc,
561 res, &node);
504 if (unlikely(ret != 0)) 562 if (unlikely(ret != 0))
505 goto out_no_reloc; 563 goto out_no_reloc;
506 564
507 rcache->node = node; 565 rcache->node = node;
508 if (p_val) 566 if (p_val)
509 *p_val = node; 567 *p_val = node;
510
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;
516 node->staged_bindings =
517 kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL);
518 if (node->staged_bindings == NULL) {
519 DRM_ERROR("Failed to allocate context binding "
520 "information.\n");
521 goto out_no_reloc;
522 }
523 INIT_LIST_HEAD(&node->staged_bindings->list);
524 }
525
526 vmw_resource_unreference(&res); 568 vmw_resource_unreference(&res);
527 return 0; 569 return 0;
528 570
@@ -534,31 +576,6 @@ out_no_reloc:
534} 576}
535 577
536/** 578/**
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 */
549static int
550vmw_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 579 * vmw_rebind_contexts - Rebind all resources previously bound to
563 * referenced contexts. 580 * referenced contexts.
564 * 581 *
@@ -572,8 +589,8 @@ static int vmw_rebind_contexts(struct vmw_sw_context *sw_context)
572 int ret; 589 int ret;
573 590
574 list_for_each_entry(val, &sw_context->resource_list, head) { 591 list_for_each_entry(val, &sw_context->resource_list, head) {
575 if (likely(!val->staged_bindings)) 592 if (unlikely(!val->staged_bindings))
576 continue; 593 break;
577 594
578 ret = vmw_context_rebind_all(val->res); 595 ret = vmw_context_rebind_all(val->res);
579 if (unlikely(ret != 0)) { 596 if (unlikely(ret != 0)) {
@@ -1626,13 +1643,14 @@ static int vmw_cmd_shader_define(struct vmw_private *dev_priv,
1626 } *cmd; 1643 } *cmd;
1627 int ret; 1644 int ret;
1628 size_t size; 1645 size_t size;
1646 struct vmw_resource_val_node *val;
1629 1647
1630 cmd = container_of(header, struct vmw_shader_define_cmd, 1648 cmd = container_of(header, struct vmw_shader_define_cmd,
1631 header); 1649 header);
1632 1650
1633 ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 1651 ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
1634 user_context_converter, &cmd->body.cid, 1652 user_context_converter, &cmd->body.cid,
1635 NULL); 1653 &val);
1636 if (unlikely(ret != 0)) 1654 if (unlikely(ret != 0))
1637 return ret; 1655 return ret;
1638 1656
@@ -1640,11 +1658,11 @@ static int vmw_cmd_shader_define(struct vmw_private *dev_priv,
1640 return 0; 1658 return 0;
1641 1659
1642 size = cmd->header.size - sizeof(cmd->body); 1660 size = cmd->header.size - sizeof(cmd->body);
1643 ret = vmw_compat_shader_add(sw_context->fp->shman, 1661 ret = vmw_compat_shader_add(dev_priv,
1662 vmw_context_res_man(val->res),
1644 cmd->body.shid, cmd + 1, 1663 cmd->body.shid, cmd + 1,
1645 cmd->body.type, size, 1664 cmd->body.type, size,
1646 sw_context->fp->tfile, 1665 &sw_context->staged_cmd_res);
1647 &sw_context->staged_shaders);
1648 if (unlikely(ret != 0)) 1666 if (unlikely(ret != 0))
1649 return ret; 1667 return ret;
1650 1668
@@ -1672,23 +1690,24 @@ static int vmw_cmd_shader_destroy(struct vmw_private *dev_priv,
1672 SVGA3dCmdDestroyShader body; 1690 SVGA3dCmdDestroyShader body;
1673 } *cmd; 1691 } *cmd;
1674 int ret; 1692 int ret;
1693 struct vmw_resource_val_node *val;
1675 1694
1676 cmd = container_of(header, struct vmw_shader_destroy_cmd, 1695 cmd = container_of(header, struct vmw_shader_destroy_cmd,
1677 header); 1696 header);
1678 1697
1679 ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, 1698 ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
1680 user_context_converter, &cmd->body.cid, 1699 user_context_converter, &cmd->body.cid,
1681 NULL); 1700 &val);
1682 if (unlikely(ret != 0)) 1701 if (unlikely(ret != 0))
1683 return ret; 1702 return ret;
1684 1703
1685 if (unlikely(!dev_priv->has_mob)) 1704 if (unlikely(!dev_priv->has_mob))
1686 return 0; 1705 return 0;
1687 1706
1688 ret = vmw_compat_shader_remove(sw_context->fp->shman, 1707 ret = vmw_compat_shader_remove(vmw_context_res_man(val->res),
1689 cmd->body.shid, 1708 cmd->body.shid,
1690 cmd->body.type, 1709 cmd->body.type,
1691 &sw_context->staged_shaders); 1710 &sw_context->staged_cmd_res);
1692 if (unlikely(ret != 0)) 1711 if (unlikely(ret != 0))
1693 return ret; 1712 return ret;
1694 1713
@@ -1715,7 +1734,9 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
1715 SVGA3dCmdHeader header; 1734 SVGA3dCmdHeader header;
1716 SVGA3dCmdSetShader body; 1735 SVGA3dCmdSetShader body;
1717 } *cmd; 1736 } *cmd;
1718 struct vmw_resource_val_node *ctx_node; 1737 struct vmw_resource_val_node *ctx_node, *res_node = NULL;
1738 struct vmw_ctx_bindinfo bi;
1739 struct vmw_resource *res = NULL;
1719 int ret; 1740 int ret;
1720 1741
1721 cmd = container_of(header, struct vmw_set_shader_cmd, 1742 cmd = container_of(header, struct vmw_set_shader_cmd,
@@ -1727,32 +1748,40 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
1727 if (unlikely(ret != 0)) 1748 if (unlikely(ret != 0))
1728 return ret; 1749 return ret;
1729 1750
1730 if (dev_priv->has_mob) { 1751 if (!dev_priv->has_mob)
1731 struct vmw_ctx_bindinfo bi; 1752 return 0;
1732 struct vmw_resource_val_node *res_node; 1753
1733 u32 shid = cmd->body.shid; 1754 if (cmd->body.shid != SVGA3D_INVALID_ID) {
1734 1755 res = vmw_compat_shader_lookup
1735 if (shid != SVGA3D_INVALID_ID) 1756 (vmw_context_res_man(ctx_node->res),
1736 (void) vmw_compat_shader_lookup(sw_context->fp->shman, 1757 cmd->body.shid,
1737 cmd->body.type, 1758 cmd->body.type);
1738 &shid); 1759
1739 1760 if (!IS_ERR(res)) {
1740 ret = vmw_cmd_compat_res_check(dev_priv, sw_context, 1761 ret = vmw_cmd_res_reloc_add(dev_priv, sw_context,
1741 vmw_res_shader, 1762 vmw_res_shader,
1742 user_shader_converter, 1763 &cmd->body.shid, res,
1743 shid, 1764 &res_node);
1744 &cmd->body.shid, &res_node); 1765 vmw_resource_unreference(&res);
1766 if (unlikely(ret != 0))
1767 return ret;
1768 }
1769 }
1770
1771 if (!res_node) {
1772 ret = vmw_cmd_res_check(dev_priv, sw_context,
1773 vmw_res_shader,
1774 user_shader_converter,
1775 &cmd->body.shid, &res_node);
1745 if (unlikely(ret != 0)) 1776 if (unlikely(ret != 0))
1746 return ret; 1777 return ret;
1747
1748 bi.ctx = ctx_node->res;
1749 bi.res = res_node ? res_node->res : NULL;
1750 bi.bt = vmw_ctx_binding_shader;
1751 bi.i1.shader_type = cmd->body.type;
1752 return vmw_context_binding_add(ctx_node->staged_bindings, &bi);
1753 } 1778 }
1754 1779
1755 return 0; 1780 bi.ctx = ctx_node->res;
1781 bi.res = res_node ? res_node->res : NULL;
1782 bi.bt = vmw_ctx_binding_shader;
1783 bi.i1.shader_type = cmd->body.type;
1784 return vmw_context_binding_add(ctx_node->staged_bindings, &bi);
1756} 1785}
1757 1786
1758/** 1787/**
@@ -2394,6 +2423,8 @@ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
2394 } 2423 }
2395} 2424}
2396 2425
2426
2427
2397int vmw_execbuf_process(struct drm_file *file_priv, 2428int vmw_execbuf_process(struct drm_file *file_priv,
2398 struct vmw_private *dev_priv, 2429 struct vmw_private *dev_priv,
2399 void __user *user_commands, 2430 void __user *user_commands,
@@ -2453,7 +2484,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
2453 goto out_unlock; 2484 goto out_unlock;
2454 sw_context->res_ht_initialized = true; 2485 sw_context->res_ht_initialized = true;
2455 } 2486 }
2456 INIT_LIST_HEAD(&sw_context->staged_shaders); 2487 INIT_LIST_HEAD(&sw_context->staged_cmd_res);
2457 2488
2458 INIT_LIST_HEAD(&resource_list); 2489 INIT_LIST_HEAD(&resource_list);
2459 ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands, 2490 ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands,
@@ -2548,8 +2579,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
2548 } 2579 }
2549 2580
2550 list_splice_init(&sw_context->resource_list, &resource_list); 2581 list_splice_init(&sw_context->resource_list, &resource_list);
2551 vmw_compat_shaders_commit(sw_context->fp->shman, 2582 vmw_cmdbuf_res_commit(&sw_context->staged_cmd_res);
2552 &sw_context->staged_shaders);
2553 mutex_unlock(&dev_priv->cmdbuf_mutex); 2583 mutex_unlock(&dev_priv->cmdbuf_mutex);
2554 2584
2555 /* 2585 /*
@@ -2576,8 +2606,7 @@ out_unlock:
2576 list_splice_init(&sw_context->resource_list, &resource_list); 2606 list_splice_init(&sw_context->resource_list, &resource_list);
2577 error_resource = sw_context->error_resource; 2607 error_resource = sw_context->error_resource;
2578 sw_context->error_resource = NULL; 2608 sw_context->error_resource = NULL;
2579 vmw_compat_shaders_revert(sw_context->fp->shman, 2609 vmw_cmdbuf_res_revert(&sw_context->staged_cmd_res);
2580 &sw_context->staged_shaders);
2581 mutex_unlock(&dev_priv->cmdbuf_mutex); 2610 mutex_unlock(&dev_priv->cmdbuf_mutex);
2582 2611
2583 /* 2612 /*