[Intel-gfx] [PATCH] drm/i915: Add soft-pinning API for execbuffer

Daniel, Thomas thomas.daniel at intel.com
Wed Apr 29 06:28:19 PDT 2015


> -----Original Message-----
> From: Intel-gfx [mailto:intel-gfx-bounces at lists.freedesktop.org] On Behalf Of
> Chris Wilson
> Sent: Friday, March 6, 2015 9:44 AM
> To: intel-gfx at lists.freedesktop.org
> Subject: [Intel-gfx] [PATCH] drm/i915: Add soft-pinning API for execbuffer
> 
> Userspace can pass in an offset that it presumes the object is located
> at. The kernel will then do its utmost to fit the object into that
> location. The assumption is that userspace is handling its own object
> locations (for example along with full-ppgtt) and that the kernel will
> rarely have to make space for the user's requests.	
> 
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_drv.h            |  5 +++
>  drivers/gpu/drm/i915/i915_gem.c            | 53 ++++++++++++++++++++++--------
>  drivers/gpu/drm/i915/i915_gem_evict.c      | 52
> +++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  9 ++++-
>  include/uapi/drm/i915_drm.h                |  3 +-
>  5 files changed, 106 insertions(+), 16 deletions(-)
> 

> diff --git a/drivers/gpu/drm/i915/i915_gem.c
> b/drivers/gpu/drm/i915/i915_gem.c
> index 9d0df4d85693..b266b31690e4 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -3592,22 +3592,43 @@ i915_gem_object_bind_to_vm(struct
> drm_i915_gem_object *obj,
>  	if (IS_ERR(vma))
>  		goto err_unpin;
> 
> +	if (flags & PIN_OFFSET_FIXED) {
> +		uint64_t offset = flags & PIN_OFFSET_MASK;
> +		if (offset & (alignment - 1)) {
> +			vma = ERR_PTR(-EINVAL);
> +			goto err_free_vma;
> +		}
> +		vma->node.start = offset;
> +		vma->node.size = size;
> +		vma->node.color = obj->cache_level;
> +		ret = drm_mm_reserve_node(&vm->mm, &vma->node);
> +		if (ret) {
> +			ret = i915_gem_evict_range(dev, vm, start, end);
Did you mean i915_gem_evict_range(dev, vm, offset, offset+size) ?

> +			if (ret == 0)
> +				ret = drm_mm_reserve_node(&vm->mm,
> &vma->node);
> +		}
> +		if (ret) {
> +			vma = ERR_PTR(ret);
> +			goto err_free_vma;
> +		}
> +	} else {
>  search_free:
> -	ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
> -						  size, alignment,
> -						  obj->cache_level,
> -						  start, end,
> -
> DRM_MM_SEARCH_DEFAULT,
> -
> DRM_MM_CREATE_DEFAULT);
> -	if (ret) {
> -		ret = i915_gem_evict_something(dev, vm, size, alignment,
> -					       obj->cache_level,
> -					       start, end,
> -					       flags);
> -		if (ret == 0)
> -			goto search_free;
> +		ret = drm_mm_insert_node_in_range_generic(&vm->mm,
> &vma->node,
> +							  size, alignment,
> +							  obj->cache_level,
> +							  start, end,
> +
> DRM_MM_SEARCH_DEFAULT,
> +
> DRM_MM_CREATE_DEFAULT);
> +		if (ret) {
> +			ret = i915_gem_evict_something(dev, vm, size,
> alignment,
> +						       obj->cache_level,
> +						       start, end,
> +						       flags);
> +			if (ret == 0)
> +				goto search_free;
> 
> -		goto err_free_vma;
> +			goto err_free_vma;
> +		}
>  	}
>  	if (WARN_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level))) {
>  		ret = -EINVAL;

> 
> diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c
> b/drivers/gpu/drm/i915/i915_gem_evict.c
> index e3a49d94da3a..c4b2ead0d805 100644
> --- a/drivers/gpu/drm/i915/i915_gem_evict.c
> +++ b/drivers/gpu/drm/i915/i915_gem_evict.c
> @@ -195,6 +195,58 @@ found:
>  	return ret;
>  }
> 
> +int
> +i915_gem_evict_range(struct drm_device *dev, struct i915_address_space
> *vm,
> +		     unsigned long start, unsigned long end)
> +{
> +	struct drm_mm_node *node;
> +	struct list_head eviction_list;
> +	int ret = 0;
> +
> +	INIT_LIST_HEAD(&eviction_list);
> +	drm_mm_for_each_node(node, &vm->mm) {
> +		struct i915_vma *vma;
> +
> +		if (node->start + node->size <= start)
> +			continue;
> +		if (node->start >= end)
> +			break;
> +
> +		vma = container_of(node, typeof(*vma), node);
> +		if (vma->pin_count) {
> +			ret = -EBUSY;
> +			break;
> +		}
> +
> +		if (WARN_ON(!list_empty(&vma->exec_list))) { 
So if an execbuffer uses both EXEC_OBJECT_PINNED and ordinary buffers in its exec_list then the ordinary buffers cannot be relocated if they are in the range of the pinned buffer.  Was this your intention?

> +			ret = -EINVAL;
> +			break;
> +		}
> +
> +		drm_gem_object_reference(&vma->obj->base);
> +		list_add(&vma->exec_list, &eviction_list);
I guess we need another list_head if we want to support both types of object in the same execbuffer call and allow relocation.

> +	}
> +
> +	while (!list_empty(&eviction_list)) {
> +		struct i915_vma *vma;
> +		struct drm_gem_object *obj;
> +
> +		vma = list_first_entry(&eviction_list,
> +				       struct i915_vma,
> +				       exec_list);
> +
> +		obj = &vma->obj->base;
> +
> +		list_del_init(&vma->exec_list);
> +		if (ret == 0)
> +			ret = i915_vma_unbind(vma);
> +
> +		drm_gem_object_unreference(obj);
> +	}
> +
> +	return ret;
> +}

Useful and worthwhile patch though.  Cheers.
Thomas.
 


More information about the Intel-gfx mailing list