mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	drm/vmwgfx: Make user resource lookups reference-free during validation
Make the process of looking up a user resource and adding it to the validation list reference-free unless when it's actually added to the validation list where a single reference is taken. This saves two locked atomic operations per command stream buffer object handle lookup, unless there is a lookup cache hit. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Sinclair Yeh <syeh@vmware.com>
This commit is contained in:
		
							parent
							
								
									1b9a01d62c
								
							
						
					
					
						commit
						e8c66efbfe
					
				
					 3 changed files with 190 additions and 136 deletions
				
			
		| 
						 | 
					@ -337,8 +337,6 @@ struct vmw_ctx_validation_info;
 | 
				
			||||||
 * @last_query_ctx: Last context that submitted a query
 | 
					 * @last_query_ctx: Last context that submitted a query
 | 
				
			||||||
 * @needs_post_query_barrier: Whether a query barrier is needed after
 | 
					 * @needs_post_query_barrier: Whether a query barrier is needed after
 | 
				
			||||||
 * command submission
 | 
					 * command submission
 | 
				
			||||||
 * @error_resource: Pointer to hold a reference to the resource causing
 | 
					 | 
				
			||||||
 * an error
 | 
					 | 
				
			||||||
 * @staged_bindings: Cached per-context binding tracker
 | 
					 * @staged_bindings: Cached per-context binding tracker
 | 
				
			||||||
 * @staged_bindings_inuse: Whether the cached per-context binding tracker
 | 
					 * @staged_bindings_inuse: Whether the cached per-context binding tracker
 | 
				
			||||||
 * is in use
 | 
					 * is in use
 | 
				
			||||||
| 
						 | 
					@ -365,7 +363,6 @@ struct vmw_sw_context{
 | 
				
			||||||
	struct vmw_res_cache_entry res_cache[vmw_res_max];
 | 
						struct vmw_res_cache_entry res_cache[vmw_res_max];
 | 
				
			||||||
	struct vmw_resource *last_query_ctx;
 | 
						struct vmw_resource *last_query_ctx;
 | 
				
			||||||
	bool needs_post_query_barrier;
 | 
						bool needs_post_query_barrier;
 | 
				
			||||||
	struct vmw_resource *error_resource;
 | 
					 | 
				
			||||||
	struct vmw_ctx_binding_state *staged_bindings;
 | 
						struct vmw_ctx_binding_state *staged_bindings;
 | 
				
			||||||
	bool staged_bindings_inuse;
 | 
						bool staged_bindings_inuse;
 | 
				
			||||||
	struct list_head staged_cmd_res;
 | 
						struct list_head staged_cmd_res;
 | 
				
			||||||
| 
						 | 
					@ -698,6 +695,12 @@ extern int vmw_user_resource_lookup_handle(
 | 
				
			||||||
	uint32_t handle,
 | 
						uint32_t handle,
 | 
				
			||||||
	const struct vmw_user_resource_conv *converter,
 | 
						const struct vmw_user_resource_conv *converter,
 | 
				
			||||||
	struct vmw_resource **p_res);
 | 
						struct vmw_resource **p_res);
 | 
				
			||||||
 | 
					extern struct vmw_resource *
 | 
				
			||||||
 | 
					vmw_user_resource_noref_lookup_handle(struct vmw_private *dev_priv,
 | 
				
			||||||
 | 
									      struct ttm_object_file *tfile,
 | 
				
			||||||
 | 
									      uint32_t handle,
 | 
				
			||||||
 | 
									      const struct vmw_user_resource_conv *
 | 
				
			||||||
 | 
									      converter);
 | 
				
			||||||
extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
 | 
					extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
 | 
				
			||||||
				  struct drm_file *file_priv);
 | 
									  struct drm_file *file_priv);
 | 
				
			||||||
extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
 | 
					extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
 | 
				
			||||||
