提交 5eac3ab4 编写于 作者: C Chris Wilson

drm/i915: Evict just the purgeable GTT entries on the first pass

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: NChris Wilson <chris@chris-wilson.co.uk>
上级 ff75b9bc
...@@ -1073,8 +1073,8 @@ void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv); ...@@ -1073,8 +1073,8 @@ void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv);
/* i915_gem_evict.c */ /* i915_gem_evict.c */
int i915_gem_evict_something(struct drm_device *dev, int min_size, int i915_gem_evict_something(struct drm_device *dev, int min_size,
unsigned alignment, bool mappable); unsigned alignment, bool mappable);
int i915_gem_evict_everything(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); int i915_gem_evict_inactive(struct drm_device *dev, bool purgeable_only);
/* i915_gem_tiling.c */ /* i915_gem_tiling.c */
void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
......
...@@ -3519,7 +3519,8 @@ i915_gem_execbuffer_pin(struct drm_device *dev, ...@@ -3519,7 +3519,8 @@ i915_gem_execbuffer_pin(struct drm_device *dev,
int ret, i, retry; int ret, i, retry;
/* attempt to pin all of the buffers into the GTT */ /* attempt to pin all of the buffers into the GTT */
for (retry = 0; retry < 2; retry++) { retry = 0;
do {
ret = 0; ret = 0;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
struct drm_i915_gem_exec_object2 *entry = &exec_list[i]; struct drm_i915_gem_exec_object2 *entry = &exec_list[i];
...@@ -3567,18 +3568,18 @@ i915_gem_execbuffer_pin(struct drm_device *dev, ...@@ -3567,18 +3568,18 @@ i915_gem_execbuffer_pin(struct drm_device *dev,
while (i--) while (i--)
i915_gem_object_unpin(object_list[i]); i915_gem_object_unpin(object_list[i]);
if (ret == 0) if (ret != -ENOSPC || retry > 1)
break;
if (ret != -ENOSPC || retry)
return ret; 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) if (ret)
return ret; return ret;
}
return 0; retry++;
} while (1);
} }
/* Throttle our rendering by waiting until the ring has completed our requests /* Throttle our rendering by waiting until the ring has completed our requests
...@@ -4484,7 +4485,7 @@ i915_gem_idle(struct drm_device *dev) ...@@ -4484,7 +4485,7 @@ i915_gem_idle(struct drm_device *dev)
/* Under UMS, be paranoid and evict. */ /* Under UMS, be paranoid and evict. */
if (!drm_core_check_feature(dev, DRIVER_MODESET)) { if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
ret = i915_gem_evict_inactive(dev); ret = i915_gem_evict_inactive(dev, false);
if (ret) { if (ret) {
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return ret; return ret;
......
...@@ -42,7 +42,7 @@ mark_free(struct drm_i915_gem_object *obj_priv, ...@@ -42,7 +42,7 @@ mark_free(struct drm_i915_gem_object *obj_priv,
int 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, bool mappable) unsigned alignment, bool mappable)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
struct list_head eviction_list, unwind_list; struct list_head eviction_list, unwind_list;
...@@ -54,7 +54,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, ...@@ -54,7 +54,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
/* Re-check for free space after retiring requests */ /* Re-check for free space after retiring requests */
if (mappable) { if (mappable) {
if (drm_mm_search_free_in_range(&dev_priv->mm.gtt_space, 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, dev_priv->mm.gtt_mappable_end,
0)) 0))
return 0; return 0;
...@@ -171,7 +171,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, ...@@ -171,7 +171,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
} }
int 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; drm_i915_private_t *dev_priv = dev->dev_private;
int ret; int ret;
...@@ -192,38 +192,22 @@ i915_gem_evict_everything(struct drm_device *dev) ...@@ -192,38 +192,22 @@ i915_gem_evict_everything(struct drm_device *dev)
BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
ret = i915_gem_evict_inactive(dev); return i915_gem_evict_inactive(dev, purgeable_only);
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;
} }
/** Unbinds all inactive objects. */ /** Unbinds all inactive objects. */
int 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; drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj, *next;
while (!list_empty(&dev_priv->mm.inactive_list)) {
struct drm_gem_object *obj; list_for_each_entry_safe(obj, next,
int ret; &dev_priv->mm.inactive_list, mm_list) {
if (!purgeable_only || obj->madv != I915_MADV_WILLNEED) {
obj = &list_first_entry(&dev_priv->mm.inactive_list, int ret = i915_gem_object_unbind(&obj->base);
struct drm_i915_gem_object, if (ret)
mm_list)->base; return ret;
ret = i915_gem_object_unbind(obj);
if (ret != 0) {
DRM_ERROR("Error unbinding object: %d\n", ret);
return ret;
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册