diff options
25 files changed, 972 insertions, 1231 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_binding.c b/drivers/gpu/drm/vmwgfx/vmwgfx_binding.c index 0b9ee7fb45d6..66e14e38d5e8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_binding.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_binding.c @@ -499,12 +499,9 @@ static int vmw_binding_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind) SVGA3dCmdSetShader body; } *cmd; - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for shader " - "unbinding.\n"); + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); + if (unlikely(cmd == NULL)) return -ENOMEM; - } cmd->header.id = SVGA_3D_CMD_SET_SHADER; cmd->header.size = sizeof(cmd->body); @@ -534,12 +531,9 @@ static int vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo *bi, SVGA3dCmdSetRenderTarget body; } *cmd; - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for render target " - "unbinding.\n"); + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); + if (unlikely(cmd == NULL)) return -ENOMEM; - } cmd->header.id = SVGA_3D_CMD_SETRENDERTARGET; cmd->header.size = sizeof(cmd->body); @@ -576,12 +570,9 @@ static int vmw_binding_scrub_texture(struct vmw_ctx_bindinfo *bi, } body; } *cmd; - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for texture " - "unbinding.\n"); + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); + if (unlikely(cmd == NULL)) return -ENOMEM; - } cmd->header.id = SVGA_3D_CMD_SETTEXTURESTATE; cmd->header.size = sizeof(cmd->body); @@ -610,12 +601,10 @@ static int vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo *bi, bool rebind) SVGA3dCmdDXSetShader body; } *cmd; - cmd = vmw_fifo_reserve_dx(dev_priv, sizeof(*cmd), bi->ctx->id); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for DX shader " - "unbinding.\n"); + cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id); + if (unlikely(cmd == NULL)) return -ENOMEM; - } + cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER; cmd->header.size = sizeof(cmd->body); cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN; @@ -641,12 +630,9 @@ static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind) SVGA3dCmdDXSetSingleConstantBuffer body; } *cmd; - cmd = vmw_fifo_reserve_dx(dev_priv, sizeof(*cmd), bi->ctx->id); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for DX shader " - "unbinding.\n"); + cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id); + if (unlikely(cmd == NULL)) return -ENOMEM; - } cmd->header.id = SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER; cmd->header.size = sizeof(cmd->body); @@ -768,12 +754,9 @@ static int vmw_emit_set_sr(struct vmw_ctx_binding_state *cbs, view_id_size = cbs->bind_cmd_count*sizeof(uint32); cmd_size = sizeof(*cmd) + view_id_size; - cmd = vmw_fifo_reserve_dx(ctx->dev_priv, cmd_size, ctx->id); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for DX shader" - " resource binding.\n"); + cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); + if (unlikely(cmd == NULL)) return -ENOMEM; - } cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER_RESOURCES; cmd->header.size = sizeof(cmd->body) + view_id_size; @@ -807,12 +790,9 @@ static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs) vmw_collect_view_ids(cbs, loc, SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS); view_id_size = cbs->bind_cmd_count*sizeof(uint32); cmd_size = sizeof(*cmd) + view_id_size; - cmd = vmw_fifo_reserve_dx(ctx->dev_priv, cmd_size, ctx->id); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for DX render-target" - " binding.\n"); + cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); + if (unlikely(cmd == NULL)) return -ENOMEM; - } cmd->header.id = SVGA_3D_CMD_DX_SET_RENDERTARGETS; cmd->header.size = sizeof(cmd->body) + view_id_size; @@ -894,12 +874,9 @@ static int vmw_emit_set_so(struct vmw_ctx_binding_state *cbs) so_target_size = cbs->bind_cmd_count*sizeof(SVGA3dSoTarget); cmd_size = sizeof(*cmd) + so_target_size; - cmd = vmw_fifo_reserve_dx(ctx->dev_priv, cmd_size, ctx->id); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for DX SO target" - " binding.\n"); + cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); + if (unlikely(cmd == NULL)) return -ENOMEM; - } cmd->header.id = SVGA_3D_CMD_DX_SET_SOTARGETS; cmd->header.size = sizeof(cmd->body) + so_target_size; @@ -1011,12 +988,9 @@ static int vmw_emit_set_vb(struct vmw_ctx_binding_state *cbs) set_vb_size = cbs->bind_cmd_count*sizeof(SVGA3dVertexBuffer); cmd_size = sizeof(*cmd) + set_vb_size; - cmd = vmw_fifo_reserve_dx(ctx->dev_priv, cmd_size, ctx->id); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for DX vertex buffer" - " binding.\n"); + cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); + if (unlikely(cmd == NULL)) return -ENOMEM; - } cmd->header.id = SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS; cmd->header.size = sizeof(cmd->body) + set_vb_size; @@ -1167,12 +1141,10 @@ static int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind) SVGA3dCmdDXSetIndexBuffer body; } *cmd; - cmd = vmw_fifo_reserve_dx(dev_priv, sizeof(*cmd), bi->ctx->id); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for DX index buffer " - "binding.\n"); + cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id); + if (unlikely(cmd == NULL)) return -ENOMEM; - } + cmd->header.id = SVGA_3D_CMD_DX_SET_INDEX_BUFFER; cmd->header.size = sizeof(cmd->body); if (rebind) { @@ -1269,6 +1241,32 @@ void vmw_binding_state_reset(struct vmw_ctx_binding_state *cbs) vmw_binding_drop(entry); } +/** + * vmw_binding_dirtying - Return whether a binding type is dirtying its resource + * @binding_type: The binding type + * + * Each time a resource is put on the validation list as the result of a + * context binding referencing it, we need to determine whether that resource + * will be dirtied (written to by the GPU) as a result of the corresponding + * GPU operation. Currently rendertarget-, depth-stencil-, and + * stream-output-target bindings are capable of dirtying its resource. + * + * Return: Whether the binding type dirties the resource its binding points to. + */ +u32 vmw_binding_dirtying(enum vmw_ctx_binding_type binding_type) +{ + static u32 is_binding_dirtying[vmw_ctx_binding_max] = { + [vmw_ctx_binding_rt] = VMW_RES_DIRTY_SET, + [vmw_ctx_binding_dx_rt] = VMW_RES_DIRTY_SET, + [vmw_ctx_binding_ds] = VMW_RES_DIRTY_SET, + [vmw_ctx_binding_so] = VMW_RES_DIRTY_SET, + }; + + /* Review this function as new bindings are added. */ + BUILD_BUG_ON(vmw_ctx_binding_max != 11); + return is_binding_dirtying[binding_type]; +} + /* * This function is unused at run-time, and only used to hold various build * asserts important for code optimization assumptions. diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_binding.h b/drivers/gpu/drm/vmwgfx/vmwgfx_binding.h index 6a2a9d69043b..f6ab79d23923 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_binding.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_binding.h @@ -205,5 +205,7 @@ extern void vmw_binding_state_free(struct vmw_ctx_binding_state *cbs); extern struct list_head * vmw_binding_state_list(struct vmw_ctx_binding_state *cbs); extern void vmw_binding_state_reset(struct vmw_ctx_binding_state *cbs); +extern u32 vmw_binding_dirtying(enum vmw_ctx_binding_type binding_type); + #endif diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c index 70dab55e7888..56979e412ca8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c @@ -393,6 +393,7 @@ static void vmw_cmdbuf_ctx_process(struct vmw_cmdbuf_man *man, __vmw_cmdbuf_header_free(entry); break; case SVGA_CB_STATUS_COMMAND_ERROR: + WARN_ONCE(true, "Command buffer error.\n"); entry->cb_header->status = SVGA_CB_STATUS_NONE; list_add_tail(&entry->list, &man->error); schedule_work(&man->work); @@ -511,17 +512,14 @@ static void vmw_cmdbuf_work_func(struct work_struct *work) container_of(work, struct vmw_cmdbuf_man, work); struct vmw_cmdbuf_header *entry, *next; uint32_t dummy; - bool restart[SVGA_CB_CONTEXT_MAX]; bool send_fence = false; struct list_head restart_head[SVGA_CB_CONTEXT_MAX]; int i; struct vmw_cmdbuf_context *ctx; bool global_block = false; - for_each_cmdbuf_ctx(man, i, ctx) { + for_each_cmdbuf_ctx(man, i, ctx) INIT_LIST_HEAD(&restart_head[i]); - restart[i] = false; - } mutex_lock(&man->error_mutex); spin_lock(&man->lock); @@ -533,23 +531,23 @@ static void vmw_cmdbuf_work_func(struct work_struct *work) const char *cmd_name; list_del_init(&entry->list); - restart[entry->cb_context] = true; global_block = true; if (!vmw_cmd_describe(header, &error_cmd_size, &cmd_name)) { - DRM_ERROR("Unknown command causing device error.\n"); - DRM_ERROR("Command buffer offset is %lu\n", - (unsigned long) cb_hdr->errorOffset); + VMW_DEBUG_USER("Unknown command causing device error.\n"); + VMW_DEBUG_USER("Command buffer offset is %lu\n", + (unsigned long) cb_hdr->errorOffset); __vmw_cmdbuf_header_free(entry); send_fence = true; continue; } - DRM_ERROR("Command \"%s\" causing device error.\n", cmd_name); - DRM_ERROR("Command buffer offset is %lu\n", - (unsigned long) cb_hdr->errorOffset); - DRM_ERROR("Command size is %lu\n", - (unsigned long) error_cmd_size); + VMW_DEBUG_USER("Command \"%s\" causing device error.\n", + cmd_name); + VMW_DEBUG_USER("Command buffer offset is %lu\n", + (unsigned long) cb_hdr->errorOffset); + VMW_DEBUG_USER("Command size is %lu\n", + (unsigned long) error_cmd_size); new_start_offset = cb_hdr->errorOffset + error_cmd_size; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c index 14bd760a62fd..63f111068a44 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c @@ -156,12 +156,9 @@ static void vmw_hw_context_destroy(struct vmw_resource *res) } vmw_execbuf_release_pinned_bo(dev_priv); - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for surface " - "destruction.\n"); + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); + if (unlikely(cmd == NULL)) return; - } cmd->header.id = SVGA_3D_CMD_CONTEXT_DESTROY; cmd->header.size = sizeof(cmd->body); @@ -210,7 +207,7 @@ static int vmw_gb_context_init(struct vmw_private *dev_priv, for (i = 0; i < SVGA_COTABLE_DX10_MAX; ++i) { uctx->cotables[i] = vmw_cotable_alloc(dev_priv, &uctx->res, i); - if (unlikely(IS_ERR(uctx->cotables[i]))) { + if (IS_ERR(uctx->cotables[i])) { ret = PTR_ERR(uctx->cotables[i]); goto out_cotables; } @@ -259,9 +256,8 @@ static int vmw_context_init(struct vmw_private *dev_priv, return -ENOMEM; } - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); if (unlikely(cmd == NULL)) { - DRM_ERROR("Fifo reserve failed.\n"); vmw_resource_unreference(&res); return -ENOMEM; } @@ -311,10 +307,8 @@ static int vmw_gb_context_create(struct vmw_resource *res) goto out_no_fifo; } - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for context " - "creation.\n"); ret = -ENOMEM; goto out_no_fifo; } @@ -345,12 +339,10 @@ static int vmw_gb_context_bind(struct vmw_resource *res, BUG_ON(bo->mem.mem_type != VMW_PL_MOB); - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for context " - "binding.\n"); + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); + if (unlikely(cmd == NULL)) return -ENOMEM; - } + cmd->header.id = SVGA_3D_CMD_BIND_GB_CONTEXT; cmd->header.size = sizeof(cmd->body); cmd->body.cid = res->id; @@ -391,10 +383,8 @@ static int vmw_gb_context_unbind(struct vmw_resource *res, submit_size = sizeof(*cmd2) + (readback ? sizeof(*cmd1) : 0); - cmd = vmw_fifo_reserve(dev_priv, submit_size); + cmd = VMW_FIFO_RESERVE(dev_priv, submit_size); if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for context " - "unbinding.\n"); mutex_unlock(&dev_priv->binding_mutex); return -ENOMEM; } @@ -441,12 +431,9 @@ static int vmw_gb_context_destroy(struct vmw_resource *res) if (likely(res->id == -1)) return 0; - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for context " - "destruction.\n"); + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); + if (unlikely(cmd == NULL)) return -ENOMEM; - } cmd->header.id = SVGA_3D_CMD_DESTROY_GB_CONTEXT; cmd->header.size = sizeof(cmd->body); @@ -487,10 +474,8 @@ static int vmw_dx_context_create(struct vmw_resource *res) goto out_no_fifo; } - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for context " - "creation.\n"); ret = -ENOMEM; goto out_no_fifo; } @@ -521,12 +506,9 @@ static int vmw_dx_context_bind(struct vmw_resource *res, BUG_ON(bo->mem.mem_type != VMW_PL_MOB); - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for context " - "binding.\n"); + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); + if (unlikely(cmd == NULL)) return -ENOMEM; - } cmd->header.id = SVGA_3D_CMD_DX_BIND_CONTEXT; cmd->header.size = sizeof(cmd->body); @@ -615,10 +597,8 @@ static int vmw_dx_context_unbind(struct vmw_resource *res, submit_size = sizeof(*cmd2) + (readback ? sizeof(*cmd1) : 0); - cmd = vmw_fifo_reserve(dev_priv, submit_size); + cmd = VMW_FIFO_RESERVE(dev_priv, submit_size); if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for context " - "unbinding.\n"); mutex_unlock(&dev_priv->binding_mutex); return -ENOMEM; } @@ -665,12 +645,9 @@ static int vmw_dx_context_destroy(struct vmw_resource *res) if (likely(res->id == -1)) return 0; - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for context " - "destruction.\n"); + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); + if (unlikely(cmd == NULL)) return -ENOMEM; - } cmd->header.id = SVGA_3D_CMD_DX_DESTROY_CONTEXT; cmd->header.size = sizeof(cmd->body); @@ -751,7 +728,7 @@ static int vmw_context_define(struct drm_device *dev, void *data, int ret; if (!dev_priv->has_dx && dx) { - DRM_ERROR("DX contexts not supported by device.\n"); + VMW_DEBUG_USER("DX contexts not supported by device.\n"); return -EINVAL; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c index 44f3f6f107d3..b4f6e1217c9d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c @@ -171,12 +171,9 @@ static int vmw_cotable_unscrub(struct vmw_resource *res) WARN_ON_ONCE(bo->mem.mem_type != VMW_PL_MOB); lockdep_assert_held(&bo->resv->lock.base); - cmd = vmw_fifo_reserve_dx(dev_priv, sizeof(*cmd), SVGA3D_INVALID_ID); - if (!cmd) { - DRM_ERROR("Failed reserving FIFO space for cotable " - "binding.\n"); + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); + if (!cmd) return -ENOMEM; - } WARN_ON(vcotbl->ctx->id == SVGA3D_INVALID_ID); WARN_ON(bo->mem.mem_type != VMW_PL_MOB); @@ -262,12 +259,9 @@ int vmw_cotable_scrub(struct vmw_resource *res, bool readback) if (readback) submit_size += sizeof(*cmd0); - cmd1 = vmw_fifo_reserve_dx(dev_priv, submit_size, SVGA3D_INVALID_ID); - if (!cmd1) { - DRM_ERROR("Failed reserving FIFO space for cotable " - "unbinding.\n"); + cmd1 = VMW_FIFO_RESERVE(dev_priv, submit_size); + if (!cmd1) return -ENOMEM; - } vcotbl->size_read_back = 0; if (readback) { @@ -351,13 +345,10 @@ static int vmw_cotable_readback(struct vmw_resource *res) struct vmw_fence_obj *fence; if (!vcotbl->scrubbed) { - cmd = vmw_fifo_reserve_dx(dev_priv, sizeof(*cmd), - SVGA3D_INVALID_ID); - if (!cmd) { - DRM_ERROR("Failed reserving FIFO space for cotable " - "readback.\n"); + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); + if (!cmd) return -ENOMEM; - } + cmd->header.id = SVGA_3D_CMD_DX_READBACK_COTABLE; cmd->header.size = sizeof(cmd->body); cmd->body.cid = vcotbl->ctx->id; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 6302c12c2298..96983c47fb40 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -699,6 +699,8 @@ extern int vmw_user_stream_lookup(struct vmw_private *dev_priv, uint32_t *inout_id, struct vmw_resource **out); extern void vmw_resource_unreserve(struct vmw_resource *res, + bool dirty_set, + bool dirty, bool switch_backup, struct vmw_buffer_object *new_backup, unsigned long new_backup_offset); @@ -811,7 +813,6 @@ extern int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo); extern void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo); -extern void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes); extern void * vmw_fifo_reserve_dx(struct vmw_private *dev_priv, uint32_t bytes, int ctx_id); extern void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes); @@ -827,6 +828,18 @@ extern int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv, extern int vmw_fifo_flush(struct vmw_private *dev_priv, bool interruptible); +#define VMW_FIFO_RESERVE_DX(__priv, __bytes, __ctx_id) \ +({ \ + vmw_fifo_reserve_dx(__priv, __bytes, __ctx_id) ? : ({ \ + DRM_ERROR("FIFO reserve failed at %s for %u bytes\n", \ + __func__, (unsigned int) __bytes); \ + NULL; \ + }); \ +}) + +#define VMW_FIFO_RESERVE(__priv, __bytes) \ + VMW_FIFO_RESERVE_DX(__priv, __bytes, SVGA3D_INVALID_ID) + /** * TTM glue - vmwgfx_ttm_glue.c */ @@ -1311,6 +1324,20 @@ int vmw_host_get_guestinfo(const char *guest_info_param, char *buffer, size_t *length); int vmw_host_log(const char *log); +/* VMW logging */ + +/** + * VMW_DEBUG_USER - Debug output for user-space debugging. + * + * @fmt: printf() like format string. + * + * This macro is for logging user-space error and debugging messages for e.g. + * command buffer execution errors due to malformed commands, invalid context, + * etc. + */ +#define VMW_DEBUG_USER(fmt, ...) \ + DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) + /** * Inline helper functions */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 88b8178d4687..2ff7ba04d8c8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -36,6 +36,25 @@ #define VMW_RES_HT_ORDER 12 /* + * Helper macro to get dx_ctx_node if available otherwise print an error + * message. This is for use in command verifier function where if dx_ctx_node + * is not set then command is invalid. + */ +#define VMW_GET_CTX_NODE(__sw_context) \ +({ \ + __sw_context->dx_ctx_node ? __sw_context->dx_ctx_node : ({ \ + VMW_DEBUG_USER("SM context is not set at %s\n", __func__); \ + __sw_context->dx_ctx_node; \ + }); \ +}) + +#define VMW_DECLARE_CMD_VAR(__var, __type) \ + struct { \ + SVGA3dCmdHeader header; \ + __type body; \ + } __var + +/** * struct vmw_relocation - Buffer object relocation * * @head: List head for the command submission context's relocation list @@ -59,9 +78,8 @@ struct vmw_relocation { * command stream is replaced with the actual id after validation. * @vmw_res_rel_nop: NOP relocation. The command is unconditionally replaced * with a NOP. - * @vmw_res_rel_cond_nop: Conditional NOP relocation. If the resource id - * after validation is -1, the command is replaced with a NOP. Otherwise no - * action. + * @vmw_res_rel_cond_nop: Conditional NOP relocation. If the resource id after + * validation is -1, the command is replaced with a NOP. Otherwise no action. */ enum vmw_resource_relocation_type { vmw_res_rel_normal, @@ -75,8 +93,8 @@ enum vmw_resource_relocation_type { * * @head: List head for the software context's relocation list. * @res: Non-ref-counted pointer to the resource. - * @offset: Offset of single byte entries into the command buffer where the - * id that needs fixup is located. + * @offset: Offset of single byte entries into the command buffer where the id + * that needs fixup is located. * @rel_type: Type of relocation. */ struct vmw_resource_relocation { @@ -86,8 +104,9 @@ struct vmw_resource_relocation { enum vmw_resource_relocation_type rel_type:3; }; -/* +/** * struct vmw_ctx_validation_info - Extra validation metadata for contexts + * * @head: List head of context list * @ctx: The context resource * @cur: The context's persistent binding state @@ -142,9 +161,10 @@ static size_t vmw_ptr_diff(void *a, void *b) /** * vmw_execbuf_bindings_commit - Commit modified binding state + * * @sw_context: The command submission context - * @backoff: Whether this is part of the error path and binding state - * changes should be ignored + * @backoff: Whether this is part of the error path and binding state changes + * should be ignored */ static void vmw_execbuf_bindings_commit(struct vmw_sw_context *sw_context, bool backoff) @@ -154,6 +174,7 @@ static void vmw_execbuf_bindings_commit(struct vmw_sw_context *sw_context, list_for_each_entry(entry, &sw_context->ctx_list, head) { if (!backoff) vmw_binding_state_commit(entry->cur, entry->staged); + if (entry->staged != sw_context->staged_bindings) vmw_binding_state_free(entry->staged); else @@ -166,6 +187,7 @@ static void vmw_execbuf_bindings_commit(struct vmw_sw_context *sw_context, /** * vmw_bind_dx_query_mob - Bind the DX query MOB if referenced + * * @sw_context: The command submission context */ static void vmw_bind_dx_query_mob(struct vmw_sw_context *sw_context) @@ -176,8 +198,8 @@ static void vmw_bind_dx_query_mob(struct vmw_sw_context *sw_context) } /** - * vmw_cmd_ctx_first_setup - Perform the setup needed when a context is - * added to the validate list. + * vmw_cmd_ctx_first_setup - Perform the setup needed when a context is added to + * the validate list. * * @dev_priv: Pointer to the device private: * @sw_context: The command submission context @@ -195,11 +217,8 @@ static int vmw_cmd_ctx_first_setup(struct vmw_private *dev_priv, goto out_err; if (!sw_context->staged_bindings) { - sw_context->staged_bindings = - vmw_binding_state_alloc(dev_priv); + sw_context->staged_bindings = vmw_binding_state_alloc(dev_priv); if (IS_ERR(sw_context->staged_bindings)) { - DRM_ERROR("Failed to allocate context binding " - "information.\n"); ret = PTR_ERR(sw_context->staged_bindings); sw_context->staged_bindings = NULL; goto out_err; @@ -209,8 +228,6 @@ static int vmw_cmd_ctx_first_setup(struct vmw_private *dev_priv, if (sw_context->staged_bindings_inuse) { node->staged = vmw_binding_state_alloc(dev_priv); if (IS_ERR(node->staged)) { - DRM_ERROR("Failed to allocate context binding " - "information.\n"); ret = PTR_ERR(node->staged); node->staged = NULL; goto out_err; @@ -225,19 +242,20 @@ static int vmw_cmd_ctx_first_setup(struct vmw_private *dev_priv, list_add_tail(&node->head, &sw_context->ctx_list); return 0; + out_err: return ret; } /** - * vmw_execbuf_res_size - calculate extra size fore the resource validation - * node + * vmw_execbuf_res_size - calculate extra size fore the resource validation node + * * @dev_priv: Pointer to the device private struct. * @res_type: The resource type. * - * Guest-backed contexts and DX contexts require extra size to store - * execbuf private information in the validation node. Typically the - * binding manager associated data structures. + * Guest-backed contexts and DX contexts require extra size to store execbuf + * private information in the validation node. Typically the binding manager + * associated data structures. * * Returns: The extra size requirement based on resource type. */ @@ -254,8 +272,8 @@ static unsigned int vmw_execbuf_res_size(struct vmw_private *dev_priv, * * @rcache: Pointer to the entry to update. * @res: Pointer to the resource. - * @private: Pointer to the execbuf-private space in the resource - * validation node. + * @private: Pointer to the execbuf-private space in the resource validation + * node. */ static void vmw_execbuf_rcache_update(struct vmw_res_cache_entry *rcache, struct vmw_resource *res, @@ -268,17 +286,19 @@ static void vmw_execbuf_rcache_update(struct vmw_res_cache_entry *rcache, } /** - * vmw_execbuf_res_noref_val_add - Add a resource described by an - * unreferenced rcu-protected pointer to the validation list. + * vmw_execbuf_res_noref_val_add - Add a resource described by an unreferenced + * rcu-protected pointer to the validation list. + * * @sw_context: Pointer to the software context. * @res: Unreferenced rcu-protected pointer to the resource. + * @dirty: Whether to change dirty status. * - * Returns: 0 on success. Negative error code on failure. Typical error - * codes are %-EINVAL on inconsistency and %-ESRCH if the resource was - * doomed. + * Returns: 0 on success. Negative error code on failure. Typical error codes + * are %-EINVAL on inconsistency and %-ESRCH if the resource was doomed. */ static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context, - struct vmw_resource *res) + struct vmw_resource *res, + u32 dirty) { struct vmw_private *dev_priv = res->dev_priv; int ret; @@ -290,13 +310,17 @@ static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context, rcache = &sw_context->res_cache[res_type]; if (likely(rcache->valid && rcache->res == res)) { + if (dirty) + vmw_validation_res_set_dirty(sw_context->ctx, + rcache->private, dirty); vmw_user_resource_noref_release(); return 0; } priv_size = vmw_execbuf_res_size(dev_priv, res_type); ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size, - (void **)&ctx_info, &first_usage); + dirty, (void **)&ctx_info, + &first_usage); vmw_user_resource_noref_release(); if (ret) return ret; @@ -304,8 +328,10 @@ static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context, if (priv_size && first_usage) { ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, res, ctx_info); - if (ret) + if (ret) { + VMW_DEBUG_USER("Failed first usage context setup.\n"); return ret; + } } vmw_execbuf_rcache_update(rcache, res, ctx_info); @@ -315,13 +341,16 @@ static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context, /** * vmw_execbuf_res_noctx_val_add - Add a non-context resource to the resource * validation list if it's not already on it + * * @sw_context: Pointer to the software context. * @res: Pointer to the resource. + * @dirty: Whether to change dirty status. * * Returns: Zero on success. Negative error code on failure. */ static int vmw_execbuf_res_noctx_val_add(struct vmw_sw_context *sw_context, - struct vmw_resource *res) + struct vmw_resource *res, + u32 dirty) { struct vmw_res_cache_entry *rcache; enum vmw_res_type res_type = vmw_res_type(res); @@ -329,10 +358,15 @@ static int vmw_execbuf_res_noctx_val_add(struct vmw_sw_context *sw_context, int ret; rcache = &sw_context->res_cache[res_type]; - if (likely(rcache->valid && rcache->res == res)) + if (likely(rcache->valid && rcache->res == res)) { + if (dirty) + vmw_validation_res_set_dirty(sw_context->ctx, + rcache->private, dirty); return 0; + } - ret = vmw_validation_add_resource(sw_context->ctx, res, 0, &ptr, NULL); + ret = vmw_validation_add_resource(sw_context->ctx, res, 0, dirty, + &ptr, NULL); if (ret) return ret; @@ -342,8 +376,8 @@ static int vmw_execbuf_res_noctx_val_add(struct vmw_sw_context *sw_context, } /** - * vmw_view_res_val_add - Add a view and the surface it's pointing to - * to the validation list + * vmw_view_res_val_add - Add a view and the surface it's pointing to to the + * validation list * * @sw_context: The software context holding the |
