]> git.karo-electronics.de Git - linux-beck.git/commitdiff
drm/i915: Evict just the purgeable GTT entries on the first pass
authorChris Wilson <chris@chris-wilson.co.uk>
Sun, 31 Oct 2010 08:49:47 +0000 (08:49 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Sun, 31 Oct 2010 12:31:30 +0000 (12:31 +0000)
Take two passes to evict everything whilst searching for sufficient free
space to bind the batchbuffer. After searching for sufficient free space
using LRU eviction, evict everything that is purgeable and try again.
Only then if there is insufficient free space (or the GTT is too badly
fragmented) evict everything from the aperture and try one last time.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_evict.c

index ec582b6d21134fbeb43dc843b4cd006020112e57..54e5b2fa5fd45e343fa2f29598499ccee5aedaca 100644 (file)
@@ -1073,8 +1073,8 @@ void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv);
 /* i915_gem_evict.c */
 int i915_gem_evict_something(struct drm_device *dev, int min_size,
                             unsigned alignment, bool mappable);
-int i915_gem_evict_everything(struct drm_device *dev);
-int i915_gem_evict_inactive(struct drm_device *dev);
+int i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only);
+int i915_gem_evict_inactive(struct drm_device *dev, bool purgeable_only);
 
 /* i915_gem_tiling.c */
 void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
index e3fc333e2e57c04ed6d00c646d218646273824d9..c8e516d3f8bc76a4da62aa80dd72db6e8b22049c 100644 (file)
@@ -3519,7 +3519,8 @@ i915_gem_execbuffer_pin(struct drm_device *dev,
        int ret, i, retry;
 
        /* attempt to pin all of the buffers into the GTT */
-       for (retry = 0; retry < 2; retry++) {
+       retry = 0;
+       do {
                ret = 0;
                for (i = 0; i < count; i++) {
                        struct drm_i915_gem_exec_object2 *entry = &exec_list[i];
@@ -3567,18 +3568,18 @@ i915_gem_execbuffer_pin(struct drm_device *dev,
                while (i--)
                        i915_gem_object_unpin(object_list[i]);
 
-               if (ret == 0)
-                       break;
-
-               if (ret != -ENOSPC || retry)
+               if (ret != -ENOSPC || retry > 1)
                        return ret;
 
-               ret = i915_gem_evict_everything(dev);
+               /* First attempt, just clear anything that is purgeable.
+                * Second attempt, clear the entire GTT.
+                */
+               ret = i915_gem_evict_everything(dev, retry == 0);
                if (ret)
                        return ret;
-       }
 
-       return 0;
+               retry++;
+       } while (1);
 }
 
 /* Throttle our rendering by waiting until the ring has completed our requests
@@ -4484,7 +4485,7 @@ i915_gem_idle(struct drm_device *dev)
 
        /* Under UMS, be paranoid and evict. */
        if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
-               ret = i915_gem_evict_inactive(dev);
+               ret = i915_gem_evict_inactive(dev, false);
                if (ret) {
                        mutex_unlock(&dev->struct_mutex);
                        return ret;
index 3a4215f316524a847dd7e3e3d92ac1f0448c9fec..a2609c5542fdcc7303d84eda65b3f310a6ce7810 100644 (file)
@@ -42,7 +42,7 @@ mark_free(struct drm_i915_gem_object *obj_priv,
 
 int
 i915_gem_evict_something(struct drm_device *dev, int min_size,
-                        unsigned alignment, bool mappable)
+                        unsigned alignment, bool mappable)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct list_head eviction_list, unwind_list;
@@ -54,7 +54,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
        /* Re-check for free space after retiring requests */
        if (mappable) {
                if (drm_mm_search_free_in_range(&dev_priv->mm.gtt_space,
-                                               min_size, alignment, 0,
+                                               min_size, alignment, 0,
                                                dev_priv->mm.gtt_mappable_end,
                                                0))
                        return 0;
@@ -171,7 +171,7 @@ found:
 }
 
 int
-i915_gem_evict_everything(struct drm_device *dev)
+i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        int ret;
@@ -192,38 +192,22 @@ i915_gem_evict_everything(struct drm_device *dev)
 
        BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
 
-       ret = i915_gem_evict_inactive(dev);
-       if (ret)
-               return ret;
-
-       lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
-                      list_empty(&dev_priv->mm.flushing_list) &&
-                      list_empty(&dev_priv->render_ring.active_list) &&
-                      list_empty(&dev_priv->bsd_ring.active_list) &&
-                      list_empty(&dev_priv->blt_ring.active_list));
-       BUG_ON(!lists_empty);
-
-       return 0;
+       return i915_gem_evict_inactive(dev, purgeable_only);
 }
 
 /** Unbinds all inactive objects. */
 int
-i915_gem_evict_inactive(struct drm_device *dev)
+i915_gem_evict_inactive(struct drm_device *dev, bool purgeable_only)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-
-       while (!list_empty(&dev_priv->mm.inactive_list)) {
-               struct drm_gem_object *obj;
-               int ret;
-
-               obj = &list_first_entry(&dev_priv->mm.inactive_list,
-                                       struct drm_i915_gem_object,
-                                       mm_list)->base;
-
-               ret = i915_gem_object_unbind(obj);
-               if (ret != 0) {
-                       DRM_ERROR("Error unbinding object: %d\n", ret);
-                       return ret;
+       struct drm_i915_gem_object *obj, *next;
+
+       list_for_each_entry_safe(obj, next,
+                                &dev_priv->mm.inactive_list, mm_list) {
+               if (!purgeable_only || obj->madv != I915_MADV_WILLNEED) {
+                       int ret = i915_gem_object_unbind(&obj->base);
+                       if (ret)
+                               return ret;
                }
        }