aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2014-02-05 02:13:56 -0500
committerThomas Hellstrom <thellstrom@vmware.com>2014-02-05 02:41:58 -0500
commit30f82d816d2dccfdc2063ac8cca994904c9b612c (patch)
treead6be8058234603ad2361f2635275a43136d880c /drivers/gpu/drm/vmwgfx
parenta6fc955ff9fc60dcffc80003410a85d874e4f1e3 (diff)
drm/vmwgfx: Reemit context bindings when necessary v2
When a context is first referenced in the command stream, make sure that all scrubbed (as a result of eviction) bindings are re-emitted. Also make sure that all bound resources are put on the resource validate list. This is needed for legacy emulation, since legacy user-space drivers will typically not re-emit shader bindings. It also removes the requirement for user-space drivers to re-emit render-target- and texture bindings. Makes suspend and hibernate now also work with legacy user-space drivers on guest-backed devices. v2: Don't rebind on legacy devices. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Jakob Bornecrantz <jakob@vmware.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_context.c144
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h6
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c85
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c11
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_shader.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_surface.c2
6 files changed, 222 insertions, 28 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
index 82c41daebc0e..9426c53fb483 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
@@ -37,7 +37,7 @@ struct vmw_user_context {
37 37
38 38
39 39
40typedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *); 40typedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *, bool);
41 41
42static void vmw_user_context_free(struct vmw_resource *res); 42static void vmw_user_context_free(struct vmw_resource *res);
43static struct vmw_resource * 43static struct vmw_resource *
@@ -50,9 +50,11 @@ static int vmw_gb_context_unbind(struct vmw_resource *res,
50 bool readback, 50 bool readback,
51 struct ttm_validate_buffer *val_buf); 51 struct ttm_validate_buffer *val_buf);
52static int vmw_gb_context_destroy(struct vmw_resource *res); 52static int vmw_gb_context_destroy(struct vmw_resource *res);
53static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi); 53static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind);
54static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi); 54static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi,
55static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi); 55 bool rebind);
56static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi, bool rebind);
57static void vmw_context_binding_state_scrub(struct vmw_ctx_binding_state *cbs);
56static void vmw_context_binding_state_kill(struct vmw_ctx_binding_state *cbs); 58static void vmw_context_binding_state_kill(struct vmw_ctx_binding_state *cbs);
57static uint64_t vmw_user_context_size; 59static uint64_t vmw_user_context_size;
58 60
@@ -111,10 +113,14 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
111 113
112 if (res->func->destroy == vmw_gb_context_destroy) { 114 if (res->func->destroy == vmw_gb_context_destroy) {
113 mutex_lock(&dev_priv->cmdbuf_mutex); 115 mutex_lock(&dev_priv->cmdbuf_mutex);
116 mutex_lock(&dev_priv->binding_mutex);
117 (void) vmw_context_binding_state_kill
118 (&container_of(res, struct vmw_user_context, res)->cbs);
114 (void) vmw_gb_context_destroy(res); 119 (void) vmw_gb_context_destroy(res);
115 if (dev_priv->pinned_bo != NULL && 120 if (dev_priv->pinned_bo != NULL &&
116 !dev_priv->query_cid_valid) 121 !dev_priv->query_cid_valid)
117 __vmw_execbuf_release_pinned_bo(dev_priv, NULL); 122 __vmw_execbuf_release_pinned_bo(dev_priv, NULL);
123 mutex_unlock(&dev_priv->binding_mutex);
118 mutex_unlock(&dev_priv->cmdbuf_mutex); 124 mutex_unlock(&dev_priv->cmdbuf_mutex);
119 return; 125 return;
120 } 126 }
@@ -328,7 +334,7 @@ static int vmw_gb_context_unbind(struct vmw_resource *res,
328 BUG_ON(bo->mem.mem_type != VMW_PL_MOB); 334 BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
329 335
330 mutex_lock(&dev_priv->binding_mutex); 336 mutex_lock(&dev_priv->binding_mutex);
331 vmw_context_binding_state_kill(&uctx->cbs); 337 vmw_context_binding_state_scrub(&uctx->cbs);
332 338
333 submit_size = sizeof(*cmd2) + (readback ? sizeof(*cmd1) : 0); 339 submit_size = sizeof(*cmd2) + (readback ? sizeof(*cmd1) : 0);
334 340
@@ -378,10 +384,6 @@ static int vmw_gb_context_destroy(struct vmw_resource *res)
378 SVGA3dCmdHeader header; 384 SVGA3dCmdHeader header;
379 SVGA3dCmdDestroyGBContext body; 385 SVGA3dCmdDestroyGBContext body;
380 } *cmd; 386 } *cmd;
381 struct vmw_user_context *uctx =
382 container_of(res, struct vmw_user_context, res);
383
384 BUG_ON(!list_empty(&uctx->cbs.list));
385 387
386 if (likely(res->id == -1)) 388 if (likely(res->id == -1))
387 return 0; 389 return 0;
@@ -528,8 +530,9 @@ out_unlock:
528 * vmw_context_scrub_shader - scrub a shader binding from a context. 530 * vmw_context_scrub_shader - scrub a shader binding from a context.
529 * 531 *
530 * @bi: single binding information. 532 * @bi: single binding information.
533 * @rebind: Whether to issue a bind instead of scrub command.
531 */ 534 */
532static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi) 535static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind)
533{ 536{
534 struct vmw_private *dev_priv = bi->ctx->dev_priv; 537 struct vmw_private *dev_priv = bi->ctx->dev_priv;
535 struct { 538 struct {
@@ -548,7 +551,8 @@ static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi)
548 cmd->header.size = sizeof(cmd->body); 551 cmd->header.size = sizeof(cmd->body);
549 cmd->body.cid = bi->ctx->id; 552 cmd->body.cid = bi->ctx->id;
550 cmd->body.type = bi->i1.shader_type; 553 cmd->body.type = bi->i1.shader_type;
551 cmd->body.shid = SVGA3D_INVALID_ID; 554 cmd->body.shid =
555 cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
552 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 556 vmw_fifo_commit(dev_priv, sizeof(*cmd));
553 557
554 return 0; 558 return 0;
@@ -559,8 +563,10 @@ static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi)
559 * from a context. 563 * from a context.
560 * 564 *
561 * @bi: single binding information. 565 * @bi: single binding information.
566 * @rebind: Whether to issue a bind instead of scrub command.
562 */ 567 */
563static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi) 568static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi,
569 bool rebind)
564{ 570{
565 struct vmw_private *dev_priv = bi->ctx->dev_priv; 571 struct vmw_private *dev_priv = bi->ctx->dev_priv;
566 struct { 572 struct {
@@ -579,7 +585,8 @@ static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi)
579 cmd->header.size = sizeof(cmd->body); 585 cmd->header.size = sizeof(cmd->body);
580 cmd->body.cid = bi->ctx->id; 586 cmd->body.cid = bi->ctx->id;
581 cmd->body.type = bi->i1.rt_type; 587 cmd->body.type = bi->i1.rt_type;
582 cmd->body.target.sid = SVGA3D_INVALID_ID; 588 cmd->body.target.sid =
589 cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
583 cmd->body.target.face = 0; 590 cmd->body.target.face = 0;
584 cmd->body.target.mipmap = 0; 591 cmd->body.target.mipmap = 0;
585 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 592 vmw_fifo_commit(dev_priv, sizeof(*cmd));
@@ -591,11 +598,13 @@ static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi)
591 * vmw_context_scrub_texture - scrub a texture binding from a context. 598 * vmw_context_scrub_texture - scrub a texture binding from a context.
592 * 599 *
593 * @bi: single binding information. 600 * @bi: single binding information.
601 * @rebind: Whether to issue a bind instead of scrub command.
594 * 602 *
595 * TODO: Possibly complement this function with a function that takes 603 * TODO: Possibly complement this function with a function that takes
596 * a list of texture bindings and combines them to a single command. 604 * a list of texture bindings and combines them to a single command.
597 */ 605 */
598static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi) 606static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi,
607 bool rebind)
599{ 608{
600 struct vmw_private *dev_priv = bi->ctx->dev_priv; 609 struct vmw_private *dev_priv = bi->ctx->dev_priv;
601 struct { 610 struct {
@@ -619,7 +628,8 @@ static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi)
619 cmd->body.c.cid = bi->ctx->id; 628 cmd->body.c.cid = bi->ctx->id;
620 cmd->body.s1.stage = bi->i1.texture_stage; 629 cmd->body.s1.stage = bi->i1.texture_stage;
621 cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE; 630 cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE;
622 cmd->body.s1.value = (uint32) SVGA3D_INVALID_ID; 631 cmd->body.s1.value =
632 cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
623 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 633 vmw_fifo_commit(dev_priv, sizeof(*cmd));
624 634
625 return 0; 635 return 0;
@@ -692,6 +702,7 @@ int vmw_context_binding_add(struct vmw_ctx_binding_state *cbs,
692 vmw_context_binding_drop(loc); 702 vmw_context_binding_drop(loc);
693 703
694 loc->bi = *bi; 704 loc->bi = *bi;
705 loc->bi.scrubbed = false;
695 list_add_tail(&loc->ctx_list, &cbs->list); 706 list_add_tail(&loc->ctx_list, &cbs->list);
696 INIT_LIST_HEAD(&loc->res_list); 707 INIT_LIST_HEAD(&loc->res_list);
697 708
@@ -727,12 +738,11 @@ static void vmw_context_binding_transfer(struct vmw_ctx_binding_state *cbs,
727 if (loc->bi.ctx != NULL) 738 if (loc->bi.ctx != NULL)
728 vmw_context_binding_drop(loc); 739 vmw_context_binding_drop(loc);
729 740
730 loc->bi = *bi; 741 if (bi->res != NULL) {
731 list_add_tail(&loc->ctx_list, &cbs->list); 742 loc->bi = *bi;
732 if (bi->res != NULL) 743 list_add_tail(&loc->ctx_list, &cbs->list);
733 list_add_tail(&loc->res_list, &bi->res->binding_head); 744 list_add_tail(&loc->res_list, &bi->res->binding_head);
734 else 745 }
735 INIT_LIST_HEAD(&loc->res_list);
736} 746}
737 747
738/** 748/**
@@ -746,7 +756,10 @@ static void vmw_context_binding_transfer(struct vmw_ctx_binding_state *cbs,
746 */ 756 */
747static void vmw_context_binding_kill(struct vmw_ctx_binding *cb) 757static void vmw_context_binding_kill(struct vmw_ctx_binding *cb)
748{ 758{
749 (void) vmw_scrub_funcs[cb->bi.bt](&cb->bi); 759 if (!cb->bi.scrubbed) {
760 (void) vmw_scrub_funcs[cb->bi.bt](&cb->bi, false);
761 cb->bi.scrubbed = true;
762 }
750 vmw_context_binding_drop(cb); 763 vmw_context_binding_drop(cb);
751} 764}
752 765
@@ -768,6 +781,27 @@ static void vmw_context_binding_state_kill(struct vmw_ctx_binding_state *cbs)
768} 781}
769 782
770/** 783/**
784 * vmw_context_binding_state_scrub - Scrub all bindings associated with a
785 * struct vmw_ctx_binding state structure.
786 *
787 * @cbs: Pointer to the context binding state tracker.
788 *
789 * Emits commands to scrub all bindings associated with the
790 * context binding state tracker.
791 */
792static void vmw_context_binding_state_scrub(struct vmw_ctx_binding_state *cbs)
793{
794 struct vmw_ctx_binding *entry;
795
796 list_for_each_entry(entry, &cbs->list, ctx_list) {
797 if (!entry->bi.scrubbed) {
798 (void) vmw_scrub_funcs[entry->bi.bt](&entry->bi, false);
799 entry->bi.scrubbed = true;
800 }
801 }
802}
803
804/**
771 * vmw_context_binding_res_list_kill - Kill all bindings on a 805 * vmw_context_binding_res_list_kill - Kill all bindings on a
772 * resource binding list 806 * resource binding list
773 * 807 *
@@ -785,6 +819,27 @@ void vmw_context_binding_res_list_kill(struct list_head *head)
785} 819}
786 820
787/** 821/**
822 * vmw_context_binding_res_list_scrub - Scrub all bindings on a
823 * resource binding list
824 *
825 * @head: list head of resource binding list
826 *
827 * Scrub all bindings associated with a specific resource. Typically
828 * called before the resource is evicted.
829 */
830void vmw_context_binding_res_list_scrub(struct list_head *head)
831{
832 struct vmw_ctx_binding *entry;
833
834 list_for_each_entry(entry, head, res_list) {
835 if (!entry->bi.scrubbed) {
836 (void) vmw_scrub_funcs[entry->bi.bt](&entry->bi, false);
837 entry->bi.scrubbed = true;
838 }
839 }
840}
841
842/**
788 * vmw_context_binding_state_transfer - Commit staged binding info 843 * vmw_context_binding_state_transfer - Commit staged binding info
789 * 844 *
790 * @ctx: Pointer to context to commit the staged binding info to. 845 * @ctx: Pointer to context to commit the staged binding info to.
@@ -803,3 +858,50 @@ void vmw_context_binding_state_transfer(struct vmw_resource *ctx,
803 list_for_each_entry_safe(entry, next, &from->list, ctx_list) 858 list_for_each_entry_safe(entry, next, &from->list, ctx_list)
804 vmw_context_binding_transfer(&uctx->cbs, &entry->bi); 859 vmw_context_binding_transfer(&uctx->cbs, &entry->bi);
805} 860}
861
862/**
863 * vmw_context_rebind_all - Rebind all scrubbed bindings of a context
864 *
865 * @ctx: The context resource
866 *
867 * Walks through the context binding list and rebinds all scrubbed
868 * resources.
869 */
870int vmw_context_rebind_all(struct vmw_resource *ctx)
871{
872 struct vmw_ctx_binding *entry;
873 struct vmw_user_context *uctx =
874 container_of(ctx, struct vmw_user_context, res);
875 struct vmw_ctx_binding_state *cbs = &uctx->cbs;
876 int ret;
877
878 list_for_each_entry(entry, &cbs->list, ctx_list) {
879 if (likely(!entry->bi.scrubbed))
880 continue;
881
882 if (WARN_ON(entry->bi.res == NULL || entry->bi.res->id ==
883 SVGA3D_INVALID_ID))
884 continue;
885
886 ret = vmw_scrub_funcs[entry->bi.bt](&entry->bi, true);
887 if (unlikely(ret != 0))
888 return ret;
889
890 entry->bi.scrubbed = false;
891 }
892
893 return 0;
894}
895
896/**
897 * vmw_context_binding_list - Return a list of context bindings
898 *
899 * @ctx: The context resource
900 *
901 * Returns the current list of bindings of the given context. Note that
902 * this list becomes stale as soon as the dev_priv::binding_mutex is unlocked.
903 */
904struct list_head *vmw_context_binding_list(struct vmw_resource *ctx)
905{
906 return &(container_of(ctx, struct vmw_user_context, res)->cbs.list);
907}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index cef0ff7ac738..ecaa302a6154 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -276,6 +276,7 @@ struct vmw_ctx_bindinfo {
276 struct vmw_resource *ctx; 276 struct vmw_resource *ctx;
277 struct vmw_resource *res; 277 struct vmw_resource *res;
278 enum vmw_ctx_binding_type bt; 278 enum vmw_ctx_binding_type bt;
279 bool scrubbed;
279 union { 280 union {
280 SVGA3dShaderType shader_type; 281 SVGA3dShaderType shader_type;
281 SVGA3dRenderTargetType rt_type; 282 SVGA3dRenderTargetType rt_type;
@@ -574,6 +575,8 @@ struct vmw_user_resource_conv;
574 575
575extern void vmw_resource_unreference(struct vmw_resource **p_res); 576extern void vmw_resource_unreference(struct vmw_resource **p_res);
576extern struct vmw_resource *vmw_resource_reference(struct vmw_resource *res); 577extern struct vmw_resource *vmw_resource_reference(struct vmw_resource *res);
578extern struct vmw_resource *
579vmw_resource_reference_unless_doomed(struct vmw_resource *res);
577extern int vmw_resource_validate(struct vmw_resource *res); 580extern int vmw_resource_validate(struct vmw_resource *res);
578extern int vmw_resource_reserve(struct vmw_resource *res, bool no_backup); 581extern int vmw_resource_reserve(struct vmw_resource *res, bool no_backup);
579extern bool vmw_resource_needs_backup(const struct vmw_resource *res); 582extern bool vmw_resource_needs_backup(const struct vmw_resource *res);
@@ -962,6 +965,9 @@ extern void
962vmw_context_binding_state_transfer(struct vmw_resource *res, 965vmw_context_binding_state_transfer(struct vmw_resource *res,
963 struct vmw_ctx_binding_state *cbs); 966 struct vmw_ctx_binding_state *cbs);
964extern void vmw_context_binding_res_list_kill(struct list_head *head); 967extern void vmw_context_binding_res_list_kill(struct list_head *head);
968extern void vmw_context_binding_res_list_scrub(struct list_head *head);
969extern int vmw_context_rebind_all(struct vmw_resource *ctx);
970extern struct list_head *vmw_context_binding_list(struct vmw_resource *ctx);
965 971
966/* 972/*
967 * Surface management - vmwgfx_surface.c 973 * Surface management - vmwgfx_surface.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 352224b9d667..269b85cc875a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -180,6 +180,44 @@ static int vmw_resource_val_add(struct vmw_sw_context *sw_context,
180} 180}
181 181
182/** 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 */
193static 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/**
183 * vmw_resource_relocation_add - Add a relocation to the relocation list 221 * vmw_resource_relocation_add - Add a relocation to the relocation list
184 * 222 *
185 * @list: Pointer to head of relocation list. 223 * @list: Pointer to head of relocation list.
@@ -470,7 +508,11 @@ vmw_cmd_compat_res_check(struct vmw_private *dev_priv,
470 if (p_val) 508 if (p_val)
471 *p_val = node; 509 *p_val = node;
472 510
473 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;
474 node->staged_bindings = 516 node->staged_bindings =
475 kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL); 517 kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL);
476 if (node->staged_bindings == NULL) { 518 if (node->staged_bindings == NULL) {
@@ -517,6 +559,34 @@ vmw_cmd_res_check(struct vmw_private *dev_priv,
517} 559}
518 560
519/** 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 */
569static 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/**
520 * 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.
521 * 591 *
522 * @dev_priv: Pointer to a device private structure. 592 * @dev_priv: Pointer to a device private structure.
@@ -1640,9 +1710,10 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
1640 struct vmw_resource_val_node *res_node; 1710 struct vmw_resource_val_node *res_node;
1641 u32 shid = cmd->body.shid; 1711 u32 shid = cmd->body.shid;
1642 1712
1643 (void) vmw_compat_shader_lookup(sw_context->fp->shman, 1713 if (shid != SVGA3D_INVALID_ID)
1644 cmd->body.type, 1714 (void) vmw_compat_shader_lookup(sw_context->fp->shman,
1645 &shid); 1715 cmd->body.type,
1716 &shid);
1646 1717
1647 ret = vmw_cmd_compat_res_check(dev_priv, sw_context, 1718 ret = vmw_cmd_compat_res_check(dev_priv, sw_context,
1648 vmw_res_shader, 1719 vmw_res_shader,
@@ -2395,6 +2466,12 @@ int vmw_execbuf_process(struct drm_file *file_priv,
2395 goto out_err; 2466 goto out_err;
2396 } 2467 }
2397 2468
2469 if (dev_priv->has_mob) {
2470 ret = vmw_rebind_contexts(sw_context);
2471 if (unlikely(ret != 0))
2472 goto out_err;
2473 }
2474
2398 cmd = vmw_fifo_reserve(dev_priv, command_size); 2475 cmd = vmw_fifo_reserve(dev_priv, command_size);
2399 if (unlikely(cmd == NULL)) { 2476 if (unlikely(cmd == NULL)) {
2400 DRM_ERROR("Failed reserving fifo space for commands.\n"); 2477 DRM_ERROR("Failed reserving fifo space for commands.\n");
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 6fdd82d42f65..2aa4bc6a4d60 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -88,6 +88,11 @@ struct vmw_resource *vmw_resource_reference(struct vmw_resource *res)
88 return res; 88 return res;
89} 89}
90 90
91struct vmw_resource *
92vmw_resource_reference_unless_doomed(struct vmw_resource *res)
93{
94 return kref_get_unless_zero(&res->kref) ? res : NULL;
95}
91 96
92/** 97/**
93 * vmw_resource_release_id - release a resource id to the id manager. 98 * vmw_resource_release_id - release a resource id to the id manager.
@@ -136,8 +141,12 @@ static void vmw_resource_release(struct kref *kref)
136 vmw_dmabuf_unreference(&res->backup); 141 vmw_dmabuf_unreference(&res->backup);
137 } 142 }
138 143
139 if (likely(res->hw_destroy != NULL)) 144 if (likely(res->hw_destroy != NULL)) {
140 res->hw_destroy(res); 145 res->hw_destroy(res);
146 mutex_lock(&dev_priv->binding_mutex);
147 vmw_context_binding_res_list_kill(&res->binding_head);
148 mutex_unlock(&dev_priv->binding_mutex);
149 }
141 150
142 id = res->id; 151 id = res->id;
143 if (res->res_free != NULL) 152 if (res->res_free != NULL)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
index be85d7fdfb5b..217d941b8176 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
@@ -304,7 +304,7 @@ static int vmw_gb_shader_destroy(struct vmw_resource *res)
304 return 0; 304 return 0;
305 305
306 mutex_lock(&dev_priv->binding_mutex); 306 mutex_lock(&dev_priv->binding_mutex);
307 vmw_context_binding_res_list_kill(&res->binding_head); 307 vmw_context_binding_res_list_scrub(&res->binding_head);
308 308
309 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 309 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
310 if (unlikely(cmd == NULL)) { 310 if (unlikely(cmd == NULL)) {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index ec2b99833fce..82468d902915 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -1111,7 +1111,7 @@ static int vmw_gb_surface_destroy(struct vmw_resource *res)
1111 return 0; 1111 return 0;
1112 1112
1113 mutex_lock(&dev_priv->binding_mutex); 1113 mutex_lock(&dev_priv->binding_mutex);
1114 vmw_context_binding_res_list_kill(&res->binding_head); 1114 vmw_context_binding_res_list_scrub(&res->binding_head);
1115 1115
1116 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 1116 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
1117 if (unlikely(cmd == NULL)) { 1117 if (unlikely(cmd == NULL)) {