diff mbox

[8/9] drm/i915: prepare for fair lru eviction

Message ID 1274217111-3882-9-git-send-email-daniel.vetter@ffwll.ch (mailing list archive)
State Deferred, archived
Headers show

Commit Message

Daniel Vetter May 18, 2010, 9:11 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 952b4b3..d5a7db7 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -50,7 +50,8 @@  static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
 static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
 					   unsigned alignment);
 static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
-static int i915_gem_evict_something(struct drm_device *dev, int min_size);
+static int i915_gem_evict_something(struct drm_device *dev, int min_size,
+				    unsigned alignment);
 static int i915_gem_evict_from_inactive_list(struct drm_device *dev);
 static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
 				struct drm_i915_gem_pwrite *args,
@@ -333,7 +334,7 @@  i915_gem_object_get_pages_or_evict(struct drm_gem_object *obj)
 	if (ret == -ENOMEM) {
 		struct drm_device *dev = obj->dev;
 
-		ret = i915_gem_evict_something(dev, obj->size);
+		ret = i915_gem_evict_something(dev, obj->size, 0);
 		if (ret)
 			return ret;
 
@@ -2114,10 +2115,12 @@  i915_gem_object_unbind(struct drm_gem_object *obj)
 	return 0;
 }
 
-static struct drm_gem_object *
-i915_gem_find_inactive_object(struct drm_device *dev, int min_size)
+static int
+i915_gem_scan_inactive_list_and_evict(struct drm_device *dev, int min_size,
+				      unsigned alignment, int *found)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_gem_object *obj;
 	struct drm_i915_gem_object *obj_priv;
 	struct drm_gem_object *best = NULL;
 	struct drm_gem_object *first = NULL;
@@ -2131,14 +2134,31 @@  i915_gem_find_inactive_object(struct drm_device *dev, int min_size)
 			    (!best || obj->size < best->size)) {
 				best = obj;
 				if (best->size == min_size)
-					return best;
+					break;
 			}
 			if (!first)
 			    first = obj;
 		}
 	}
 
-	return best ? best : first;
+	obj = best ? best : first;
+
+	if (!obj) {
+		*found = 0;
+		return 0;
+	}
+
+	*found = 1;
+
+#if WATCH_LRU
+	DRM_INFO("%s: evicting %p\n", __func__, obj);
+#endif
+	obj_priv = to_intel_bo(obj);
+	BUG_ON(obj_priv->pin_count != 0);
+	BUG_ON(obj_priv->active);
+
+	/* Wait on the rendering and unbind the buffer. */
+	return i915_gem_object_unbind(obj);
 }
 
 static int
@@ -2203,11 +2223,11 @@  i915_gem_evict_everything(struct drm_device *dev)
 }
 
 static int
-i915_gem_evict_something(struct drm_device *dev, int min_size)
+i915_gem_evict_something(struct drm_device *dev,
+			 int min_size, unsigned alignment)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_gem_object *obj;
-	int ret;
+	int ret, found;
 
 	for (;;) {
 		i915_gem_retire_requests(dev);
@@ -2215,20 +2235,11 @@  i915_gem_evict_something(struct drm_device *dev, int min_size)
 		/* If there's an inactive buffer available now, grab it
 		 * and be done.
 		 */
-		obj = i915_gem_find_inactive_object(dev, min_size);
-		if (obj) {
-			struct drm_i915_gem_object *obj_priv;
-
-#if WATCH_LRU
-			DRM_INFO("%s: evicting %p\n", __func__, obj);
-#endif
-			obj_priv = to_intel_bo(obj);
-			BUG_ON(obj_priv->pin_count != 0);
-			BUG_ON(obj_priv->active);
-
-			/* Wait on the rendering and unbind the buffer. */
-			return i915_gem_object_unbind(obj);
-		}
+		ret = i915_gem_scan_inactive_list_and_evict(dev, min_size,
+							    alignment,
+							    &found);
+		if (found)
+			return ret;
 
 		/* If we didn't get anything, but the ring is still processing
 		 * things, wait for the next to finish and hopefully leave us
@@ -2254,6 +2265,7 @@  i915_gem_evict_something(struct drm_device *dev, int min_size)
 		 * will get moved to inactive.
 		 */
 		if (!list_empty(&dev_priv->mm.flushing_list)) {
+			struct drm_gem_object *obj = NULL;
 			struct drm_i915_gem_object *obj_priv;
 
 			/* Find an object that we can immediately reuse */
@@ -2716,7 +2728,7 @@  i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
 #if WATCH_LRU
 		DRM_INFO("%s: GTT full, evicting something\n", __func__);
 #endif
-		ret = i915_gem_evict_something(dev, obj->size);
+		ret = i915_gem_evict_something(dev, obj->size, alignment);
 		if (ret)
 			return ret;
 
@@ -2734,7 +2746,8 @@  i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
 
 		if (ret == -ENOMEM) {
 			/* first try to clear up some space from the GTT */
-			ret = i915_gem_evict_something(dev, obj->size);
+			ret = i915_gem_evict_something(dev, obj->size,
+						       alignment);
 			if (ret) {
 				/* now try to shrink everyone else */
 				if (gfpmask) {
@@ -2764,7 +2777,7 @@  i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
 		drm_mm_put_block(obj_priv->gtt_space);
 		obj_priv->gtt_space = NULL;
 
-		ret = i915_gem_evict_something(dev, obj->size);
+		ret = i915_gem_evict_something(dev, obj->size, alignment);
 		if (ret)
 			return ret;