diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2016-10-10 14:06:45 -0400 |
---|---|---|
committer | Sinclair Yeh <syeh@vmware.com> | 2016-10-10 14:15:05 -0400 |
commit | a19440304db2d97aed5cee9bfa5017c98d2348bf (patch) | |
tree | cf6c0727b420debe8be56edc17d50e6a8487e471 | |
parent | 51ab70bed997f64f091a639dbe22b629725a7faf (diff) |
drm/vmwgfx: Avoid validating views on view destruction
When a view destruction command was present in the command stream, the
view was validated to avoid a device error. That caused excessive and
unnecessary validations of views, surfaces and mobs on view destruction.
Replace this with a new relocation type that patches the view
destruction command to a NOP if the view is not present in the device
after the execbuf validation sequence.
Also add checks for the member size of the vmw_res_relocation struct.
Fixes sporadic command submission errors on google-earth exit.
Reported-by: Brian Paul <brianp@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Sinclair Yeh <syeh@vmware.com>
Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Cc: stable@vger.kernel.org
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 71 |
1 files changed, 58 insertions, 13 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index d1f4a48dee0f..c7b53d987f06 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | |||
@@ -35,17 +35,37 @@ | |||
35 | #define VMW_RES_HT_ORDER 12 | 35 | #define VMW_RES_HT_ORDER 12 |
36 | 36 | ||
37 | /** | 37 | /** |
38 | * enum vmw_resource_relocation_type - Relocation type for resources | ||
39 | * | ||
40 | * @vmw_res_rel_normal: Traditional relocation. The resource id in the | ||
41 | * command stream is replaced with the actual id after validation. | ||
42 | * @vmw_res_rel_nop: NOP relocation. The command is unconditionally replaced | ||
43 | * with a NOP. | ||
44 | * @vmw_res_rel_cond_nop: Conditional NOP relocation. If the resource id | ||
45 | * after validation is -1, the command is replaced with a NOP. Otherwise no | ||
46 | * action. | ||
47 | */ | ||
48 | enum vmw_resource_relocation_type { | ||
49 | vmw_res_rel_normal, | ||
50 | vmw_res_rel_nop, | ||
51 | vmw_res_rel_cond_nop, | ||
52 | vmw_res_rel_max | ||
53 | }; | ||
54 | |||
55 | /** | ||
38 | * struct vmw_resource_relocation - Relocation info for resources | 56 | * struct vmw_resource_relocation - Relocation info for resources |
39 | * | 57 | * |
40 | * @head: List head for the software context's relocation list. | 58 | * @head: List head for the software context's relocation list. |
41 | * @res: Non-ref-counted pointer to the resource. | 59 | * @res: Non-ref-counted pointer to the resource. |
42 | * @offset: Offset of single byte entries into the command buffer where the | 60 | * @offset: Offset of single byte entries into the command buffer where the |
43 | * id that needs fixup is located. | 61 | * id that needs fixup is located. |
62 | * @rel_type: Type of relocation. | ||
44 | */ | 63 | */ |
45 | struct vmw_resource_relocation { | 64 | struct vmw_resource_relocation { |
46 | struct list_head head; | 65 | struct list_head head; |
47 | const struct vmw_resource *res; | 66 | const struct vmw_resource *res; |
48 | unsigned long offset; | 67 | u32 offset:29; |
68 | enum vmw_resource_relocation_type rel_type:3; | ||
49 | }; | 69 | }; |
50 | 70 | ||
51 | /** | 71 | /** |
@@ -421,10 +441,13 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, | |||
421 | * @res: The resource. | 441 | * @res: The resource. |
422 | * @offset: Offset into the command buffer currently being parsed where the | 442 | * @offset: Offset into the command buffer currently being parsed where the |
423 | * id that needs fixup is located. Granularity is one byte. | 443 | * id that needs fixup is located. Granularity is one byte. |
444 | * @rel_type: Relocation type. | ||
424 | */ | 445 | */ |
425 | static int vmw_resource_relocation_add(struct list_head *list, | 446 | static int vmw_resource_relocation_add(struct list_head *list, |
426 | const struct vmw_resource *res, | 447 | const struct vmw_resource *res, |
427 | unsigned long offset) | 448 | unsigned long offset, |
449 | enum vmw_resource_relocation_type | ||
450 | rel_type) | ||
428 | { | 451 | { |
429 | struct vmw_resource_relocation *rel; | 452 | struct vmw_resource_relocation *rel; |
430 | 453 | ||
@@ -436,6 +459,7 @@ static int vmw_resource_relocation_add(struct list_head *list, | |||
436 | 459 | ||
437 | rel->res = res; | 460 | rel->res = res; |
438 | rel->offset = offset; | 461 | rel->offset = offset; |
462 | rel->rel_type = rel_type; | ||
439 | list_add_tail(&rel->head, list); | 463 | list_add_tail(&rel->head, list); |
440 | 464 | ||
441 | return 0; | 465 | return 0; |
@@ -470,12 +494,24 @@ static void vmw_resource_relocations_apply(uint32_t *cb, | |||
470 | { | 494 | { |
471 | struct vmw_resource_relocation *rel; | 495 | struct vmw_resource_relocation *rel; |
472 | 496 | ||
497 | /* Validate the struct vmw_resource_relocation member size */ | ||
498 | BUILD_BUG_ON(SVGA_CB_MAX_SIZE >= (1 << 29)); | ||
499 | BUILD_BUG_ON(vmw_res_rel_max >= (1 << 3)); | ||
500 | |||
473 | list_for_each_entry(rel, list, head) { | 501 | list_for_each_entry(rel, list, head) { |
474 | u32 *addr = (u32 *)((unsigned long) cb + rel->offset); | 502 | u32 *addr = (u32 *)((unsigned long) cb + rel->offset); |
475 | if (likely(rel->res != NULL)) | 503 | switch (rel->rel_type) { |
504 | case vmw_res_rel_normal: | ||
476 | *addr = rel->res->id; | 505 | *addr = rel->res->id; |
477 | else | 506 | break; |
507 | case vmw_res_rel_nop: | ||
478 | *addr = SVGA_3D_CMD_NOP; | 508 | *addr = SVGA_3D_CMD_NOP; |
509 | break; | ||
510 | default: | ||
511 | if (rel->res->id == -1) | ||
512 | *addr = SVGA_3D_CMD_NOP; | ||
513 | break; | ||
514 | } | ||
479 | } | 515 | } |
480 | } | 516 | } |
481 | 517 | ||
@@ -668,7 +704,8 @@ static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv, | |||
668 | ret = vmw_resource_relocation_add(&sw_context->res_relocations, | 704 | ret = vmw_resource_relocation_add(&sw_context->res_relocations, |
669 | res, | 705 | res, |
670 | vmw_ptr_diff(sw_context->buf_start, | 706 | vmw_ptr_diff(sw_context->buf_start, |
671 | id_loc)); | 707 | id_loc), |
708 | vmw_res_rel_normal); | ||
672 | if (unlikely(ret != 0)) | 709 | if (unlikely(ret != 0)) |
673 | return ret; | 710 | return ret; |
674 | 711 | ||
@@ -734,7 +771,8 @@ vmw_cmd_res_check(struct vmw_private *dev_priv, | |||
734 | 771 | ||
735 | return vmw_resource_relocation_add | 772 | return vmw_resource_relocation_add |
736 | (&sw_context->res_relocations, res, | 773 | (&sw_context->res_relocations, res, |
737 | vmw_ptr_diff(sw_context->buf_start, id_loc)); | 774 | vmw_ptr_diff(sw_context->buf_start, id_loc), |
775 | vmw_res_rel_normal); | ||
738 | } | 776 | } |
739 | 777 | ||
740 | ret = vmw_user_resource_lookup_handle(dev_priv, | 778 | ret = vmw_user_resource_lookup_handle(dev_priv, |
@@ -2158,7 +2196,8 @@ static int vmw_cmd_shader_define(struct vmw_private *dev_priv, | |||
2158 | return vmw_resource_relocation_add(&sw_context->res_relocations, | 2196 | return vmw_resource_relocation_add(&sw_context->res_relocations, |
2159 | NULL, | 2197 | NULL, |
2160 | vmw_ptr_diff(sw_context->buf_start, | 2198 | vmw_ptr_diff(sw_context->buf_start, |
2161 | &cmd->header.id)); | 2199 | &cmd->header.id), |
2200 | vmw_res_rel_nop); | ||
2162 | } | 2201 | } |
2163 | 2202 | ||
2164 | /** | 2203 | /** |
@@ -2202,7 +2241,8 @@ static int vmw_cmd_shader_destroy(struct vmw_private *dev_priv, | |||
2202 | return vmw_resource_relocation_add(&sw_context->res_relocations, | 2241 | return vmw_resource_relocation_add(&sw_context->res_relocations, |
2203 | NULL, | 2242 | NULL, |
2204 | vmw_ptr_diff(sw_context->buf_start, | 2243 | vmw_ptr_diff(sw_context->buf_start, |
2205 | &cmd->header.id)); | 2244 | &cmd->header.id), |
2245 | vmw_res_rel_nop); | ||
2206 | } | 2246 | } |
2207 | 2247 | ||
2208 | /** | 2248 | /** |
@@ -2859,8 +2899,7 @@ static int vmw_cmd_dx_cid_check(struct vmw_private *dev_priv, | |||
2859 | * @header: Pointer to the command header in the command stream. | 2899 | * @header: Pointer to the command header in the command stream. |
2860 | * | 2900 | * |
2861 | * Check that the view exists, and if it was not created using this | 2901 | * Check that the view exists, and if it was not created using this |
2862 | * command batch, make sure it's validated (present in the device) so that | 2902 | * command batch, conditionally make this command a NOP. |
2863 | * the remove command will not confuse the device. | ||
2864 | */ | 2903 | */ |
2865 | static int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv, | 2904 | static int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv, |
2866 | struct vmw_sw_context *sw_context, | 2905 | struct vmw_sw_context *sw_context, |
@@ -2888,10 +2927,16 @@ static int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv, | |||
2888 | return ret; | 2927 | return ret; |
2889 | 2928 | ||
2890 | /* | 2929 | /* |
2891 | * Add view to the validate list iff it was not created using this | 2930 | * If the view wasn't created during this command batch, it might |
2892 | * command batch. | 2931 | * have been removed due to a context swapout, so add a |
2932 | * relocation to conditionally make this command a NOP to avoid | ||
2933 | * device errors. | ||
2893 | */ | 2934 | */ |
2894 | return vmw_view_res_val_add(sw_context, view); | 2935 | return vmw_resource_relocation_add(&sw_context->res_relocations, |
2936 | view, | ||
2937 | vmw_ptr_diff(sw_context->buf_start, | ||
2938 | &cmd->header.id), | ||
2939 | vmw_res_rel_cond_nop); | ||
2895 | } | 2940 | } |
2896 | 2941 | ||
2897 | /** | 2942 | /** |