diff options
| author | Eric Anholt <eric@anholt.net> | 2008-05-20 10:48:36 -0700 | 
|---|---|---|
| committer | Eric Anholt <eric@anholt.net> | 2008-05-20 10:52:39 -0700 | 
| commit | 6c3ac484b049681f9f3e692f9a6238ed122a8191 (patch) | |
| tree | 5cbe0ca9b9bc234ef7a0fa503d312ff5d0d6fad6 | |
| parent | 7dced2f33a952ad12aafb7a3e34747156020a3ae (diff) | |
[gem] Clean up active/inactive list handling using helper functions.
Additionally, a boolean active field is added to indicate which list an
object is on, rather than smashing last_rendering_cookie to 0 to show
inactive.  This will help with flush-reduction later on, and makes the code
clearer.
| -rw-r--r-- | linux-core/i915_gem.c | 80 | ||||
| -rw-r--r-- | shared-core/i915_drv.h | 18 | 
2 files changed, 61 insertions, 37 deletions
| diff --git a/linux-core/i915_gem.c b/linux-core/i915_gem.c index 144667a3..1a97fdef 100644 --- a/linux-core/i915_gem.c +++ b/linux-core/i915_gem.c @@ -81,6 +81,42 @@ i915_gem_object_free_page_list(struct drm_gem_object *obj)  }  static void +i915_gem_object_move_to_active(struct drm_gem_object *obj) +{ +	struct drm_device *dev = obj->dev; +	drm_i915_private_t *dev_priv = dev->dev_private; +	struct drm_i915_gem_object *obj_priv = obj->driver_private; + +	/* Add a reference if we're newly entering the active list. */ +	if (!obj_priv->active) { +		drm_gem_object_reference(obj); +		obj_priv->active = 1; +	} +	/* Move from whatever list we were on to the tail of execution. */ +	list_move_tail(&obj_priv->list, +		       &dev_priv->mm.active_list); +} + +static void +i915_gem_object_move_to_inactive(struct drm_gem_object *obj) +{ +	struct drm_device *dev = obj->dev; +	drm_i915_private_t *dev_priv = dev->dev_private; +	struct drm_i915_gem_object *obj_priv = obj->driver_private; + +	if (obj_priv->pin_count != 0) +		list_del_init(&obj_priv->list); +	else +		list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); + +	if (obj_priv->active) { +		obj_priv->active = 0; +		drm_gem_object_unreference(obj); +	} +} + + +static void  i915_gem_flush(struct drm_device *dev,  	       uint32_t invalidate_domains,  	       uint32_t flush_domains) @@ -156,7 +192,6 @@ static int  i915_gem_object_wait_rendering(struct drm_gem_object *obj)  {  	struct drm_device *dev = obj->dev; -	drm_i915_private_t *dev_priv = dev->dev_private;  	struct drm_i915_gem_object *obj_priv = obj->driver_private;  	int ret; @@ -171,13 +206,7 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj)  		i915_gem_flush(dev, 0, obj->write_domain);  		obj->write_domain = 0; -		/* Add a reference since we're gaining a cookie. */ -		if (obj_priv->last_rendering_cookie == 0) -			drm_gem_object_reference(obj); -		/* Move from whatever list we were on to the tail of execution. -		 */ -		list_move_tail(&obj_priv->list, -			       &dev_priv->mm.active_list); +		i915_gem_object_move_to_active(obj);  		obj_priv->last_rendering_cookie = i915_emit_irq(dev);  		BUG_ON(obj_priv->last_rendering_cookie == 0);  #if WATCH_LRU @@ -187,7 +216,7 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj)  	/* If there is rendering queued on the buffer being evicted, wait for  	 * it.  	 */ -	if (obj_priv->last_rendering_cookie != 0) { +	if (obj_priv->active) {  #if WATCH_BUF  		DRM_INFO("%s: object %p wait for cookie %08x\n",  			  __func__, obj, obj_priv->last_rendering_cookie); @@ -196,23 +225,11 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj)  		if (ret != 0)  			return ret; -		/* Clear it now that we know it's passed. */ -		obj_priv->last_rendering_cookie = 0; - -		/* We were on the execution list since we had a cookie. -		 * Move to the tail of the LRU list now since we're done. -		 */ -		if (obj_priv->pin_count == 0) -			list_move_tail(&obj_priv->list, -				       &dev_priv->mm.inactive_list); +		i915_gem_object_move_to_inactive(obj);  #if WATCH_LRU  		DRM_INFO("%s: wait moves to lru list %p\n", __func__, obj);  #endif -		/* The cookie held a reference to the object, release that -		 * now -		 */ -		drm_gem_object_unreference(obj);  	}  	return 0; @@ -253,10 +270,10 @@ i915_gem_object_unbind(struct drm_gem_object *obj)  	/* Remove ourselves from the LRU list if present. */  	if (!list_empty(&obj_priv->list)) {  		list_del_init(&obj_priv->list); -		if (obj_priv->last_rendering_cookie) { +		if (obj_priv->active) {  			DRM_ERROR("Failed to wait on buffer when unbinding, "  				  "continued anyway.\n"); -			obj_priv->last_rendering_cookie = 0; +			obj_priv->active = 0;  			drm_gem_object_unreference(obj);  		}  	} @@ -862,7 +879,6 @@ int  i915_gem_execbuffer(struct drm_device *dev, void *data,  		    struct drm_file *file_priv)  { -	drm_i915_private_t *dev_priv = dev->dev_private;  	struct drm_i915_gem_execbuffer *args = data;  	struct drm_i915_gem_exec_object *validate_list = NULL;  	struct drm_gem_object **object_list = NULL; @@ -980,21 +996,13 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,  	 * wait on when trying to clear up gtt space).  	 */  	cookie = i915_emit_irq(dev); +	BUG_ON(cookie == 0);  	for (i = 0; i < args->buffer_count; i++) {  		struct drm_gem_object *obj = object_list[i];  		struct drm_i915_gem_object *obj_priv = obj->driver_private; -		/* -		 * Have the cookie hold a reference to this object -		 * which is freed when the object is waited for -		 */ -		if (obj_priv->last_rendering_cookie == 0) -			drm_gem_object_reference(obj); +		i915_gem_object_move_to_active(obj);  		obj_priv->last_rendering_cookie = cookie; -		BUG_ON(obj_priv->last_rendering_cookie == 0); -		/* Move our buffer to the tail of the execution list. */ -		list_move_tail(&obj_priv->list, -			       &dev_priv->mm.active_list);  #if WATCH_LRU  		DRM_INFO("%s: move to exec list %p\n", __func__, obj);  #endif @@ -1172,7 +1180,7 @@ i915_gem_lastclose(struct drm_device *dev)  					    list);  		list_del_init(&obj_priv->list); -		obj_priv->last_rendering_cookie = 0; +		obj_priv->active = 0;  		obj_priv->obj->write_domain = 0;  		drm_gem_object_unreference(obj_priv->obj);  	} diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 296e1823..870726c5 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -247,9 +247,18 @@ typedef struct drm_i915_private {  		/**  		 * List of objects currently involved in rendering from the  		 * ringbuffer. +		 * +		 * A reference is held on the buffer while on this list.  		 */  		struct list_head active_list; -		/** LRU List of non-executing objects still in the GTT. */ +		/** +		 * LRU List of non-executing objects still in the GTT. +		 * There may still be dirty cachelines that need to be flushed +		 * before unbind. +		 * A reference is not held on the buffer while on this list, +		 * as merely being GTT-bound shouldn't prevent its being +		 * freed, and we'll pull it off the list in the free path. +		 */  		struct list_head inactive_list;  	} mm;  } drm_i915_private_t; @@ -271,6 +280,13 @@ struct drm_i915_gem_object {  	/** This object's place on the active or inactive lists */  	struct list_head list; +	/** +	 * This is set if the object is on the active list +	 * (has pending rendering), and is not set if it's on inactive (ready +	 * to be unbound). +	 */ +	int active; +  	/** AGP memory structure for our GTT binding. */  	DRM_AGP_MEM *agp_mem; | 
