diff options
author | Dave Airlie <airlied@redhat.com> | 2014-01-19 19:03:27 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-01-19 19:03:27 -0500 |
commit | 9354eafd893f45320a37da360e1728104e49cc2f (patch) | |
tree | 8cd82ac2ff70ea3a9fd97b432f10c880b1d97a4c /drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | |
parent | 53dac830537b51df555ba5e7ebb236705b7eaa7c (diff) | |
parent | 1985f99987ff04e1bb0405101dd8e25cf1b6b037 (diff) |
Merge tag 'vmwgfx-next-2014-01-17' of git://people.freedesktop.org/~thomash/linux into drm-next
Pull request of 2014-01-17
Pull request for 3.14. One not so urgent fix, One huge device update.
The pull request corresponds to the patches sent out on dri-devel, except:
[PATCH 02/33], review tag typo pointed out by Matt Turner.
[PATCH 04/33], dropped. The new surface formats are never used.
The upcoming vmware svga2 hardware version 11 will introduce the concept
of "guest backed objects" or -resources. The device will in principle
get all
of its memory from the guest, which has big advantages from the device
point of view.
This means that vmwgfx contexts, shaders and surfaces need to be backed
by guest memory in the form of buffer objects called MOBs, presumably
short for MemoryOBjects, which are bound to the device in a special way.
This patch series introduces guest backed object support. Some new IOCTLs
are added to allocate these new guest backed object, and to optionally
provide
them with a backing MOB.
There is an update to the gallium driver that comes with this update, and
it will be pushed in the near timeframe presumably to a separate mesa branch
before merged to master.
* tag 'vmwgfx-next-2014-01-17' of git://people.freedesktop.org/~thomash/linux: (33 commits)
drm/vmwgfx: Invalidate surface on non-readback unbind
drm/vmwgfx: Silence the device command verifier
drm/vmwgfx: Implement 64-bit Otable- and MOB binding v2
drm/vmwgfx: Fix surface framebuffer check for guest-backed surfaces
drm/vmwgfx: Update otable definitions
drm/vmwgfx: Use the linux DMA api also for MOBs
drm/vmwgfx: Ditch the vmw_dummy_query_bo_prepare function
drm/vmwgfx: Persistent tracking of context bindings
drm/vmwgfx: Track context bindings and scrub them upon exiting execbuf
drm/vmwgfx: Block the BIND_SHADERCONSTS command
drm/vmwgfx: Add a parameter to get max MOB memory size
drm/vmwgfx: Implement a buffer object synccpu ioctl.
drm/vmwgfx: Make sure that the multisampling is off
drm/vmwgfx: Extend the command verifier to handle guest-backed on / off
drm/vmwgfx: Fix up the vmwgfx_drv.h header for new files
drm/vmwgfx: Enable 3D for new hardware version
drm/vmwgfx: Add new unused (by user-space) commands to the verifier
drm/vmwgfx: Validate guest-backed shader const commands
drm/vmwgfx: Add guest-backed shaders
drm/vmwgfx: Hook up guest-backed surfaces
...
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 872 |
1 files changed, 796 insertions, 76 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 599f6469a1eb..7a5f1eb55c5a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | |||
@@ -54,6 +54,8 @@ struct vmw_resource_relocation { | |||
54 | * @res: Ref-counted pointer to the resource. | 54 | * @res: Ref-counted pointer to the resource. |
55 | * @switch_backup: Boolean whether to switch backup buffer on unreserve. | 55 | * @switch_backup: Boolean whether to switch backup buffer on unreserve. |
56 | * @new_backup: Refcounted pointer to the new backup buffer. | 56 | * @new_backup: Refcounted pointer to the new backup buffer. |
57 | * @staged_bindings: If @res is a context, tracks bindings set up during | ||
58 | * the command batch. Otherwise NULL. | ||
57 | * @new_backup_offset: New backup buffer offset if @new_backup is non-NUll. | 59 | * @new_backup_offset: New backup buffer offset if @new_backup is non-NUll. |
58 | * @first_usage: Set to true the first time the resource is referenced in | 60 | * @first_usage: Set to true the first time the resource is referenced in |
59 | * the command stream. | 61 | * the command stream. |
@@ -65,12 +67,32 @@ struct vmw_resource_val_node { | |||
65 | struct drm_hash_item hash; | 67 | struct drm_hash_item hash; |
66 | struct vmw_resource *res; | 68 | struct vmw_resource *res; |
67 | struct vmw_dma_buffer *new_backup; | 69 | struct vmw_dma_buffer *new_backup; |
70 | struct vmw_ctx_binding_state *staged_bindings; | ||
68 | unsigned long new_backup_offset; | 71 | unsigned long new_backup_offset; |
69 | bool first_usage; | 72 | bool first_usage; |
70 | bool no_buffer_needed; | 73 | bool no_buffer_needed; |
71 | }; | 74 | }; |
72 | 75 | ||
73 | /** | 76 | /** |
77 | * struct vmw_cmd_entry - Describe a command for the verifier | ||
78 | * | ||
79 | * @user_allow: Whether allowed from the execbuf ioctl. | ||
80 | * @gb_disable: Whether disabled if guest-backed objects are available. | ||
81 | * @gb_enable: Whether enabled iff guest-backed objects are available. | ||
82 | */ | ||
83 | struct vmw_cmd_entry { | ||
84 | int (*func) (struct vmw_private *, struct vmw_sw_context *, | ||
85 | SVGA3dCmdHeader *); | ||
86 | bool user_allow; | ||
87 | bool gb_disable; | ||
88 | bool gb_enable; | ||
89 | }; | ||
90 | |||
91 | #define VMW_CMD_DEF(_cmd, _func, _user_allow, _gb_disable, _gb_enable) \ | ||
92 | [(_cmd) - SVGA_3D_CMD_BASE] = {(_func), (_user_allow),\ | ||
93 | (_gb_disable), (_gb_enable)} | ||
94 | |||
95 | /** | ||
74 | * vmw_resource_unreserve - unreserve resources previously reserved for | 96 | * vmw_resource_unreserve - unreserve resources previously reserved for |
75 | * command submission. | 97 | * command submission. |
76 | * | 98 | * |
@@ -87,6 +109,16 @@ static void vmw_resource_list_unreserve(struct list_head *list, | |||
87 | struct vmw_dma_buffer *new_backup = | 109 | struct vmw_dma_buffer *new_backup = |
88 | backoff ? NULL : val->new_backup; | 110 | backoff ? NULL : val->new_backup; |
89 | 111 | ||
112 | /* | ||
113 | * Transfer staged context bindings to the | ||
114 | * persistent context binding tracker. | ||
115 | */ | ||
116 | if (unlikely(val->staged_bindings)) { | ||
117 | vmw_context_binding_state_transfer | ||
118 | (val->res, val->staged_bindings); | ||
119 | kfree(val->staged_bindings); | ||
120 | val->staged_bindings = NULL; | ||
121 | } | ||
90 | vmw_resource_unreserve(res, new_backup, | 122 | vmw_resource_unreserve(res, new_backup, |
91 | val->new_backup_offset); | 123 | val->new_backup_offset); |
92 | vmw_dmabuf_unreference(&val->new_backup); | 124 | vmw_dmabuf_unreference(&val->new_backup); |
@@ -224,6 +256,7 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv, | |||
224 | * | 256 | * |
225 | * @sw_context: The software context used for this command submission batch. | 257 | * @sw_context: The software context used for this command submission batch. |
226 | * @bo: The buffer object to add. | 258 | * @bo: The buffer object to add. |
259 | * @validate_as_mob: Validate this buffer as a MOB. | ||
227 | * @p_val_node: If non-NULL Will be updated with the validate node number | 260 | * @p_val_node: If non-NULL Will be updated with the validate node number |
228 | * on return. | 261 | * on return. |
229 | * | 262 | * |
@@ -232,6 +265,7 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv, | |||
232 | */ | 265 | */ |
233 | static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context, | 266 | static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context, |
234 | struct ttm_buffer_object *bo, | 267 | struct ttm_buffer_object *bo, |
268 | bool validate_as_mob, | ||
235 | uint32_t *p_val_node) | 269 | uint32_t *p_val_node) |
236 | { | 270 | { |
237 | uint32_t val_node; | 271 | uint32_t val_node; |
@@ -244,6 +278,10 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context, | |||
244 | &hash) == 0)) { | 278 | &hash) == 0)) { |
245 | vval_buf = container_of(hash, struct vmw_validate_buffer, | 279 | vval_buf = container_of(hash, struct vmw_validate_buffer, |
246 | hash); | 280 | hash); |
281 | if (unlikely(vval_buf->validate_as_mob != validate_as_mob)) { | ||
282 | DRM_ERROR("Inconsistent buffer usage.\n"); | ||
283 | return -EINVAL; | ||
284 | } | ||
247 | val_buf = &vval_buf->base; | 285 | val_buf = &vval_buf->base; |
248 | val_node = vval_buf - sw_context->val_bufs; | 286 | val_node = vval_buf - sw_context->val_bufs; |
249 | } else { | 287 | } else { |
@@ -266,6 +304,7 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context, | |||
266 | val_buf->bo = ttm_bo_reference(bo); | 304 | val_buf->bo = ttm_bo_reference(bo); |
267 | val_buf->reserved = false; | 305 | val_buf->reserved = false; |
268 | list_add_tail(&val_buf->head, &sw_context->validate_nodes); | 306 | list_add_tail(&val_buf->head, &sw_context->validate_nodes); |
307 | vval_buf->validate_as_mob = validate_as_mob; | ||
269 | } | 308 | } |
270 | 309 | ||
271 | sw_context->fence_flags |= DRM_VMW_FENCE_FLAG_EXEC; | 310 | sw_context->fence_flags |= DRM_VMW_FENCE_FLAG_EXEC; |
@@ -302,7 +341,8 @@ static int vmw_resources_reserve(struct vmw_sw_context *sw_context) | |||
302 | struct ttm_buffer_object *bo = &res->backup->base; | 341 | struct ttm_buffer_object *bo = &res->backup->base; |
303 | 342 | ||
304 | ret = vmw_bo_to_validate_list | 343 | ret = vmw_bo_to_validate_list |
305 | (sw_context, bo, NULL); | 344 | (sw_context, bo, |
345 | vmw_resource_needs_backup(res), NULL); | ||
306 | 346 | ||
307 | if (unlikely(ret != 0)) | 347 | if (unlikely(ret != 0)) |
308 | return ret; | 348 | return ret; |
@@ -362,8 +402,15 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv, | |||
362 | struct vmw_resource_val_node *node; | 402 | struct vmw_resource_val_node *node; |
363 | int ret; | 403 | int ret; |
364 | 404 | ||
365 | if (*id == SVGA3D_INVALID_ID) | 405 | if (*id == SVGA3D_INVALID_ID) { |
406 | if (p_val) | ||
407 | *p_val = NULL; | ||
408 | if (res_type == vmw_res_context) { | ||
409 | DRM_ERROR("Illegal context invalid id.\n"); | ||
410 | return -EINVAL; | ||
411 | } | ||
366 | return 0; | 412 | return 0; |
413 | } | ||
367 | 414 | ||
368 | /* | 415 | /* |
369 | * Fastpath in case of repeated commands referencing the same | 416 | * Fastpath in case of repeated commands referencing the same |
@@ -411,6 +458,18 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv, | |||
411 | rcache->node = node; | 458 | rcache->node = node; |
412 | if (p_val) | 459 | if (p_val) |
413 | *p_val = node; | 460 | *p_val = node; |
461 | |||
462 | if (node->first_usage && res_type == vmw_res_context) { | ||
463 | node->staged_bindings = | ||
464 | kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL); | ||
465 | if (node->staged_bindings == NULL) { | ||
466 | DRM_ERROR("Failed to allocate context binding " | ||
467 | "information.\n"); | ||
468 | goto out_no_reloc; | ||
469 | } | ||
470 | INIT_LIST_HEAD(&node->staged_bindings->list); | ||
471 | } | ||
472 | |||
414 | vmw_resource_unreference(&res); | 473 | vmw_resource_unreference(&res); |
415 | return 0; | 474 | return 0; |
416 | 475 | ||
@@ -453,17 +512,35 @@ static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv, | |||
453 | SVGA3dCmdHeader header; | 512 | SVGA3dCmdHeader header; |
454 | SVGA3dCmdSetRenderTarget body; | 513 | SVGA3dCmdSetRenderTarget body; |
455 | } *cmd; | 514 | } *cmd; |
515 | struct vmw_resource_val_node *ctx_node; | ||
516 | struct vmw_resource_val_node *res_node; | ||
456 | int ret; | 517 | int ret; |
457 | 518 | ||
458 | ret = vmw_cmd_cid_check(dev_priv, sw_context, header); | 519 | cmd = container_of(header, struct vmw_sid_cmd, header); |
520 | |||
521 | ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, | ||
522 | user_context_converter, &cmd->body.cid, | ||
523 | &ctx_node); | ||
459 | if (unlikely(ret != 0)) | 524 | if (unlikely(ret != 0)) |
460 | return ret; | 525 | return ret; |
461 | 526 | ||
462 | cmd = container_of(header, struct vmw_sid_cmd, header); | ||
463 | ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, | 527 | ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, |
464 | user_surface_converter, | 528 | user_surface_converter, |
465 | &cmd->body.target.sid, NULL); | 529 | &cmd->body.target.sid, &res_node); |
466 | return ret; | 530 | if (unlikely(ret != 0)) |
531 | return ret; | ||
532 | |||
533 | if (dev_priv->has_mob) { | ||
534 | struct vmw_ctx_bindinfo bi; | ||
535 | |||
536 | bi.ctx = ctx_node->res; | ||
537 | bi.res = res_node ? res_node->res : NULL; | ||
538 | bi.bt = vmw_ctx_binding_rt; | ||
539 | bi.i1.rt_type = cmd->body.type; | ||
540 | return vmw_context_binding_add(ctx_node->staged_bindings, &bi); | ||
541 | } | ||
542 | |||
543 | return 0; | ||
467 | } | 544 | } |
468 | 545 | ||
469 | static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv, | 546 | static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv, |
@@ -519,11 +596,6 @@ static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv, | |||
519 | 596 | ||
520 | cmd = container_of(header, struct vmw_sid_cmd, header); | 597 | cmd = container_of(header, struct vmw_sid_cmd, header); |
521 | 598 | ||
522 | if (unlikely(!sw_context->kernel)) { | ||
523 | DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id); | ||
524 | return -EPERM; | ||
525 | } | ||
526 | |||
527 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, | 599 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, |
528 | user_surface_converter, | 600 | user_surface_converter, |
529 | &cmd->body.srcImage.sid, NULL); | 601 | &cmd->body.srcImage.sid, NULL); |
@@ -541,11 +613,6 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv, | |||
541 | 613 | ||
542 | cmd = container_of(header, struct vmw_sid_cmd, header); | 614 | cmd = container_of(header, struct vmw_sid_cmd, header); |
543 | 615 | ||
544 | if (unlikely(!sw_context->kernel)) { | ||
545 | DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id); | ||
546 | return -EPERM; | ||
547 | } | ||
548 | |||
549 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, | 616 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, |
550 | user_surface_converter, &cmd->body.sid, | 617 | user_surface_converter, &cmd->body.sid, |
551 | NULL); | 618 | NULL); |
@@ -586,7 +653,7 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, | |||
586 | sw_context->needs_post_query_barrier = true; | 653 | sw_context->needs_post_query_barrier = true; |
587 | ret = vmw_bo_to_validate_list(sw_context, | 654 | ret = vmw_bo_to_validate_list(sw_context, |
588 | sw_context->cur_query_bo, | 655 | sw_context->cur_query_bo, |
589 | NULL); | 656 | dev_priv->has_mob, NULL); |
590 | if (unlikely(ret != 0)) | 657 | if (unlikely(ret != 0)) |
591 | return ret; | 658 | return ret; |
592 | } | 659 | } |
@@ -594,7 +661,7 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, | |||
594 | 661 | ||
595 | ret = vmw_bo_to_validate_list(sw_context, | 662 | ret = vmw_bo_to_validate_list(sw_context, |
596 | dev_priv->dummy_query_bo, | 663 | dev_priv->dummy_query_bo, |
597 | NULL); | 664 | dev_priv->has_mob, NULL); |
598 | if (unlikely(ret != 0)) | 665 | if (unlikely(ret != 0)) |
599 | return ret; | 666 | return ret; |
600 | 667 | ||
@@ -672,6 +739,66 @@ static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv, | |||
672 | } | 739 | } |
673 | 740 | ||
674 | /** | 741 | /** |
742 | * vmw_translate_mob_pointer - Prepare to translate a user-space buffer | ||
743 | * handle to a MOB id. | ||
744 | * | ||
745 | * @dev_priv: Pointer to a device private structure. | ||
746 | * @sw_context: The software context used for this command batch validation. | ||
747 | * @id: Pointer to the user-space handle to be translated. | ||
748 | * @vmw_bo_p: Points to a location that, on successful return will carry | ||
749 | * a reference-counted pointer to the DMA buffer identified by the | ||
750 | * user-space handle in @id. | ||
751 | * | ||
752 | * This function saves information needed to translate a user-space buffer | ||
753 | * handle to a MOB id. The translation does not take place immediately, but | ||
754 | * during a call to vmw_apply_relocations(). This function builds a relocation | ||
755 | * list and a list of buffers to validate. The former needs to be freed using | ||
756 | * either vmw_apply_relocations() or vmw_free_relocations(). The latter | ||
757 | * needs to be freed using vmw_clear_validations. | ||
758 | */ | ||
759 | static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, | ||
760 | struct vmw_sw_context *sw_context, | ||
761 | SVGAMobId *id, | ||
762 | struct vmw_dma_buffer **vmw_bo_p) | ||
763 | { | ||
764 | struct vmw_dma_buffer *vmw_bo = NULL; | ||
765 | struct ttm_buffer_object *bo; | ||
766 | uint32_t handle = *id; | ||
767 | struct vmw_relocation *reloc; | ||
768 | int ret; | ||
769 | |||
770 | ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo); | ||
771 | if (unlikely(ret != 0)) { | ||
772 | DRM_ERROR("Could not find or use MOB buffer.\n"); | ||
773 | return -EINVAL; | ||
774 | } | ||
775 | bo = &vmw_bo->base; | ||
776 | |||
777 | if (unlikely(sw_context->cur_reloc >= VMWGFX_MAX_RELOCATIONS)) { | ||
778 | DRM_ERROR("Max number relocations per submission" | ||
779 | " exceeded\n"); | ||
780 | ret = -EINVAL; | ||
781 | goto out_no_reloc; | ||
782 | } | ||
783 | |||
784 | reloc = &sw_context->relocs[sw_context->cur_reloc++]; | ||
785 | reloc->mob_loc = id; | ||
786 | reloc->location = NULL; | ||
787 | |||
788 | ret = vmw_bo_to_validate_list(sw_context, bo, true, &reloc->index); | ||
789 | if (unlikely(ret != 0)) | ||
790 | goto out_no_reloc; | ||
791 | |||
792 | *vmw_bo_p = vmw_bo; | ||
793 | return 0; | ||
794 | |||
795 | out_no_reloc: | ||
796 | vmw_dmabuf_unreference(&vmw_bo); | ||
797 | vmw_bo_p = NULL; | ||
798 | return ret; | ||
799 | } | ||
800 | |||
801 | /** | ||
675 | * vmw_translate_guest_pointer - Prepare to translate a user-space buffer | 802 | * vmw_translate_guest_pointer - Prepare to translate a user-space buffer |
676 | * handle to a valid SVGAGuestPtr | 803 | * handle to a valid SVGAGuestPtr |
677 | * | 804 | * |
@@ -718,7 +845,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, | |||
718 | reloc = &sw_context->relocs[sw_context->cur_reloc++]; | 845 | reloc = &sw_context->relocs[sw_context->cur_reloc++]; |
719 | reloc->location = ptr; | 846 | reloc->location = ptr; |
720 | 847 | ||
721 | ret = vmw_bo_to_validate_list(sw_context, bo, &reloc->index); | 848 | ret = vmw_bo_to_validate_list(sw_context, bo, false, &reloc->index); |
722 | if (unlikely(ret != 0)) | 849 | if (unlikely(ret != 0)) |
723 | goto out_no_reloc; | 850 | goto out_no_reloc; |
724 | 851 | ||
@@ -732,6 +859,30 @@ out_no_reloc: | |||
732 | } | 859 | } |
733 | 860 | ||
734 | /** | 861 | /** |
862 | * vmw_cmd_begin_gb_query - validate a SVGA_3D_CMD_BEGIN_GB_QUERY command. | ||
863 | * | ||
864 | * @dev_priv: Pointer to a device private struct. | ||
865 | * @sw_context: The software context used for this command submission. | ||
866 | * @header: Pointer to the command header in the command stream. | ||
867 | */ | ||
868 | static int vmw_cmd_begin_gb_query(struct vmw_private *dev_priv, | ||
869 | struct vmw_sw_context *sw_context, | ||
870 | SVGA3dCmdHeader *header) | ||
871 | { | ||
872 | struct vmw_begin_gb_query_cmd { | ||
873 | SVGA3dCmdHeader header; | ||
874 | SVGA3dCmdBeginGBQuery q; | ||
875 | } *cmd; | ||
876 | |||
877 | cmd = container_of(header, struct vmw_begin_gb_query_cmd, | ||
878 | header); | ||
879 | |||
880 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, | ||
881 | user_context_converter, &cmd->q.cid, | ||
882 | NULL); | ||
883 | } | ||
884 | |||
885 | /** | ||
735 | * vmw_cmd_begin_query - validate a SVGA_3D_CMD_BEGIN_QUERY command. | 886 | * vmw_cmd_begin_query - validate a SVGA_3D_CMD_BEGIN_QUERY command. |
736 | * | 887 | * |
737 | * @dev_priv: Pointer to a device private struct. | 888 | * @dev_priv: Pointer to a device private struct. |
@@ -750,12 +901,64 @@ static int vmw_cmd_begin_query(struct vmw_private *dev_priv, | |||
750 | cmd = container_of(header, struct vmw_begin_query_cmd, | 901 | cmd = container_of(header, struct vmw_begin_query_cmd, |
751 | header); | 902 | header); |
752 | 903 | ||
904 | if (unlikely(dev_priv->has_mob)) { | ||
905 | struct { | ||
906 | SVGA3dCmdHeader header; | ||
907 | SVGA3dCmdBeginGBQuery q; | ||
908 | } gb_cmd; | ||
909 | |||
910 | BUG_ON(sizeof(gb_cmd) != sizeof(*cmd)); | ||
911 | |||
912 | gb_cmd.header.id = SVGA_3D_CMD_BEGIN_GB_QUERY; | ||
913 | gb_cmd.header.size = cmd->header.size; | ||
914 | gb_cmd.q.cid = cmd->q.cid; | ||
915 | gb_cmd.q.type = cmd->q.type; | ||
916 | |||
917 | memcpy(cmd, &gb_cmd, sizeof(*cmd)); | ||
918 | return vmw_cmd_begin_gb_query(dev_priv, sw_context, header); | ||
919 | } | ||
920 | |||
753 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, | 921 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, |
754 | user_context_converter, &cmd->q.cid, | 922 | user_context_converter, &cmd->q.cid, |
755 | NULL); | 923 | NULL); |
756 | } | 924 | } |
757 | 925 | ||
758 | /** | 926 | /** |
927 | * vmw_cmd_end_gb_query - validate a SVGA_3D_CMD_END_GB_QUERY command. | ||
928 | * | ||
929 | * @dev_priv: Pointer to a device private struct. | ||
930 | * @sw_context: The software context used for this command submission. | ||
931 | * @header: Pointer to the command header in the command stream. | ||
932 | */ | ||
933 | static int vmw_cmd_end_gb_query(struct vmw_private *dev_priv, | ||
934 | struct vmw_sw_context *sw_context, | ||
935 | SVGA3dCmdHeader *header) | ||
936 | { | ||
937 | struct vmw_dma_buffer *vmw_bo; | ||
938 | struct vmw_query_cmd { | ||
939 | SVGA3dCmdHeader header; | ||
940 | SVGA3dCmdEndGBQuery q; | ||
941 | } *cmd; | ||
942 | int ret; | ||
943 | |||
944 | cmd = container_of(header, struct vmw_query_cmd, header); | ||
945 | ret = vmw_cmd_cid_check(dev_priv, sw_context, header); | ||
946 | if (unlikely(ret != 0)) | ||
947 | return ret; | ||
948 | |||
949 | ret = vmw_translate_mob_ptr(dev_priv, sw_context, | ||
950 | &cmd->q.mobid, | ||
951 | &vmw_bo); | ||
952 | if (unlikely(ret != 0)) | ||
953 | return ret; | ||
954 | |||
955 | ret = vmw_query_bo_switch_prepare(dev_priv, &vmw_bo->base, sw_context); | ||
956 | |||
957 | vmw_dmabuf_unreference(&vmw_bo); | ||
958 | return ret; | ||
959 | } | ||
960 | |||
961 | /** | ||
759 | * vmw_cmd_end_query - validate a SVGA_3D_CMD_END_QUERY command. | 962 | * vmw_cmd_end_query - validate a SVGA_3D_CMD_END_QUERY command. |
760 | * | 963 | * |
761 | * @dev_priv: Pointer to a device private struct. | 964 | * @dev_priv: Pointer to a device private struct. |
@@ -774,6 +977,25 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv, | |||
774 | int ret; | 977 | int ret; |
775 | 978 | ||
776 | cmd = container_of(header, struct vmw_query_cmd, header); | 979 | cmd = container_of(header, struct vmw_query_cmd, header); |
980 | if (dev_priv->has_mob) { | ||
981 | struct { | ||
982 | SVGA3dCmdHeader header; | ||
983 | SVGA3dCmdEndGBQuery q; | ||
984 | } gb_cmd; | ||
985 | |||
986 | BUG_ON(sizeof(gb_cmd) != sizeof(*cmd)); | ||
987 | |||
988 | gb_cmd.header.id = SVGA_3D_CMD_END_GB_QUERY; | ||
989 | gb_cmd.header.size = cmd->header.size; | ||
990 | gb_cmd.q.cid = cmd->q.cid; | ||
991 | gb_cmd.q.type = cmd->q.type; | ||
992 | gb_cmd.q.mobid = cmd->q.guestResult.gmrId; | ||
993 | gb_cmd.q.offset = cmd->q.guestResult.offset; | ||
994 | |||
995 | memcpy(cmd, &gb_cmd, sizeof(*cmd)); | ||
996 | return vmw_cmd_end_gb_query(dev_priv, sw_context, header); | ||
997 | } | ||
998 | |||
777 | ret = vmw_cmd_cid_check(dev_priv, sw_context, header); | 999 | ret = vmw_cmd_cid_check(dev_priv, sw_context, header); |
778 | if (unlikely(ret != 0)) | 1000 | if (unlikely(ret != 0)) |
779 | return ret; | 1001 | return ret; |
@@ -790,7 +1012,40 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv, | |||
790 | return ret; | 1012 | return ret; |
791 | } | 1013 | } |
792 | 1014 | ||
793 | /* | 1015 | /** |
1016 | * vmw_cmd_wait_gb_query - validate a SVGA_3D_CMD_WAIT_GB_QUERY command. | ||
1017 | * | ||
1018 | * @dev_priv: Pointer to a device private struct. | ||
1019 | * @sw_context: The software context used for this command submission. | ||
1020 | * @header: Pointer to the command header in the command stream. | ||
1021 | */ | ||
1022 | static int vmw_cmd_wait_gb_query(struct vmw_private *dev_priv, | ||
1023 | struct vmw_sw_context *sw_context, | ||
1024 | SVGA3dCmdHeader *header) | ||
1025 | { | ||
1026 | struct vmw_dma_buffer *vmw_bo; | ||
1027 | struct vmw_query_cmd { | ||
1028 | SVGA3dCmdHeader header; | ||
1029 | SVGA3dCmdWaitForGBQuery q; | ||
1030 | } *cmd; | ||
1031 | int ret; | ||
1032 | |||
1033 | cmd = container_of(header, struct vmw_query_cmd, header); | ||
1034 | ret = vmw_cmd_cid_check(dev_priv, sw_context, header); | ||
1035 | if (unlikely(ret != 0)) | ||
1036 | return ret; | ||
1037 | |||
1038 | ret = vmw_translate_mob_ptr(dev_priv, sw_context, | ||
1039 | &cmd->q.mobid, | ||
1040 | &vmw_bo); | ||
1041 | if (unlikely(ret != 0)) | ||
1042 | return ret; | ||
1043 | |||
1044 | vmw_dmabuf_unreference(&vmw_bo); | ||
1045 | return 0; | ||
1046 | } | ||
1047 | |||
1048 | /** | ||
794 | * vmw_cmd_wait_query - validate a SVGA_3D_CMD_WAIT_QUERY command. | 1049 | * vmw_cmd_wait_query - validate a SVGA_3D_CMD_WAIT_QUERY command. |
795 | * | 1050 | * |
796 | * @dev_priv: Pointer to a device private struct. | 1051 | * @dev_priv: Pointer to a device private struct. |
@@ -809,6 +1064,25 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv, | |||
809 | int ret; | 1064 | int ret; |
810 | 1065 | ||
811 | cmd = container_of(header, struct vmw_query_cmd, header); | 1066 | cmd = container_of(header, struct vmw_query_cmd, header); |
1067 | if (dev_priv->has_mob) { | ||
1068 | struct { | ||
1069 | SVGA3dCmdHeader header; | ||
1070 | SVGA3dCmdWaitForGBQuery q; | ||
1071 | } gb_cmd; | ||
1072 | |||
1073 | BUG_ON(sizeof(gb_cmd) != sizeof(*cmd)); | ||
1074 | |||
1075 | gb_cmd.header.id = SVGA_3D_CMD_WAIT_FOR_GB_QUERY; | ||
1076 | gb_cmd.header.size = cmd->header.size; | ||
1077 | gb_cmd.q.cid = cmd->q.cid; | ||
1078 | gb_cmd.q.type = cmd->q.type; | ||
1079 | gb_cmd.q.mobid = cmd->q.guestResult.gmrId; | ||
1080 | gb_cmd.q.offset = cmd->q.guestResult.offset; | ||
1081 | |||
1082 | memcpy(cmd, &gb_cmd, sizeof(*cmd)); | ||
1083 | return vmw_cmd_wait_gb_query(dev_priv, sw_context, header); | ||
1084 | } | ||
1085 | |||
812 | ret = vmw_cmd_cid_check(dev_priv, sw_context, header); | 1086 | ret = vmw_cmd_cid_check(dev_priv, sw_context, header); |
813 | if (unlikely(ret != 0)) | 1087 | if (unlikely(ret != 0)) |
814 | return ret; | 1088 | return ret; |
@@ -921,15 +1195,22 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv, | |||
921 | struct vmw_tex_state_cmd { | 1195 | struct vmw_tex_state_cmd { |
922 | SVGA3dCmdHeader header; | 1196 | SVGA3dCmdHeader header; |
923 | SVGA3dCmdSetTextureState state; | 1197 | SVGA3dCmdSetTextureState state; |
924 | }; | 1198 | } *cmd; |
925 | 1199 | ||
926 | SVGA3dTextureState *last_state = (SVGA3dTextureState *) | 1200 | SVGA3dTextureState *last_state = (SVGA3dTextureState *) |
927 | ((unsigned long) header + header->size + sizeof(header)); | 1201 | ((unsigned long) header + header->size + sizeof(header)); |
928 | SVGA3dTextureState *cur_state = (SVGA3dTextureState *) | 1202 | SVGA3dTextureState *cur_state = (SVGA3dTextureState *) |
929 | ((unsigned long) header + sizeof(struct vmw_tex_state_cmd)); | 1203 | ((unsigned long) header + sizeof(struct vmw_tex_state_cmd)); |
1204 | struct vmw_resource_val_node *ctx_node; | ||
1205 | struct vmw_resource_val_node *res_node; | ||
930 | int ret; | 1206 | int ret; |
931 | 1207 | ||
932 | ret = vmw_cmd_cid_check(dev_priv, sw_context, header); | 1208 | cmd = container_of(header, struct vmw_tex_state_cmd, |
1209 | header); | ||
1210 | |||
1211 | ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, | ||
1212 | user_context_converter, &cmd->state.cid, | ||
1213 | &ctx_node); | ||
933 | if (unlikely(ret != 0)) | 1214 | if (unlikely(ret != 0)) |
934 | return ret; | 1215 | return ret; |
935 | 1216 | ||
@@ -939,9 +1220,20 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv, | |||
939 | 1220 | ||
940 | ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, | 1221 | ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, |
941 | user_surface_converter, | 1222 | user_surface_converter, |
942 | &cur_state->value, NULL); | 1223 | &cur_state->value, &res_node); |
943 | if (unlikely(ret != 0)) | 1224 | if (unlikely(ret != 0)) |
944 | return ret; | 1225 | return ret; |
1226 | |||
1227 | if (dev_priv->has_mob) { | ||
1228 | struct vmw_ctx_bindinfo bi; | ||
1229 | |||
1230 | bi.ctx = ctx_node->res; | ||
1231 | bi.res = res_node ? res_node->res : NULL; | ||
1232 | bi.bt = vmw_ctx_binding_tex; | ||
1233 | bi.i1.texture_stage = cur_state->stage; | ||
1234 | vmw_context_binding_add(ctx_node->staged_bindings, | ||
1235 | &bi); | ||
1236 | } | ||
945 | } | 1237 | } |
946 | 1238 | ||
947 | return 0; | 1239 | return 0; |
@@ -971,6 +1263,222 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv, | |||
971 | } | 1263 | } |
972 | 1264 | ||
973 | /** | 1265 | /** |
1266 | * vmw_cmd_switch_backup - Utility function to handle backup buffer switching | ||
1267 | * | ||
1268 | * @dev_priv: Pointer to a device private struct. | ||
1269 | * @sw_context: The software context being used for this batch. | ||
1270 | * @res_type: The resource type. | ||
1271 | * @converter: Information about user-space binding for this resource type. | ||
1272 | * @res_id: Pointer to the user-space resource handle in the command stream. | ||
1273 | * @buf_id: Pointer to the user-space backup buffer handle in the command | ||
1274 | * stream. | ||
1275 | * @backup_offset: Offset of backup into MOB. | ||
1276 | * | ||
1277 | * This function prepares for registering a switch of backup buffers | ||
1278 | * in the resource metadata just prior to unreserving. | ||
1279 | */ | ||
1280 | static int vmw_cmd_switch_backup(struct vmw_private *dev_priv, | ||
1281 | struct vmw_sw_context *sw_context, | ||
1282 | enum vmw_res_type res_type, | ||
1283 | const struct vmw_user_resource_conv | ||
1284 | *converter, | ||
1285 | uint32_t *res_id, | ||
1286 | uint32_t *buf_id, | ||
1287 | unsigned long backup_offset) | ||
1288 | { | ||
1289 | int ret; | ||
1290 | struct vmw_dma_buffer *dma_buf; | ||
1291 | struct vmw_resource_val_node *val_node; | ||
1292 | |||
1293 | ret = vmw_cmd_res_check(dev_priv, sw_context, res_type, | ||
1294 | converter, res_id, &val_node); | ||
1295 | if (unlikely(ret != 0)) | ||
1296 | return ret; | ||
1297 | |||
1298 | ret = vmw_translate_mob_ptr(dev_priv, sw_context, buf_id, &dma_buf); | ||
1299 | if (unlikely(ret != 0)) | ||
1300 | return ret; | ||
1301 | |||
1302 | if (val_node->first_usage) | ||
1303 | val_node->no_buffer_needed = true; | ||
1304 | |||
1305 | vmw_dmabuf_unreference(&val_node->new_backup); | ||
1306 | val_node->new_backup = dma_buf; | ||
1307 | val_node->new_backup_offset = backup_offset; | ||
1308 | |||
1309 | return 0; | ||
1310 | } | ||
1311 | |||
1312 | /** | ||
1313 | * vmw_cmd_bind_gb_surface - Validate an SVGA_3D_CMD_BIND_GB_SURFACE | ||
1314 | * command | ||
1315 | * | ||
1316 | * @dev_priv: Pointer to a device private struct. | ||
1317 | * @sw_context: The software context being used for this batch. | ||
1318 | * @header: Pointer to the command header in the command stream. | ||
1319 | */ | ||
1320 | static int vmw_cmd_bind_gb_surface(struct vmw_private *dev_priv, | ||
1321 | struct vmw_sw_context *sw_context, | ||
1322 | SVGA3dCmdHeader *header) | ||
1323 | { | ||
1324 | struct vmw_bind_gb_surface_cmd { | ||
1325 | SVGA3dCmdHeader header; | ||
1326 | SVGA3dCmdBindGBSurface body; | ||
1327 | } *cmd; | ||
1328 | |||
1329 | cmd = container_of(header, struct vmw_bind_gb_surface_cmd, header); | ||
1330 | |||
1331 | return vmw_cmd_switch_backup(dev_priv, sw_context, vmw_res_surface, | ||
1332 | user_surface_converter, | ||
1333 | &cmd->body.sid, &cmd->body.mobid, | ||
1334 | 0); | ||
1335 | } | ||
1336 | |||
1337 | /** | ||
1338 | * vmw_cmd_update_gb_image - Validate an SVGA_3D_CMD_UPDATE_GB_IMAGE | ||
1339 | * command | ||
1340 | * | ||
1341 | * @dev_priv: Pointer to a device private struct. | ||
1342 | * @sw_context: The software context being used for this batch. | ||
1343 | * @header: Pointer to the command header in the command stream. | ||
1344 | */ | ||
1345 | static int vmw_cmd_update_gb_image(struct vmw_private *dev_priv, | ||
1346 | struct vmw_sw_context *sw_context, | ||
1347 | SVGA3dCmdHeader *header) | ||
1348 | { | ||
1349 | struct vmw_gb_surface_cmd { | ||
1350 | SVGA3dCmdHeader header; | ||
1351 | SVGA3dCmdUpdateGBImage body; | ||
1352 | } *cmd; | ||
1353 | |||
1354 | cmd = container_of(header, struct vmw_gb_surface_cmd, header); | ||
1355 | |||
1356 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, | ||
1357 | user_surface_converter, | ||
1358 | &cmd->body.image.sid, NULL); | ||
1359 | } | ||
1360 | |||
1361 | /** | ||
1362 | * vmw_cmd_update_gb_surface - Validate an SVGA_3D_CMD_UPDATE_GB_SURFACE | ||
1363 | * command | ||
1364 | * | ||
1365 | * @dev_priv: Pointer to a device private struct. | ||
1366 | * @sw_context: The software context being used for this batch. | ||
1367 | * @header: Pointer to the command header in the command stream. | ||
1368 | */ | ||
1369 | static int vmw_cmd_update_gb_surface(struct vmw_private *dev_priv, | ||
1370 | struct vmw_sw_context *sw_context, | ||
1371 | SVGA3dCmdHeader *header) | ||
1372 | { | ||
1373 | struct vmw_gb_surface_cmd { | ||
1374 | SVGA3dCmdHeader header; | ||
1375 | SVGA3dCmdUpdateGBSurface body; | ||
1376 | } *cmd; | ||
1377 | |||
1378 | cmd = container_of(header, struct vmw_gb_surface_cmd, header); | ||
1379 | |||
1380 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, | ||
1381 | user_surface_converter, | ||
1382 | &cmd->body.sid, NULL); | ||
1383 | } | ||
1384 | |||
1385 | /** | ||
1386 | * vmw_cmd_readback_gb_image - Validate an SVGA_3D_CMD_READBACK_GB_IMAGE | ||
1387 | * command | ||
1388 | * | ||
1389 | * @dev_priv: Pointer to a device private struct. | ||
1390 | * @sw_context: The software context being used for this batch. | ||
1391 | * @header: Pointer to the command header in the command stream. | ||
1392 | */ | ||
1393 | static int vmw_cmd_readback_gb_image(struct vmw_private *dev_priv, | ||
1394 | struct vmw_sw_context *sw_context, | ||
1395 | SVGA3dCmdHeader *header) | ||
1396 | { | ||
1397 | struct vmw_gb_surface_cmd { | ||
1398 | SVGA3dCmdHeader header; | ||
1399 | SVGA3dCmdReadbackGBImage body; | ||
1400 | } *cmd; | ||
1401 | |||
1402 | cmd = container_of(header, struct vmw_gb_surface_cmd, header); | ||
1403 | |||
1404 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, | ||
1405 | user_surface_converter, | ||
1406 | &cmd->body.image.sid, NULL); | ||
1407 | } | ||
1408 | |||
1409 | /** | ||
1410 | * vmw_cmd_readback_gb_surface - Validate an SVGA_3D_CMD_READBACK_GB_SURFACE | ||
1411 | * command | ||
1412 | * | ||
1413 | * @dev_priv: Pointer to a device private struct. | ||
1414 | * @sw_context: The software context being used for this batch. | ||
1415 | * @header: Pointer to the command header in the command stream. | ||
1416 | */ | ||
1417 | static int vmw_cmd_readback_gb_surface(struct vmw_private *dev_priv, | ||
1418 | struct vmw_sw_context *sw_context, | ||
1419 | SVGA3dCmdHeader *header) | ||
1420 | { | ||
1421 | struct vmw_gb_surface_cmd { | ||
1422 | SVGA3dCmdHeader header; | ||
1423 | SVGA3dCmdReadbackGBSurface body; | ||
1424 | } *cmd; | ||
1425 | |||
1426 | cmd = container_of(header, struct vmw_gb_surface_cmd, header); | ||
1427 | |||
1428 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, | ||
1429 | user_surface_converter, | ||
1430 | &cmd->body.sid, NULL); | ||
1431 | } | ||
1432 | |||
1433 | /** | ||
1434 | * vmw_cmd_invalidate_gb_image - Validate an SVGA_3D_CMD_INVALIDATE_GB_IMAGE | ||
1435 | * command | ||
1436 | * | ||
1437 | * @dev_priv: Pointer to a device private struct. | ||
1438 | * @sw_context: The software context being used for this batch. | ||
1439 | * @header: Pointer to the command header in the command stream. | ||
1440 | */ | ||
1441 | static int vmw_cmd_invalidate_gb_image(struct vmw_private *dev_priv, | ||
1442 | struct vmw_sw_context *sw_context, | ||
1443 | SVGA3dCmdHeader *header) | ||
1444 | { | ||
1445 | struct vmw_gb_surface_cmd { | ||
1446 | SVGA3dCmdHeader header; | ||
1447 | SVGA3dCmdInvalidateGBImage body; | ||
1448 | } *cmd; | ||
1449 | |||
1450 | cmd = container_of(header, struct vmw_gb_surface_cmd, header); | ||
1451 | |||
1452 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, | ||
1453 | user_surface_converter, | ||
1454 | &cmd->body.image.sid, NULL); | ||
1455 | } | ||
1456 | |||
1457 | /** | ||
1458 | * vmw_cmd_invalidate_gb_surface - Validate an | ||
1459 | * SVGA_3D_CMD_INVALIDATE_GB_SURFACE command | ||
1460 | * | ||
1461 | * @dev_priv: Pointer to a device private struct. | ||
1462 | * @sw_context: The software context being used for this batch. | ||
1463 | * @header: Pointer to the command header in the command stream. | ||
1464 | */ | ||
1465 | static int vmw_cmd_invalidate_gb_surface(struct vmw_private *dev_priv, | ||
1466 | struct vmw_sw_context *sw_context, | ||
1467 | SVGA3dCmdHeader *header) | ||
1468 | { | ||
1469 | struct vmw_gb_surface_cmd { | ||
1470 | SVGA3dCmdHeader header; | ||
1471 | SVGA3dCmdInvalidateGBSurface body; | ||
1472 | } *cmd; | ||
1473 | |||
1474 | cmd = container_of(header, struct vmw_gb_surface_cmd, header); | ||
1475 | |||
1476 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, | ||
1477 | user_surface_converter, | ||
1478 | &cmd->body.sid, NULL); | ||
1479 | } | ||
1480 | |||
1481 | /** | ||
974 | * vmw_cmd_set_shader - Validate an SVGA_3D_CMD_SET_SHADER | 1482 | * vmw_cmd_set_shader - Validate an SVGA_3D_CMD_SET_SHADER |
975 | * command | 1483 | * command |
976 | * | 1484 | * |
@@ -986,18 +1494,64 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv, | |||
986 | SVGA3dCmdHeader header; | 1494 | SVGA3dCmdHeader header; |
987 | SVGA3dCmdSetShader body; | 1495 | SVGA3dCmdSetShader body; |
988 | } *cmd; | 1496 | } *cmd; |
1497 | struct vmw_resource_val_node *ctx_node; | ||
989 | int ret; | 1498 | int ret; |
990 | 1499 | ||
991 | cmd = container_of(header, struct vmw_set_shader_cmd, | 1500 | cmd = container_of(header, struct vmw_set_shader_cmd, |
992 | header); | 1501 | header); |
993 | 1502 | ||
994 | ret = vmw_cmd_cid_check(dev_priv, sw_context, header); | 1503 | ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, |
1504 | user_context_converter, &cmd->body.cid, | ||
1505 | &ctx_node); | ||
995 | if (unlikely(ret != 0)) | 1506 | if (unlikely(ret != 0)) |
996 | return ret; | 1507 | return ret; |
997 | 1508 | ||
1509 | if (dev_priv->has_mob) { | ||
1510 | struct vmw_ctx_bindinfo bi; | ||
1511 | struct vmw_resource_val_node *res_node; | ||
1512 | |||
1513 | ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_shader, | ||
1514 | user_shader_converter, | ||
1515 | &cmd->body.shid, &res_node); | ||
1516 | if (unlikely(ret != 0)) | ||
1517 | return ret; | ||
1518 | |||
1519 | bi.ctx = ctx_node->res; | ||
1520 | bi.res = res_node ? res_node->res : NULL; | ||
1521 | bi.bt = vmw_ctx_binding_shader; | ||
1522 | bi.i1.shader_type = cmd->body.type; | ||
1523 | return vmw_context_binding_add(ctx_node->staged_bindings, &bi); | ||
1524 | } | ||
1525 | |||
998 | return 0; | 1526 | return 0; |
999 | } | 1527 | } |
1000 | 1528 | ||
1529 | /** | ||
1530 | * vmw_cmd_bind_gb_shader - Validate an SVGA_3D_CMD_BIND_GB_SHADER | ||
1531 | * command | ||
1532 | * | ||
1533 | * @dev_priv: Pointer to a device private struct. | ||
1534 | * @sw_context: The software context being used for this batch. | ||
1535 | * @header: Pointer to the command header in the command stream. | ||
1536 | */ | ||
1537 | static int vmw_cmd_bind_gb_shader(struct vmw_private *dev_priv, | ||
1538 | struct vmw_sw_context *sw_context, | ||
1539 | SVGA3dCmdHeader *header) | ||
1540 | { | ||
1541 | struct vmw_bind_gb_shader_cmd { | ||
1542 | SVGA3dCmdHeader header; | ||
1543 | SVGA3dCmdBindGBShader body; | ||
1544 | } *cmd; | ||
1545 | |||
1546 | cmd = container_of(header, struct vmw_bind_gb_shader_cmd, | ||
1547 | header); | ||
1548 | |||
1549 | return vmw_cmd_switch_backup(dev_priv, sw_context, vmw_res_shader, | ||
1550 | user_shader_converter, | ||
1551 | &cmd->body.shid, &cmd->body.mobid, | ||
1552 | cmd->body.offsetInBytes); | ||
1553 | } | ||
1554 | |||
1001 | static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv, | 1555 | static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv, |
1002 | struct vmw_sw_context *sw_context, | 1556 | struct vmw_sw_context *sw_context, |
1003 | void *buf, uint32_t *size) | 1557 | void *buf, uint32_t *size) |
@@ -1041,50 +1595,173 @@ static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv, | |||
1041 | return 0; | 1595 | return 0; |
1042 | } | 1596 | } |
1043 | 1597 | ||
1044 | typedef int (*vmw_cmd_func) (struct vmw_private *, | 1598 | static const struct vmw_cmd_entry const vmw_cmd_entries[SVGA_3D_CMD_MAX] = { |
1045 | struct vmw_sw_context *, | 1599 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid, |
1046 | SVGA3dCmdHeader *); | 1600 | false, false, false), |
1047 | 1601 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid, | |
1048 | #define VMW_CMD_DEF(cmd, func) \ | 1602 | false, false, false), |
1049 | [cmd - SVGA_3D_CMD_BASE] = func | 1603 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_COPY, &vmw_cmd_surface_copy_check, |
1050 | 1604 | true, false, false), | |
1051 | static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = { | 1605 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_STRETCHBLT, &vmw_cmd_stretch_blt_check, |
1052 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid), | 1606 | true, false, false), |
1053 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid), | 1607 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DMA, &vmw_cmd_dma, |
1054 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_COPY, &vmw_cmd_surface_copy_check), | 1608 | true, false, false), |
1055 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_STRETCHBLT, &vmw_cmd_stretch_blt_check), | 1609 | VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DEFINE, &vmw_cmd_invalid, |
1056 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DMA, &vmw_cmd_dma), | 1610 | false, false, false), |
1057 | VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DEFINE, &vmw_cmd_invalid), | 1611 | VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DESTROY, &vmw_cmd_invalid, |
1058 | VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DESTROY, &vmw_cmd_invalid), | 1612 | false, false, false), |
1059 | VMW_CMD_DEF(SVGA_3D_CMD_SETTRANSFORM, &vmw_cmd_cid_check), | 1613 | VMW_CMD_DEF(SVGA_3D_CMD_SETTRANSFORM, &vmw_cmd_cid_check, |
1060 | VMW_CMD_DEF(SVGA_3D_CMD_SETZRANGE, &vmw_cmd_cid_check), | 1614 | true, false, false), |
1061 | VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check), | 1615 | VMW_CMD_DEF(SVGA_3D_CMD_SETZRANGE, &vmw_cmd_cid_check, |
1616 | true, false, false), | ||
1617 | VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check, | ||
1618 | true, false, false), | ||
1062 | VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERTARGET, | 1619 | VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERTARGET, |
1063 | &vmw_cmd_set_render_target_check), | 1620 | &vmw_cmd_set_render_target_check, true, false, false), |
1064 | VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state), | 1621 | VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state, |
1065 | VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check), | 1622 | true, false, false), |
1066 | VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check), | 1623 | VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check, |
1067 | VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check), | 1624 | true, false, false), |
1068 | VMW_CMD_DEF(SVGA_3D_CMD_SETVIEWPORT, &vmw_cmd_cid_check), | 1625 | VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check, |
1069 | VMW_CMD_DEF(SVGA_3D_CMD_SETCLIPPLANE, &vmw_cmd_cid_check), | 1626 | true, false, false), |
1070 | VMW_CMD_DEF(SVGA_3D_CMD_CLEAR, &vmw_cmd_cid_check), | 1627 | VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check, |
1071 | VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check), | 1628 | true, false, false), |
1072 | VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check), | 1629 | VMW_CMD_DEF(SVGA_3D_CMD_SETVIEWPORT, &vmw_cmd_cid_check, |
1073 | VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check), | 1630 | true, false, false), |
1074 | VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader), | 1631 | VMW_CMD_DEF(SVGA_3D_CMD_SETCLIPPLANE, &vmw_cmd_cid_check, |
1075 | VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check), | 1632 | true, false, false), |
1076 | VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw), | 1633 | VMW_CMD_DEF(SVGA_3D_CMD_CLEAR, &vmw_cmd_cid_check, |
1077 | VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check), | 1634 | true, false, false), |
1078 | VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_begin_query), | 1635 | VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check, |
1079 | VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query), | 1636 | false, false, false), |
1080 | VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query), | 1637 | VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check, |
1081 | VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok), | 1638 | true, true, false), |
1639 | VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check, | ||
1640 | true, true, false), | ||
1641 | VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader, | ||
1642 | true, false, false), | ||
1643 | VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check, | ||
1644 | true, true, false), | ||
1645 | VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw, | ||
1646 | true, false, false), | ||
1647 | VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check, | ||
1648 | true, false, false), | ||
1649 | VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_begin_query, | ||
1650 | true, false, false), | ||
1651 | VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query, | ||
1652 | true, false, false), | ||
1653 | VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query, | ||
1654 | true, false, false), | ||
1655 | VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok, | ||
1656 | true, false, false), | ||
1082 | VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN, | 1657 | VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN, |
1083 | &vmw_cmd_blt_surf_screen_check), | 1658 | &vmw_cmd_blt_surf_screen_check, false, false, false), |
1084 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE_V2, &vmw_cmd_invalid), | 1659 | VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE_V2, &vmw_cmd_invalid, |
1085 | VMW_CMD_DEF(SVGA_3D_CMD_GENERATE_MIPMAPS, &vmw_cmd_invalid), | 1660 | false, false, false), |
1086 | VMW_CMD_DEF(SVGA_3D_CMD_ACTIVATE_SURFACE, &vmw_cmd_invalid), | 1661 | VMW_CMD_DEF(SVGA_3D_CMD_GENERATE_MIPMAPS, &vmw_cmd_invalid, |
1087 | VMW_CMD_DEF(SVGA_3D_CMD_DEACTIVATE_SURFACE, &vmw_cmd_invalid), | 1662 | false, false, false), |
1663 | VMW_CMD_DEF(SVGA_3D_CMD_ACTIVATE_SURFACE, &vmw_cmd_invalid, | ||
1664 | false, false, false), | ||
1665 | VMW_CMD_DEF(SVGA_3D_CMD_DEACTIVATE_SURFACE, &vmw_cmd_invalid, | ||
1666 | false, false, false), | ||
1667 | VMW_CMD_DEF(SVGA_3D_CMD_SCREEN_DMA, &vmw_cmd_invalid, | ||
1668 | false, false, false), | ||
1669 | VMW_CMD_DEF(SVGA_3D_CMD_SET_UNITY_SURFACE_COOKIE, &vmw_cmd_invalid, | ||
1670 | false, false, false), | ||
1671 | VMW_CMD_DEF(SVGA_3D_CMD_OPEN_CONTEXT_SURFACE, &vmw_cmd_invalid, | ||
1672 | false, false, false), | ||
1673 | VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_BITBLT, &vmw_cmd_invalid, | ||
1674 | false, false, false), | ||
1675 | VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_TRANSBLT, &vmw_cmd_invalid, | ||
1676 | false, false, false), | ||
1677 | VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_STRETCHBLT, &vmw_cmd_invalid, | ||
1678 | false, false, false), | ||
1679 | VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_COLORFILL, &vmw_cmd_invalid, | ||
1680 | false, false, false), | ||
1681 | VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_ALPHABLEND, &vmw_cmd_invalid, | ||
1682 | false, false, false), | ||
1683 | VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND, &vmw_cmd_invalid, | ||
1684 | false, false, false), | ||
1685 | VMW_CMD_DEF(SVGA_3D_CMD_SET_OTABLE_BASE, &vmw_cmd_invalid, | ||
1686 | false, false, true), | ||
1687 | VMW_CMD_DEF(SVGA_3D_CMD_READBACK_OTABLE, &vmw_cmd_invalid, | ||
1688 | false, false, true), | ||
1689 | VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_MOB, &vmw_cmd_invalid, | ||
1690 | false, false, true), | ||
1691 | VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_MOB, &vmw_cmd_invalid, | ||
1692 | false, false, true), | ||
1693 | VMW_CMD_DEF(SVGA_3D_CMD_REDEFINE_GB_MOB, &vmw_cmd_invalid, | ||
1694 | false, false, true), | ||
1695 | VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING, &vmw_cmd_invalid, | ||
1696 | false, false, true), | ||
1697 | VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SURFACE, &vmw_cmd_invalid, | ||
1698 | false, false, true), | ||
1699 | VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SURFACE, &vmw_cmd_invalid, | ||
1700 | false, false, true), | ||
1701 | VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SURFACE, &vmw_cmd_bind_gb_surface, | ||
1702 | true, false, true), | ||
1703 | VMW_CMD_DEF(SVGA_3D_CMD_COND_BIND_GB_SURFACE, &vmw_cmd_invalid, | ||
1704 | false, false, true), | ||
1705 | VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_IMAGE, &vmw_cmd_update_gb_image, | ||
1706 | true, false, true), | ||
1707 | VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_SURFACE, | ||
1708 | &vmw_cmd_update_gb_surface, true, false, true), | ||
1709 | VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_IMAGE, | ||
1710 | &vmw_cmd_readback_gb_image, true, false, true), | ||
1711 | VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_SURFACE, | ||
1712 | &vmw_cmd_readback_gb_surface, true, false, true), | ||
1713 | VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_IMAGE, | ||
1714 | &vmw_cmd_invalidate_gb_image, true, false, true), | ||
1715 | VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_SURFACE, | ||
1716 | &vmw_cmd_invalidate_gb_surface, true, false, true), | ||
1717 | VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_CONTEXT, &vmw_cmd_invalid, | ||
1718 | false, false, true), | ||
1719 | VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_CONTEXT, &vmw_cmd_invalid, | ||
1720 | false, false, true), | ||
1721 | VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_CONTEXT, &vmw_cmd_invalid, | ||
1722 | false, false, true), | ||
1723 | VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_CONTEXT, &vmw_cmd_invalid, | ||
1724 | false, false, true), | ||
1725 | VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_CONTEXT, &vmw_cmd_invalid, | ||
1726 | false, false, true), | ||
1727 | VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SHADER, &vmw_cmd_invalid, | ||
1728 | false, false, true), | ||
1729 | VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SHADER, &vmw_cmd_bind_gb_shader, | ||
1730 | true, false, true), | ||
1731 | VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SHADER, &vmw_cmd_invalid, | ||
1732 | false, false, true), | ||
1733 | VMW_CMD_DEF(SVGA_3D_CMD_SET_OTABLE_BASE64, &vmw_cmd_invalid, | ||
1734 | false, false, false), | ||
1735 | VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_GB_QUERY, &vmw_cmd_begin_gb_query, | ||
1736 | true, false, true), | ||
1737 | VMW_CMD_DEF(SVGA_3D_CMD_END_GB_QUERY, &vmw_cmd_end_gb_query, | ||
1738 | true, false, true), | ||
1739 | VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_GB_QUERY, &vmw_cmd_wait_gb_query, | ||
1740 | true, false, true), | ||
1741 | VMW_CMD_DEF(SVGA_3D_CMD_NOP, &vmw_cmd_ok, | ||
1742 | true, false, true), | ||
1743 | VMW_CMD_DEF(SVGA_3D_CMD_ENABLE_GART, &vmw_cmd_invalid, | ||
1744 | false, false, true), | ||
1745 | VMW_CMD_DEF(SVGA_3D_CMD_DISABLE_GART, &vmw_cmd_invalid, | ||
1746 | false, false, true), | ||
1747 | VMW_CMD_DEF(SVGA_3D_CMD_MAP_MOB_INTO_GART, &vmw_cmd_invalid, | ||
1748 | false, false, true), | ||
1749 | VMW_CMD_DEF(SVGA_3D_CMD_UNMAP_GART_RANGE, &vmw_cmd_invalid, | ||
1750 | false, false, true), | ||
1751 | VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SCREENTARGET, &vmw_cmd_invalid, | ||
1752 | false, false, true), | ||
1753 | VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SCREENTARGET, &vmw_cmd_invalid, | ||
1754 | false, false, true), | ||
1755 | VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SCREENTARGET, &vmw_cmd_invalid, | ||
1756 | false, false, true), | ||
1757 | VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_SCREENTARGET, &vmw_cmd_invalid, | ||
1758 | false, false, true), | ||
1759 | VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL, &vmw_cmd_invalid, | ||
1760 | false, false, true), | ||
1761 | VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL, &vmw_cmd_invalid, | ||
1762 | false, false, true), | ||
1763 | VMW_CMD_DEF(SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE, &vmw_cmd_cid_check, | ||
1764 | true, false, true) | ||
1088 | }; | 1765 | }; |
1089 | 1766 | ||
1090 | static int vmw_cmd_check(struct vmw_private *dev_priv, | 1767 | static int vmw_cmd_check(struct vmw_private *dev_priv, |
@@ -1095,6 +1772,8 @@ static int vmw_cmd_check(struct vmw_private *dev_priv, | |||
1095 | uint32_t size_remaining = *size; | 1772 | uint32_t size_remaining = *size; |
1096 | SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf; | 1773 | SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf; |
1097 | int ret; | 1774 | int ret; |
1775 | const struct vmw_cmd_entry *entry; | ||
1776 | bool gb = dev_priv->capabilities & SVGA_CAP_GBOBJECTS; | ||
1098 | 1777 | ||
1099 | cmd_id = le32_to_cpu(((uint32_t *)buf)[0]); | 1778 | cmd_id = le32_to_cpu(((uint32_t *)buf)[0]); |
1100 | /* Handle any none 3D commands */ | 1779 | /* Handle any none 3D commands */ |
@@ -1107,18 +1786,40 @@ static int vmw_cmd_check(struct vmw_private *dev_priv, | |||
1107 | 1786 | ||
1108 | cmd_id -= SVGA_3D_CMD_BASE; | 1787 | cmd_id -= SVGA_3D_CMD_BASE; |
1109 | if (unlikely(*size > size_remaining)) | 1788 | if (unlikely(*size > size_remaining)) |
1110 | goto out_err; | 1789 | goto out_invalid; |
1111 | 1790 | ||
1112 | if (unlikely(cmd_id >= SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE)) | 1791 | if (unlikely(cmd_id >= SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE)) |
1113 | goto out_err; | 1792 | goto out_invalid; |
1793 | |||
1794 | entry = &vmw_cmd_entries[cmd_id]; | ||
1795 | if (unlikely(!entry->user_allow && !sw_context->kernel)) | ||
1796 | goto out_privileged; | ||
1114 | 1797 | ||
1115 | ret = vmw_cmd_funcs[cmd_id](dev_priv, sw_context, header); | 1798 | if (unlikely(entry->gb_disable && gb)) |
1799 | goto out_old; | ||
1800 | |||
1801 | if (unlikely(entry->gb_enable && !gb)) | ||
1802 | goto out_new; | ||
1803 | |||
1804 | ret = entry->func(dev_priv, sw_context, header); | ||
1116 | if (unlikely(ret != 0)) | 1805 | if (unlikely(ret != 0)) |
1117 | goto out_err; | 1806 | goto out_invalid; |
1118 | 1807 | ||
1119 | return 0; | 1808 | return 0; |
1120 | out_err: | 1809 | out_invalid: |
1121 | DRM_ERROR("Illegal / Invalid SVGA3D command: %d\n", | 1810 | DRM_ERROR("Invalid SVGA3D command: %d\n", |
1811 | cmd_id + SVGA_3D_CMD_BASE); | ||
1812 | return -EINVAL; | ||
1813 | out_privileged: | ||
1814 | DRM_ERROR("Privileged SVGA3D command: %d\n", | ||
1815 | cmd_id + SVGA_3D_CMD_BASE); | ||
1816 | return -EPERM; | ||
1817 | out_old: | ||
1818 | DRM_ERROR("Deprecated (disallowed) SVGA3D command: %d\n", | ||
1819 | cmd_id + SVGA_3D_CMD_BASE); | ||
1820 | return -EINVAL; | ||
1821 | out_new: | ||
1822 | DRM_ERROR("SVGA3D command: %d not supported by virtual hardware.\n", | ||
1122 | cmd_id + SVGA_3D_CMD_BASE); | 1823 | cmd_id + SVGA_3D_CMD_BASE); |
1123 | return -EINVAL; | 1824 | return -EINVAL; |
1124 | } | 1825 | } |
@@ -1174,6 +1875,9 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context) | |||
1174 | case VMW_PL_GMR: | 1875 | case VMW_PL_GMR: |
1175 | reloc->location->gmrId = bo->mem.start; | 1876 | reloc->location->gmrId = bo->mem.start; |
1176 | break; | 1877 | break; |
1878 | case VMW_PL_MOB: | ||
1879 | *reloc->mob_loc = bo->mem.start; | ||
1880 | break; | ||
1177 | default: | 1881 | default: |
1178 | BUG(); | 1882 | BUG(); |
1179 | } | 1883 | } |
@@ -1198,6 +1902,8 @@ static void vmw_resource_list_unreference(struct list_head *list) | |||
1198 | list_for_each_entry_safe(val, val_next, list, head) { | 1902 | list_for_each_entry_safe(val, val_next, list, head) { |
1199 | list_del_init(&val->head); | 1903 | list_del_init(&val->head); |
1200 | vmw_resource_unreference(&val->res); | 1904 | vmw_resource_unreference(&val->res); |
1905 | if (unlikely(val->staged_bindings)) | ||
1906 | kfree(val->staged_bindings); | ||
1201 | kfree(val); | 1907 | kfree(val); |
1202 | } | 1908 | } |
1203 | } | 1909 | } |
@@ -1224,7 +1930,8 @@ static void vmw_clear_validations(struct vmw_sw_context *sw_context) | |||
1224 | } | 1930 | } |
1225 | 1931 | ||
1226 | static int vmw_validate_single_buffer(struct vmw_private *dev_priv, | 1932 | static int vmw_validate_single_buffer(struct vmw_private *dev_priv, |
1227 | struct ttm_buffer_object *bo) | 1933 | struct ttm_buffer_object *bo, |
1934 | bool validate_as_mob) | ||
1228 | { | 1935 | { |
1229 | int ret; | 1936 | int ret; |
1230 | 1937 | ||
@@ -1238,6 +1945,9 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv, | |||
1238 | dev_priv->dummy_query_bo_pinned)) | 1945 | dev_priv->dummy_query_bo_pinned)) |
1239 | return 0; | 1946 | return 0; |
1240 | 1947 | ||
1948 | if (validate_as_mob) | ||
1949 | return ttm_bo_validate(bo, &vmw_mob_placement, true, false); | ||
1950 | |||
1241 | /** | 1951 | /** |
1242 | * Put BO in VRAM if there is space, otherwise as a GMR. | 1952 | * Put BO in VRAM if there is space, otherwise as a GMR. |
1243 | * If there is no space in VRAM and GMR ids are all used up, | 1953 | * If there is no space in VRAM and GMR ids are all used up, |
@@ -1259,7 +1969,6 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv, | |||
1259 | return ret; | 1969 | return ret; |
1260 | } | 1970 | } |
1261 | 1971 | ||
1262 | |||
1263 | static int vmw_validate_buffers(struct vmw_private *dev_priv, | 1972 | static int vmw_validate_buffers(struct vmw_private *dev_priv, |
1264 | struct vmw_sw_context *sw_context) | 1973 | struct vmw_sw_context *sw_context) |
1265 | { | 1974 | { |
@@ -1267,7 +1976,8 @@ static int vmw_validate_buffers(struct vmw_private *dev_priv, | |||
1267 | int ret; | 1976 | int ret; |
1268 | 1977 | ||
1269 | list_for_each_entry(entry, &sw_context->validate_nodes, base.head) { | 1978 | list_for_each_entry(entry, &sw_context->validate_nodes, base.head) { |
1270 | ret = vmw_validate_single_buffer(dev_priv, entry->base.bo); | 1979 | ret = vmw_validate_single_buffer(dev_priv, entry->base.bo, |
1980 | entry->validate_as_mob); | ||
1271 | if (unlikely(ret != 0)) | 1981 | if (unlikely(ret != 0)) |
1272 | return ret; | 1982 | return ret; |
1273 | } | 1983 | } |
@@ -1509,11 +2219,17 @@ int vmw_execbuf_process(struct drm_file *file_priv, | |||
1509 | goto out_err; | 2219 | goto out_err; |
1510 | } | 2220 | } |
1511 | 2221 | ||
2222 | ret = mutex_lock_interruptible(&dev_priv->binding_mutex); | ||
2223 | if (unlikely(ret != 0)) { | ||
2224 | ret = -ERESTARTSYS; | ||
2225 | goto out_err; | ||
2226 | } | ||
2227 | |||
1512 | cmd = vmw_fifo_reserve(dev_priv, command_size); | 2228 | cmd = vmw_fifo_reserve(dev_priv, command_size); |
1513 | if (unlikely(cmd == NULL)) { | 2229 | if (unlikely(cmd == NULL)) { |
1514 | DRM_ERROR("Failed reserving fifo space for commands.\n"); | 2230 | DRM_ERROR("Failed reserving fifo space for commands.\n"); |
1515 | ret = -ENOMEM; | 2231 | ret = -ENOMEM; |
1516 | goto out_err; | 2232 | goto out_unlock_binding; |
1517 | } | 2233 | } |
1518 | 2234 | ||
1519 | vmw_apply_relocations(sw_context); | 2235 | vmw_apply_relocations(sw_context); |
@@ -1538,6 +2254,8 @@ int vmw_execbuf_process(struct drm_file *file_priv, | |||
1538 | DRM_ERROR("Fence submission error. Syncing.\n"); | 2254 | DRM_ERROR("Fence submission error. Syncing.\n"); |
1539 | 2255 | ||
1540 | vmw_resource_list_unreserve(&sw_context->resource_list, false); | 2256 | vmw_resource_list_unreserve(&sw_context->resource_list, false); |
2257 | mutex_unlock(&dev_priv->binding_mutex); | ||
2258 | |||
1541 | ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes, | 2259 | ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes, |
1542 | (void *) fence); | 2260 | (void *) fence); |
1543 | 2261 | ||
@@ -1568,6 +2286,8 @@ int vmw_execbuf_process(struct drm_file *file_priv, | |||
1568 | 2286 | ||
1569 | return 0; | 2287 | return 0; |
1570 | 2288 | ||
2289 | out_unlock_binding: | ||
2290 | mutex_unlock(&dev_priv->binding_mutex); | ||
1571 | out_err: | 2291 | out_err: |
1572 | vmw_resource_relocations_free(&sw_context->res_relocations); | 2292 | vmw_resource_relocations_free(&sw_context->res_relocations); |
1573 | vmw_free_relocations(sw_context); | 2293 | vmw_free_relocations(sw_context); |