diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c')
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 176 | 
1 files changed, 82 insertions, 94 deletions
| diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index a5379f6fb5ab..a44d53e33cdb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -290,20 +290,26 @@ static void vmw_execbuf_rcache_update(struct vmw_res_cache_entry *rcache,  	rcache->valid_handle = 0;  } +enum vmw_val_add_flags { +	vmw_val_add_flag_none  =      0, +	vmw_val_add_flag_noctx = 1 << 0, +}; +  /** - * vmw_execbuf_res_noref_val_add - Add a resource described by an unreferenced - * rcu-protected pointer to the validation list. + * vmw_execbuf_res_val_add - Add a resource 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. + * @flags: specifies whether to use the context or not   *   * 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, -					 u32 dirty) +static int vmw_execbuf_res_val_add(struct vmw_sw_context *sw_context, +				   struct vmw_resource *res, +				   u32 dirty, +				   u32 flags)  {  	struct vmw_private *dev_priv = res->dev_priv;  	int ret; @@ -318,24 +324,30 @@ static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context,  		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, -					  dirty, (void **)&ctx_info, -					  &first_usage); -	vmw_user_resource_noref_release(); -	if (ret) -		return ret; +	if ((flags & vmw_val_add_flag_noctx) != 0) { +		ret = vmw_validation_add_resource(sw_context->ctx, res, 0, dirty, +						  (void **)&ctx_info, NULL); +		if (ret) +			return ret; -	if (priv_size && first_usage) { -		ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, res, -					      ctx_info); -		if (ret) { -			VMW_DEBUG_USER("Failed first usage context setup.\n"); +	} else { +		priv_size = vmw_execbuf_res_size(dev_priv, res_type); +		ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size, +						  dirty, (void **)&ctx_info, +						  &first_usage); +		if (ret)  			return ret; + +		if (priv_size && first_usage) { +			ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, res, +						      ctx_info); +			if (ret) { +				VMW_DEBUG_USER("Failed first usage context setup.\n"); +				return ret; +			}  		}  	} @@ -344,43 +356,6 @@ 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, -					 u32 dirty) -{ -	struct vmw_res_cache_entry *rcache; -	enum vmw_res_type res_type = vmw_res_type(res); -	void *ptr; -	int ret; - -	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); -		return 0; -	} - -	ret = vmw_validation_add_resource(sw_context->ctx, res, 0, dirty, -					  &ptr, NULL); -	if (ret) -		return ret; - -	vmw_execbuf_rcache_update(rcache, res, ptr); - -	return 0; -} - -/**   * vmw_view_res_val_add - Add a view and the surface it's pointing to to the   * validation list   * @@ -398,13 +373,13 @@ static int vmw_view_res_val_add(struct vmw_sw_context *sw_context,  	 * First add the resource the view is pointing to, otherwise it may be  	 * swapped out when the view is validated.  	 */ -	ret = vmw_execbuf_res_noctx_val_add(sw_context, vmw_view_srf(view), -					    vmw_view_dirtying(view)); +	ret = vmw_execbuf_res_val_add(sw_context, vmw_view_srf(view), +				      vmw_view_dirtying(view), vmw_val_add_flag_noctx);  	if (ret)  		return ret; -	return vmw_execbuf_res_noctx_val_add(sw_context, view, -					     VMW_RES_DIRTY_NONE); +	return vmw_execbuf_res_val_add(sw_context, view, VMW_RES_DIRTY_NONE, +				       vmw_val_add_flag_noctx);  }  /** @@ -475,8 +450,9 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,  			if (IS_ERR(res))  				continue; -			ret = vmw_execbuf_res_noctx_val_add(sw_context, res, -							    VMW_RES_DIRTY_SET); +			ret = vmw_execbuf_res_val_add(sw_context, res, +						      VMW_RES_DIRTY_SET, +						      vmw_val_add_flag_noctx);  			if (unlikely(ret != 0))  				return ret;  		} @@ -490,9 +466,9 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,  		if (vmw_res_type(entry->res) == vmw_res_view)  			ret = vmw_view_res_val_add(sw_context, entry->res);  		else -			ret = vmw_execbuf_res_noctx_val_add -				(sw_context, entry->res, -				 vmw_binding_dirtying(entry->bt)); +			ret = vmw_execbuf_res_val_add(sw_context, entry->res, +						      vmw_binding_dirtying(entry->bt), +						      vmw_val_add_flag_noctx);  		if (unlikely(ret != 0))  			break;  	} @@ -658,7 +634,8 @@ vmw_cmd_res_check(struct vmw_private *dev_priv,  {  	struct vmw_res_cache_entry *rcache = &sw_context->res_cache[res_type];  	struct vmw_resource *res; -	int ret; +	int ret = 0; +	bool needs_unref = false;  	if (p_res)  		*p_res = NULL; @@ -683,17 +660,18 @@ vmw_cmd_res_check(struct vmw_private *dev_priv,  		if (ret)  			return ret; -		res = vmw_user_resource_noref_lookup_handle -			(dev_priv, sw_context->fp->tfile, *id_loc, converter); -		if (IS_ERR(res)) { +		ret = vmw_user_resource_lookup_handle +			(dev_priv, sw_context->fp->tfile, *id_loc, converter, &res); +		if (ret != 0) {  			VMW_DEBUG_USER("Could not find/use resource 0x%08x.\n",  				       (unsigned int) *id_loc); -			return PTR_ERR(res); +			return ret;  		} +		needs_unref = true; -		ret = vmw_execbuf_res_noref_val_add(sw_context, res, dirty); +		ret = vmw_execbuf_res_val_add(sw_context, res, dirty, vmw_val_add_flag_none);  		if (unlikely(ret != 0)) -			return ret; +			goto res_check_done;  		if (rcache->valid && rcache->res == res) {  			rcache->valid_handle = true; @@ -708,7 +686,11 @@ vmw_cmd_res_check(struct vmw_private *dev_priv,  	if (p_res)  		*p_res = res; -	return 0; +res_check_done: +	if (needs_unref) +		vmw_resource_unreference(&res); + +	return ret;  }  /** @@ -1171,9 +1153,9 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,  	int ret;  	vmw_validation_preload_bo(sw_context->ctx); -	vmw_bo = vmw_user_bo_noref_lookup(sw_context->filp, handle); -	if (IS_ERR(vmw_bo)) { -		VMW_DEBUG_USER("Could not find or use MOB buffer.\n"); +	ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo); +	if (ret != 0) { +		drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n");  		return PTR_ERR(vmw_bo);  	}  	ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false); @@ -1225,9 +1207,9 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,  	int ret;  	vmw_validation_preload_bo(sw_context->ctx); -	vmw_bo = vmw_user_bo_noref_lookup(sw_context->filp, handle); -	if (IS_ERR(vmw_bo)) { -		VMW_DEBUG_USER("Could not find or use GMR region.\n"); +	ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo); +	if (ret != 0) { +		drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n");  		return PTR_ERR(vmw_bo);  	}  	ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false); @@ -2025,8 +2007,9 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,  		res = vmw_shader_lookup(vmw_context_res_man(ctx),  					cmd->body.shid, cmd->body.type);  		if (!IS_ERR(res)) { -			ret = vmw_execbuf_res_noctx_val_add(sw_context, res, -							    VMW_RES_DIRTY_NONE); +			ret = vmw_execbuf_res_val_add(sw_context, res, +						      VMW_RES_DIRTY_NONE, +						      vmw_val_add_flag_noctx);  			if (unlikely(ret != 0))  				return ret; @@ -2273,8 +2256,9 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv,  			return PTR_ERR(res);  		} -		ret = vmw_execbuf_res_noctx_val_add(sw_context, res, -						    VMW_RES_DIRTY_NONE); +		ret = vmw_execbuf_res_val_add(sw_context, res, +					      VMW_RES_DIRTY_NONE, +					      vmw_val_add_flag_noctx);  		if (ret)  			return ret;  	} @@ -2777,8 +2761,8 @@ static int vmw_cmd_dx_bind_shader(struct vmw_private *dev_priv,  		return PTR_ERR(res);  	} -	ret = vmw_execbuf_res_noctx_val_add(sw_context, res, -					    VMW_RES_DIRTY_NONE); +	ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE, +				      vmw_val_add_flag_noctx);  	if (ret) {  		VMW_DEBUG_USER("Error creating resource validation node.\n");  		return ret; @@ -3098,8 +3082,8 @@ static int vmw_cmd_dx_bind_streamoutput(struct vmw_private *dev_priv,  	vmw_dx_streamoutput_set_size(res, cmd->body.sizeInBytes); -	ret = vmw_execbuf_res_noctx_val_add(sw_context, res, -					    VMW_RES_DIRTY_NONE); +	ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE, +				      vmw_val_add_flag_noctx);  	if (ret) {  		DRM_ERROR("Error creating resource validation node.\n");  		return ret; @@ -3148,8 +3132,8 @@ static int vmw_cmd_dx_set_streamoutput(struct vmw_private *dev_priv,  		return 0;  	} -	ret = vmw_execbuf_res_noctx_val_add(sw_context, res, -					    VMW_RES_DIRTY_NONE); +	ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE, +				      vmw_val_add_flag_noctx);  	if (ret) {  		DRM_ERROR("Error creating resource validation node.\n");  		return ret; @@ -4066,22 +4050,26 @@ static int vmw_execbuf_tie_context(struct vmw_private *dev_priv,  	if (ret)  		return ret; -	res = vmw_user_resource_noref_lookup_handle +	ret = vmw_user_resource_lookup_handle  		(dev_priv, sw_context->fp->tfile, handle, -		 user_context_converter); -	if (IS_ERR(res)) { +		 user_context_converter, &res); +	if (ret != 0) {  		VMW_DEBUG_USER("Could not find or user DX context 0x%08x.\n",  			       (unsigned int) handle); -		return PTR_ERR(res); +		return ret;  	} -	ret = vmw_execbuf_res_noref_val_add(sw_context, res, VMW_RES_DIRTY_SET); -	if (unlikely(ret != 0)) +	ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_SET, +				      vmw_val_add_flag_none); +	if (unlikely(ret != 0)) { +		vmw_resource_unreference(&res);  		return ret; +	}  	sw_context->dx_ctx_node = vmw_execbuf_info_from_res(sw_context, res);  	sw_context->man = vmw_context_res_man(res); +	vmw_resource_unreference(&res);  	return 0;  } |