diff mbox

[2/3] drm/i915: Preallocate the drm_mm_node prior to manipulating the GTT drm_mm manager

Message ID 1354912628-7776-2-git-send-email-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Wilson Dec. 7, 2012, 8:37 p.m. UTC
As we may reap neighbouring objects in order to free up pages for
allocations, we need to be careful not to allocate in the middle of the
drm_mm manager. To accomplish this, we can simply allocate the
drm_mm_node up front and then use the combined search & insert
drm_mm routines, reducing our code footprint in the process.

Fixes (partially) i-g-t/gem_tiled_swapping

Reported-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem.c |   64 +++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 37 deletions(-)

Comments

Jani Nikula Dec. 12, 2012, 10:18 a.m. UTC | #1
On Fri, 07 Dec 2012, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> As we may reap neighbouring objects in order to free up pages for
> allocations, we need to be careful not to allocate in the middle of the
> drm_mm manager. To accomplish this, we can simply allocate the
> drm_mm_node up front and then use the combined search & insert
> drm_mm routines, reducing our code footprint in the process.
>
> Fixes (partially) i-g-t/gem_tiled_swapping
>
> Reported-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_gem.c |   64 +++++++++++++++++----------------------
>  1 file changed, 27 insertions(+), 37 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index c1f6919..d17f52d 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -2890,7 +2890,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
>  {
>  	struct drm_device *dev = obj->base.dev;
>  	drm_i915_private_t *dev_priv = dev->dev_private;
> -	struct drm_mm_node *free_space;
> +	struct drm_mm_node *node;
>  	u32 size, fence_size, fence_alignment, unfenced_alignment;
>  	bool mappable, fenceable;
>  	int ret;
> @@ -2936,66 +2936,56 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
>  
>  	i915_gem_object_pin_pages(obj);
>  
> +	node = kzalloc(sizeof(*node), GFP_KERNEL);
> +	if (node == NULL) {
> +		i915_gem_object_unpin_pages(obj);
> +		return -ENOMEM;
> +	}

Any reason not to do the kzalloc before i915_gem_object_pin_pages, with
a slight simplification of the error path there?

Otherwise, with the disclaimer that I'm a newbie in drm mm,

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


> +
>   search_free:
>  	if (map_and_fenceable)
> -		free_space = drm_mm_search_free_in_range_color(&dev_priv->mm.gtt_space,
> -							       size, alignment, obj->cache_level,
> -							       0, dev_priv->mm.gtt_mappable_end,
> -							       false);
> +		ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, node,
> +							  size, alignment, obj->cache_level,
> +							  0, dev_priv->mm.gtt_mappable_end,
> +							  false);
>  	else
> -		free_space = drm_mm_search_free_color(&dev_priv->mm.gtt_space,
> -						      size, alignment, obj->cache_level,
> -						      false);
> -
> -	if (free_space != NULL) {
> -		if (map_and_fenceable)
> -			free_space =
> -				drm_mm_get_block_range_generic(free_space,
> -							       size, alignment, obj->cache_level,
> -							       0, dev_priv->mm.gtt_mappable_end,
> -							       false);
> -		else
> -			free_space =
> -				drm_mm_get_block_generic(free_space,
> -							 size, alignment, obj->cache_level,
> -							 false);
> -	}
> -	if (free_space == NULL) {
> +		ret = drm_mm_insert_node_generic(&dev_priv->mm.gtt_space, node,
> +						 size, alignment, obj->cache_level,
> +						 false);
> +	if (ret) {
>  		ret = i915_gem_evict_something(dev, size, alignment,
>  					       obj->cache_level,
>  					       map_and_fenceable,
>  					       nonblocking);
> -		if (ret) {
> -			i915_gem_object_unpin_pages(obj);
> -			return ret;
> -		}
> +		if (ret == 0)
> +			goto search_free;
>  
> -		goto search_free;
> +		i915_gem_object_unpin_pages(obj);
> +		kfree(node);
> +		return ret;
>  	}
> -	if (WARN_ON(!i915_gem_valid_gtt_space(dev,
> -					      free_space,
> -					      obj->cache_level))) {
> +	if (WARN_ON(!i915_gem_valid_gtt_space(dev, node, obj->cache_level))) {
>  		i915_gem_object_unpin_pages(obj);
> -		drm_mm_put_block(free_space);
> +		drm_mm_put_block(node);
>  		return -EINVAL;
>  	}
>  
>  	ret = i915_gem_gtt_prepare_object(obj);
>  	if (ret) {
>  		i915_gem_object_unpin_pages(obj);
> -		drm_mm_put_block(free_space);
> +		drm_mm_put_block(node);
>  		return ret;
>  	}
>  
>  	list_move_tail(&obj->gtt_list, &dev_priv->mm.bound_list);
>  	list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
>  
> -	obj->gtt_space = free_space;
> -	obj->gtt_offset = free_space->start;
> +	obj->gtt_space = node;
> +	obj->gtt_offset = node->start;
>  
>  	fenceable =
> -		free_space->size == fence_size &&
> -		(free_space->start & (fence_alignment - 1)) == 0;
> +		node->size == fence_size &&
> +		(node->start & (fence_alignment - 1)) == 0;
>  
>  	mappable =
>  		obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end;
> -- 
> 1.7.10.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Chris Wilson Dec. 12, 2012, 10:27 a.m. UTC | #2
On Wed, 12 Dec 2012 12:18:35 +0200, Jani Nikula <jani.nikula@linux.intel.com> wrote:
> On Fri, 07 Dec 2012, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> > As we may reap neighbouring objects in order to free up pages for
> > allocations, we need to be careful not to allocate in the middle of the
> > drm_mm manager. To accomplish this, we can simply allocate the
> > drm_mm_node up front and then use the combined search & insert
> > drm_mm routines, reducing our code footprint in the process.
> >
> > Fixes (partially) i-g-t/gem_tiled_swapping
> >
> > Reported-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> > ---
> >  drivers/gpu/drm/i915/i915_gem.c |   64 +++++++++++++++++----------------------
> >  1 file changed, 27 insertions(+), 37 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> > index c1f6919..d17f52d 100644
> > --- a/drivers/gpu/drm/i915/i915_gem.c
> > +++ b/drivers/gpu/drm/i915/i915_gem.c
> > @@ -2890,7 +2890,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
> >  {
> >  	struct drm_device *dev = obj->base.dev;
> >  	drm_i915_private_t *dev_priv = dev->dev_private;
> > -	struct drm_mm_node *free_space;
> > +	struct drm_mm_node *node;
> >  	u32 size, fence_size, fence_alignment, unfenced_alignment;
> >  	bool mappable, fenceable;
> >  	int ret;
> > @@ -2936,66 +2936,56 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
> >  
> >  	i915_gem_object_pin_pages(obj);
> >  
> > +	node = kzalloc(sizeof(*node), GFP_KERNEL);
> > +	if (node == NULL) {
> > +		i915_gem_object_unpin_pages(obj);
> > +		return -ENOMEM;
> > +	}
> 
> Any reason not to do the kzalloc before i915_gem_object_pin_pages, with
> a slight simplification of the error path there?

No reason at all. In my defense, I was trying to make the code as similar
as possible...
-Chris
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index c1f6919..d17f52d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2890,7 +2890,7 @@  i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 {
 	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_mm_node *free_space;
+	struct drm_mm_node *node;
 	u32 size, fence_size, fence_alignment, unfenced_alignment;
 	bool mappable, fenceable;
 	int ret;
@@ -2936,66 +2936,56 @@  i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 
 	i915_gem_object_pin_pages(obj);
 
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
+	if (node == NULL) {
+		i915_gem_object_unpin_pages(obj);
+		return -ENOMEM;
+	}
+
  search_free:
 	if (map_and_fenceable)
-		free_space = drm_mm_search_free_in_range_color(&dev_priv->mm.gtt_space,
-							       size, alignment, obj->cache_level,
-							       0, dev_priv->mm.gtt_mappable_end,
-							       false);
+		ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, node,
+							  size, alignment, obj->cache_level,
+							  0, dev_priv->mm.gtt_mappable_end,
+							  false);
 	else
-		free_space = drm_mm_search_free_color(&dev_priv->mm.gtt_space,
-						      size, alignment, obj->cache_level,
-						      false);
-
-	if (free_space != NULL) {
-		if (map_and_fenceable)
-			free_space =
-				drm_mm_get_block_range_generic(free_space,
-							       size, alignment, obj->cache_level,
-							       0, dev_priv->mm.gtt_mappable_end,
-							       false);
-		else
-			free_space =
-				drm_mm_get_block_generic(free_space,
-							 size, alignment, obj->cache_level,
-							 false);
-	}
-	if (free_space == NULL) {
+		ret = drm_mm_insert_node_generic(&dev_priv->mm.gtt_space, node,
+						 size, alignment, obj->cache_level,
+						 false);
+	if (ret) {
 		ret = i915_gem_evict_something(dev, size, alignment,
 					       obj->cache_level,
 					       map_and_fenceable,
 					       nonblocking);
-		if (ret) {
-			i915_gem_object_unpin_pages(obj);
-			return ret;
-		}
+		if (ret == 0)
+			goto search_free;
 
-		goto search_free;
+		i915_gem_object_unpin_pages(obj);
+		kfree(node);
+		return ret;
 	}
-	if (WARN_ON(!i915_gem_valid_gtt_space(dev,
-					      free_space,
-					      obj->cache_level))) {
+	if (WARN_ON(!i915_gem_valid_gtt_space(dev, node, obj->cache_level))) {
 		i915_gem_object_unpin_pages(obj);
-		drm_mm_put_block(free_space);
+		drm_mm_put_block(node);
 		return -EINVAL;
 	}
 
 	ret = i915_gem_gtt_prepare_object(obj);
 	if (ret) {
 		i915_gem_object_unpin_pages(obj);
-		drm_mm_put_block(free_space);
+		drm_mm_put_block(node);
 		return ret;
 	}
 
 	list_move_tail(&obj->gtt_list, &dev_priv->mm.bound_list);
 	list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
 
-	obj->gtt_space = free_space;
-	obj->gtt_offset = free_space->start;
+	obj->gtt_space = node;
+	obj->gtt_offset = node->start;
 
 	fenceable =
-		free_space->size == fence_size &&
-		(free_space->start & (fence_alignment - 1)) == 0;
+		node->size == fence_size &&
+		(node->start & (fence_alignment - 1)) == 0;
 
 	mappable =
 		obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end;