| 
						 | 
					@ -716,6 +719,15 @@ extern int vmw_query_readback_all(struct vmw_buffer_object *dx_query_mob);
 | 
				
			||||||
extern void vmw_resource_evict_all(struct vmw_private *dev_priv);
 | 
					extern void vmw_resource_evict_all(struct vmw_private *dev_priv);
 | 
				
			||||||
extern void vmw_resource_unbind_list(struct vmw_buffer_object *vbo);
 | 
					extern void vmw_resource_unbind_list(struct vmw_buffer_object *vbo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * vmw_user_resource_noref_release - release a user resource pointer looked up
 | 
				
			||||||
 | 
					 * without reference
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void vmw_user_resource_noref_release(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ttm_base_object_noref_release();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Buffer object helper functions - vmwgfx_bo.c
 | 
					 * Buffer object helper functions - vmwgfx_bo.c
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -230,16 +230,55 @@ static int vmw_cmd_ctx_first_setup(struct vmw_private *dev_priv,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * vmw_resource_val_add - Add a resource to the software context's
 | 
					 * vmw_execbuf_res_size - calculate extra size fore the resource validation
 | 
				
			||||||
 * resource list if it's not already on it.
 | 
					 * node
 | 
				
			||||||
 | 
					 * @dev_priv: Pointer to the device private struct.
 | 
				
			||||||
 | 
					 * @res_type: The resource type.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @sw_context: Pointer to the software context.
 | 
					 * Guest-backed contexts and DX contexts require extra size to store
 | 
				
			||||||
 * @res: Pointer to the resource.
 | 
					 * execbuf private information in the validation node. Typically the
 | 
				
			||||||
 * @p_node On successful return points to a valid pointer to a
 | 
					 * binding manager associated data structures.
 | 
				
			||||||
 * struct vmw_resource_val_node, if non-NULL on entry.
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns: The extra size requirement based on resource type.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int vmw_resource_val_add(struct vmw_sw_context *sw_context,
 | 
					static unsigned int vmw_execbuf_res_size(struct vmw_private *dev_priv,
 | 
				
			||||||
				struct vmw_resource *res)
 | 
										 enum vmw_res_type res_type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (res_type == vmw_res_dx_context ||
 | 
				
			||||||
 | 
							(res_type == vmw_res_context && dev_priv->has_mob)) ?
 | 
				
			||||||
 | 
							sizeof(struct vmw_ctx_validation_info) : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * vmw_execbuf_rcache_update - Update a resource-node cache entry
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @rcache: Pointer to the entry to update.
 | 
				
			||||||
 | 
					 * @res: Pointer to the resource.
 | 
				
			||||||
 | 
					 * @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,
 | 
				
			||||||
 | 
									      void *private)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						rcache->res = res;
 | 
				
			||||||
 | 
						rcache->private = private;
 | 
				
			||||||
 | 
						rcache->valid = 1;
 | 
				
			||||||
 | 
						rcache->valid_handle = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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_private *dev_priv = res->dev_priv;
 | 
						struct vmw_private *dev_priv = res->dev_priv;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -247,18 +286,18 @@ static int vmw_resource_val_add(struct vmw_sw_context *sw_context,
 | 
				
			||||||
	struct vmw_res_cache_entry *rcache;
 | 
						struct vmw_res_cache_entry *rcache;
 | 
				
			||||||
	struct vmw_ctx_validation_info *ctx_info;
 | 
						struct vmw_ctx_validation_info *ctx_info;
 | 
				
			||||||
	bool first_usage;
 | 
						bool first_usage;
 | 
				
			||||||
	size_t priv_size;
 | 
						unsigned int priv_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						rcache = &sw_context->res_cache[res_type];
 | 
				
			||||||
	 * If the resource is a context, set up structures to track
 | 
						if (likely(rcache->valid && rcache->res == res)) {
 | 
				
			||||||
	 * context bindings.
 | 
							vmw_user_resource_noref_release();
 | 
				
			||||||
	 */
 | 
							return 0;
 | 
				
			||||||
	priv_size = (res_type == vmw_res_dx_context ||
 | 
						}
 | 
				
			||||||
		     (res_type == vmw_res_context && dev_priv->has_mob)) ?
 | 
					 | 
				
			||||||
		sizeof(*ctx_info) : 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv_size = vmw_execbuf_res_size(dev_priv, res_type);
 | 
				
			||||||
	ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size,
 | 
						ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size,
 | 
				
			||||||
					  (void **)&ctx_info, &first_usage);
 | 
										  (void **)&ctx_info, &first_usage);
 | 
				
			||||||
 | 
						vmw_user_resource_noref_release();
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -269,14 +308,37 @@ static int vmw_resource_val_add(struct vmw_sw_context *sw_context,
 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Cache info about the last added resource */
 | 
						vmw_execbuf_rcache_update(rcache, res, ctx_info);
 | 
				
			||||||
	rcache = &sw_context->res_cache[res_type];
 | 
						return 0;
 | 
				
			||||||
	rcache->res = res;
 | 
					}
 | 
				
			||||||
	rcache->private = ctx_info;
 | 
					 | 
				
			||||||
	rcache->valid = 1;
 | 
					 | 
				
			||||||
	rcache->valid_handle = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
					/**
 | 
				
			||||||
 | 
					 * 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.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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_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))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = vmw_validation_add_resource(sw_context->ctx, res, 0, &ptr, NULL);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vmw_execbuf_rcache_update(rcache, res, ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -297,11 +359,11 @@ static int vmw_view_res_val_add(struct vmw_sw_context *sw_context,
 | 
				
			||||||
	 * First add the resource the view is pointing to, otherwise
 | 
						 * First add the resource the view is pointing to, otherwise
 | 
				
			||||||
	 * it may be swapped out when the view is validated.
 | 
						 * it may be swapped out when the view is validated.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	ret = vmw_resource_val_add(sw_context, vmw_view_srf(view));
 | 
						ret = vmw_execbuf_res_noctx_val_add(sw_context, vmw_view_srf(view));
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return vmw_resource_val_add(sw_context, view);
 | 
						return vmw_execbuf_res_noctx_val_add(sw_context, view);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -371,7 +433,7 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,
 | 
				
			||||||
			if (IS_ERR(res))
 | 
								if (IS_ERR(res))
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ret = vmw_resource_val_add(sw_context, res);
 | 
								ret = vmw_execbuf_res_noctx_val_add(sw_context, res);
 | 
				
			||||||
			if (unlikely(ret != 0))
 | 
								if (unlikely(ret != 0))
 | 
				
			||||||
				return ret;
 | 
									return ret;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -383,16 +445,11 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,
 | 
				
			||||||
	binding_list = vmw_context_binding_list(ctx);
 | 
						binding_list = vmw_context_binding_list(ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry(entry, binding_list, ctx_list) {
 | 
						list_for_each_entry(entry, binding_list, ctx_list) {
 | 
				
			||||||
		/* entry->res is not refcounted */
 | 
					 | 
				
			||||||
		res = vmw_resource_reference_unless_doomed(entry->res);
 | 
					 | 
				
			||||||
		if (unlikely(res == NULL))
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (vmw_res_type(entry->res) == vmw_res_view)
 | 
							if (vmw_res_type(entry->res) == vmw_res_view)
 | 
				
			||||||
			ret = vmw_view_res_val_add(sw_context, entry->res);
 | 
								ret = vmw_view_res_val_add(sw_context, entry->res);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			ret = vmw_resource_val_add(sw_context, entry->res);
 | 
								ret = vmw_execbuf_res_noctx_val_add(sw_context,
 | 
				
			||||||
		vmw_resource_unreference(&res);
 | 
												    entry->res);
 | 
				
			||||||
		if (unlikely(ret != 0))
 | 
							if (unlikely(ret != 0))
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -534,38 +591,6 @@ static int vmw_resources_reserve(struct vmw_sw_context *sw_context)
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * vmw_cmd_res_reloc_add - Add a resource to a software context's
 | 
					 | 
				
			||||||
 * relocation- and validation lists.
 | 
					 | 
				
			||||||
 * @dev_priv: Pointer to a struct vmw_private identifying the device.
 | 
					 | 
				
			||||||
 * @sw_context: Pointer to the software context.
 | 
					 | 
				
			||||||
 * @id_loc: Pointer to where the id that needs translation is located.
 | 
					 | 
				
			||||||
 * @res: Valid pointer to a struct vmw_resource.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *  Return: Zero on success, negative error code on error
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv,
 | 
					 | 
				
			||||||
				 struct vmw_sw_context *sw_context,
 | 
					 | 
				
			||||||
				 uint32_t *id_loc,
 | 
					 | 
				
			||||||
				 struct vmw_resource *res)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = vmw_resource_relocation_add(sw_context, res,
 | 
					 | 
				
			||||||
					  vmw_ptr_diff(sw_context->buf_start,
 | 
					 | 
				
			||||||
						       id_loc),
 | 
					 | 
				
			||||||
					  vmw_res_rel_normal);
 | 
					 | 
				
			||||||
	if (unlikely(ret != 0))
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = vmw_resource_val_add(sw_context, res);
 | 
					 | 
				
			||||||
	if (unlikely(ret != 0))
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * vmw_cmd_res_check - Check that a resource is present and if so, put it
 | 
					 * vmw_cmd_res_check - Check that a resource is present and if so, put it
 | 
				
			||||||
 * on the resource validate list unless it's already there.
 | 
					 * on the resource validate list unless it's already there.
 | 
				
			||||||
| 
						 | 
					@ -587,8 +612,7 @@ vmw_cmd_res_check(struct vmw_private *dev_priv,
 | 
				
			||||||
		  uint32_t *id_loc,
 | 
							  uint32_t *id_loc,
 | 
				
			||||||
		  struct vmw_resource **p_res)
 | 
							  struct vmw_resource **p_res)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct vmw_res_cache_entry *rcache =
 | 
						struct vmw_res_cache_entry *rcache = &sw_context->res_cache[res_type];
 | 
				
			||||||
		&sw_context->res_cache[res_type];
 | 
					 | 
				
			||||||
	struct vmw_resource *res;
 | 
						struct vmw_resource *res;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -603,56 +627,41 @@ vmw_cmd_res_check(struct vmw_private *dev_priv,
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Fastpath in case of repeated commands referencing the same
 | 
					 | 
				
			||||||
	 * resource
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (likely(rcache->valid_handle && *id_loc == rcache->handle)) {
 | 
						if (likely(rcache->valid_handle && *id_loc == rcache->handle)) {
 | 
				
			||||||
		struct vmw_resource *res = rcache->res;
 | 
							res = rcache->res;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							unsigned int size = vmw_execbuf_res_size(dev_priv, res_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (p_res)
 | 
							ret = vmw_validation_preload_res(sw_context->ctx, size);
 | 
				
			||||||
			*p_res = res;
 | 
							if (ret)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return vmw_resource_relocation_add
 | 
							res = vmw_user_resource_noref_lookup_handle
 | 
				
			||||||
			(sw_context, res,
 | 
								(dev_priv, sw_context->fp->tfile, *id_loc, converter);
 | 
				
			||||||
			 vmw_ptr_diff(sw_context->buf_start, id_loc),
 | 
							if (unlikely(IS_ERR(res))) {
 | 
				
			||||||
			 vmw_res_rel_normal);
 | 
								DRM_ERROR("Could not find or use resource 0x%08x.\n",
 | 
				
			||||||
 | 
									  (unsigned int) *id_loc);
 | 
				
			||||||
 | 
								return PTR_ERR(res);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ret = vmw_execbuf_res_noref_val_add(sw_context, res);
 | 
				
			||||||
 | 
							if (unlikely(ret != 0))
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (rcache->valid && rcache->res == res) {
 | 
				
			||||||
 | 
								rcache->valid_handle = true;
 | 
				
			||||||
 | 
								rcache->handle = *id_loc;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = vmw_user_resource_lookup_handle(dev_priv,
 | 
						ret = vmw_resource_relocation_add(sw_context, res,
 | 
				
			||||||
					      sw_context->fp->tfile,
 | 
										  vmw_ptr_diff(sw_context->buf_start,
 | 
				
			||||||
					      *id_loc,
 | 
											       id_loc),
 | 
				
			||||||
					      converter,
 | 
										  vmw_res_rel_normal);
 | 
				
			||||||
					      &res);
 | 
					 | 
				
			||||||
	if (unlikely(ret != 0)) {
 | 
					 | 
				
			||||||
		DRM_ERROR("Could not find or use resource 0x%08x.\n",
 | 
					 | 
				
			||||||
			  (unsigned) *id_loc);
 | 
					 | 
				
			||||||
		dump_stack();
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = vmw_cmd_res_reloc_add(dev_priv, sw_context, id_loc,
 | 
					 | 
				
			||||||
				    res);
 | 
					 | 
				
			||||||
	if (unlikely(ret != 0))
 | 
					 | 
				
			||||||
		goto out_no_reloc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (p_res)
 | 
						if (p_res)
 | 
				
			||||||
		*p_res = res;
 | 
							*p_res = res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (rcache->valid && rcache->res == res) {
 | 
					 | 
				
			||||||
		rcache->valid_handle = true;
 | 
					 | 
				
			||||||
		rcache->handle = *id_loc;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	vmw_resource_unreference(&res);
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					 | 
				
			||||||
out_no_reloc:
 | 
					 | 
				
			||||||
	BUG_ON(sw_context->error_resource != NULL);
 | 
					 | 
				
			||||||
	sw_context->error_resource = res;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -854,9 +863,9 @@ static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
 | 
						ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
 | 
				
			||||||
				user_surface_converter,
 | 
									user_surface_converter, &cmd->body.target.sid,
 | 
				
			||||||
				&cmd->body.target.sid, &res);
 | 
									&res);
 | 
				
			||||||
	if (unlikely(ret != 0))
 | 
						if (unlikely(ret))
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dev_priv->has_mob) {
 | 
						if (dev_priv->has_mob) {
 | 
				
			||||||
| 
						 | 
					@ -890,8 +899,8 @@ static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
 | 
				
			||||||
	cmd = container_of(header, struct vmw_sid_cmd, header);
 | 
						cmd = container_of(header, struct vmw_sid_cmd, header);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
 | 
						ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
 | 
				
			||||||
				user_surface_converter,
 | 
										  user_surface_converter,
 | 
				
			||||||
				&cmd->body.src.sid, NULL);
 | 
										  &cmd->body.src.sid, NULL);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2127,8 +2136,7 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
 | 
				
			||||||
					cmd->body.type);
 | 
										cmd->body.type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!IS_ERR(res)) {
 | 
							if (!IS_ERR(res)) {
 | 
				
			||||||
			ret = vmw_cmd_res_reloc_add(dev_priv, sw_context,
 | 
								ret = vmw_execbuf_res_noctx_val_add(sw_context, res);
 | 
				
			||||||
						    &cmd->body.shid, res);
 | 
					 | 
				
			||||||
			if (unlikely(ret != 0))
 | 
								if (unlikely(ret != 0))
 | 
				
			||||||
				return ret;
 | 
									return ret;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -2345,7 +2353,7 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv,
 | 
				
			||||||
			return PTR_ERR(res);
 | 
								return PTR_ERR(res);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = vmw_resource_val_add(sw_context, res);
 | 
							ret = vmw_execbuf_res_noctx_val_add(sw_context, res);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -2883,13 +2891,12 @@ static int vmw_cmd_dx_bind_shader(struct vmw_private *dev_priv,
 | 
				
			||||||
		return PTR_ERR(res);
 | 
							return PTR_ERR(res);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = vmw_resource_val_add(sw_context, res);
 | 
						ret = vmw_execbuf_res_noctx_val_add(sw_context, res);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		DRM_ERROR("Error creating resource validation node.\n");
 | 
							DRM_ERROR("Error creating resource validation node.\n");
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return vmw_cmd_res_switch_backup(dev_priv, sw_context, res,
 | 
						return vmw_cmd_res_switch_backup(dev_priv, sw_context, res,
 | 
				
			||||||
					 &cmd->body.mobid,
 | 
										 &cmd->body.mobid,
 | 
				
			||||||
					 cmd->body.offsetInBytes);
 | 
										 cmd->body.offsetInBytes);
 | 
				
			||||||
| 
						 | 
					@ -3781,28 +3788,33 @@ static int vmw_execbuf_tie_context(struct vmw_private *dev_priv,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct vmw_resource *res;
 | 
						struct vmw_resource *res;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
						unsigned int size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (handle == SVGA3D_INVALID_ID)
 | 
						if (handle == SVGA3D_INVALID_ID)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = vmw_user_resource_lookup_handle(dev_priv, sw_context->fp->tfile,
 | 
						size = vmw_execbuf_res_size(dev_priv, vmw_res_dx_context);
 | 
				
			||||||
					      handle, user_context_converter,
 | 
						ret = vmw_validation_preload_res(sw_context->ctx, size);
 | 
				
			||||||
					      &res);
 | 
						if (ret)
 | 
				
			||||||
	if (unlikely(ret != 0)) {
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						res = vmw_user_resource_noref_lookup_handle
 | 
				
			||||||
 | 
							(dev_priv, sw_context->fp->tfile, handle,
 | 
				
			||||||
 | 
							 user_context_converter);
 | 
				
			||||||
 | 
						if (unlikely(IS_ERR(res))) {
 | 
				
			||||||
		DRM_ERROR("Could not find or user DX context 0x%08x.\n",
 | 
							DRM_ERROR("Could not find or user DX context 0x%08x.\n",
 | 
				
			||||||
			  (unsigned) handle);
 | 
								  (unsigned) handle);
 | 
				
			||||||
		return ret;
 | 
							return PTR_ERR(res);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = vmw_resource_val_add(sw_context, res);
 | 
						ret = vmw_execbuf_res_noref_val_add(sw_context, res);
 | 
				
			||||||
	if (unlikely(ret != 0))
 | 
						if (unlikely(ret != 0))
 | 
				
			||||||
		goto out_err;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sw_context->dx_ctx_node = vmw_execbuf_info_from_res(sw_context, res);
 | 
						sw_context->dx_ctx_node = vmw_execbuf_info_from_res(sw_context, res);
 | 
				
			||||||
	sw_context->man = vmw_context_res_man(res);
 | 
						sw_context->man = vmw_context_res_man(res);
 | 
				
			||||||
out_err:
 | 
					
 | 
				
			||||||
	vmw_resource_unreference(&res);
 | 
						return 0;
 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int vmw_execbuf_process(struct drm_file *file_priv,
 | 
					int vmw_execbuf_process(struct drm_file *file_priv,
 | 
				
			||||||
| 
						 | 
					@ -3818,7 +3830,6 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct vmw_sw_context *sw_context = &dev_priv->ctx;
 | 
						struct vmw_sw_context *sw_context = &dev_priv->ctx;
 | 
				
			||||||
	struct vmw_fence_obj *fence = NULL;
 | 
						struct vmw_fence_obj *fence = NULL;
 | 
				
			||||||
	struct vmw_resource *error_resource;
 | 
					 | 
				
			||||||
	struct vmw_cmdbuf_header *header;
 | 
						struct vmw_cmdbuf_header *header;
 | 
				
			||||||
	uint32_t handle;
 | 
						uint32_t handle;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -4028,8 +4039,6 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 | 
				
			||||||
		     !dev_priv->query_cid_valid))
 | 
							     !dev_priv->query_cid_valid))
 | 
				
			||||||
		__vmw_execbuf_release_pinned_bo(dev_priv, NULL);
 | 
							__vmw_execbuf_release_pinned_bo(dev_priv, NULL);
 | 
				
			||||||
out_unlock:
 | 
					out_unlock:
 | 
				
			||||||
	error_resource = sw_context->error_resource;
 | 
					 | 
				
			||||||
	sw_context->error_resource = NULL;
 | 
					 | 
				
			||||||
	vmw_cmdbuf_res_revert(&sw_context->staged_cmd_res);
 | 
						vmw_cmdbuf_res_revert(&sw_context->staged_cmd_res);
 | 
				
			||||||
	vmw_validation_drop_ht(&val_ctx);
 | 
						vmw_validation_drop_ht(&val_ctx);
 | 
				
			||||||
	WARN_ON(!list_empty(&sw_context->ctx_list));
 | 
						WARN_ON(!list_empty(&sw_context->ctx_list));
 | 
				
			||||||
| 
						 | 
					@ -4040,8 +4049,6 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 | 
				
			||||||
	 * avoid deadlocks in resource destruction paths.
 | 
						 * avoid deadlocks in resource destruction paths.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	vmw_validation_unref_lists(&val_ctx);
 | 
						vmw_validation_unref_lists(&val_ctx);
 | 
				
			||||||
	if (unlikely(error_resource != NULL))
 | 
					 | 
				
			||||||
		vmw_resource_unreference(&error_resource);
 | 
					 | 
				
			||||||
out_free_header:
 | 
					out_free_header:
 | 
				
			||||||
	if (header)
 | 
						if (header)
 | 
				
			||||||
		vmw_cmdbuf_header_free(header);
 | 
							vmw_cmdbuf_header_free(header);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -230,6 +230,41 @@ int vmw_user_resource_lookup_handle(struct vmw_private *dev_priv,
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * vmw_user_resource_lookup_handle - lookup a struct resource from a
 | 
				
			||||||
 | 
					 * TTM user-space handle and perform basic type checks
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @dev_priv:     Pointer to a device private struct
 | 
				
			||||||
 | 
					 * @tfile:        Pointer to a struct ttm_object_file identifying the caller
 | 
				
			||||||
 | 
					 * @handle:       The TTM user-space handle
 | 
				
			||||||
 | 
					 * @converter:    Pointer to an object describing the resource type
 | 
				
			||||||
 | 
					 * @p_res:        On successful return the location pointed to will contain
 | 
				
			||||||
 | 
					 *                a pointer to a refcounted struct vmw_resource.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If the handle can't be found or is associated with an incorrect resource
 | 
				
			||||||
 | 
					 * type, -EINVAL will be returned.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct vmw_resource *
 | 
				
			||||||
 | 
					vmw_user_resource_noref_lookup_handle(struct vmw_private *dev_priv,
 | 
				
			||||||
 | 
									      struct ttm_object_file *tfile,
 | 
				
			||||||
 | 
									      uint32_t handle,
 | 
				
			||||||
 | 
									      const struct vmw_user_resource_conv
 | 
				
			||||||
 | 
									      *converter)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ttm_base_object *base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						base = ttm_base_object_noref_lookup(tfile, handle);
 | 
				
			||||||
 | 
						if (!base)
 | 
				
			||||||
 | 
							return ERR_PTR(-ESRCH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (unlikely(ttm_base_object_type(base) != converter->object_type)) {
 | 
				
			||||||
 | 
							ttm_base_object_noref_release();
 | 
				
			||||||
 | 
							return ERR_PTR(-EINVAL);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return converter->base_obj_to_res(base);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Helper function that looks either a surface or bo.
 | 
					 * Helper function that looks either a surface or bo.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue