Commit 68c8c17f authored by Ben Widawsky's avatar Ben Widawsky Committed by Daniel Vetter

drm/i915: evict VM instead of everything

When reserving objects during execbuf, it is possible to come across an
object which will not fit given the current fragmentation of the address
space. We do not have any defragment in drm_mm, so the strategy is to
instead evict everything, and reallocate objects.

With the upcoming addition of multiple VMs, there is no point to evict
everything since doing so is overkill for the specific case mentioned
above.
Recommended-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarBen Widawsky <ben@bwidawsk.net>
[danvet: One additional s/evict_everything/evict_vm/ to update a
comment in the code.]
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 7b796122
...@@ -2106,6 +2106,7 @@ int __must_check i915_gem_evict_something(struct drm_device *dev, ...@@ -2106,6 +2106,7 @@ int __must_check i915_gem_evict_something(struct drm_device *dev,
unsigned cache_level, unsigned cache_level,
bool mappable, bool mappable,
bool nonblock); bool nonblock);
int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle);
int i915_gem_evict_everything(struct drm_device *dev); int i915_gem_evict_everything(struct drm_device *dev);
/* i915_gem_stolen.c */ /* i915_gem_stolen.c */
......
...@@ -116,7 +116,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, ...@@ -116,7 +116,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
} }
/* We expect the caller to unpin, evict all and try again, or give up. /* We expect the caller to unpin, evict all and try again, or give up.
* So calling i915_gem_evict_everything() is unnecessary. * So calling i915_gem_evict_vm() is unnecessary.
*/ */
return -ENOSPC; return -ENOSPC;
...@@ -155,7 +155,22 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, ...@@ -155,7 +155,22 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
return ret; return ret;
} }
static int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle) /**
* i915_gem_evict_vm - Try to free up VM space
*
* @vm: Address space to evict from
* @do_idle: Boolean directing whether to idle first.
*
* VM eviction is about freeing up virtual address space. If one wants fine
* grained eviction, they should see evict something for more details. In terms
* of freeing up actual system memory, this function may not accomplish the
* desired result. An object may be shared in multiple address space, and this
* function will not assert those objects be freed.
*
* Using do_idle will result in a more complete eviction because it retires, and
* inactivates current BOs.
*/
int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
{ {
struct i915_vma *vma, *next; struct i915_vma *vma, *next;
int ret; int ret;
......
...@@ -549,10 +549,16 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, ...@@ -549,10 +549,16 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
{ {
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
struct i915_vma *vma; struct i915_vma *vma;
struct i915_address_space *vm;
struct list_head ordered_vmas; struct list_head ordered_vmas;
bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
int retry; int retry;
if (list_empty(vmas))
return 0;
vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm;
INIT_LIST_HEAD(&ordered_vmas); INIT_LIST_HEAD(&ordered_vmas);
while (!list_empty(vmas)) { while (!list_empty(vmas)) {
struct drm_i915_gem_exec_object2 *entry; struct drm_i915_gem_exec_object2 *entry;
...@@ -641,7 +647,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, ...@@ -641,7 +647,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
if (ret != -ENOSPC || retry++) if (ret != -ENOSPC || retry++)
return ret; return ret;
ret = i915_gem_evict_everything(ring->dev); ret = i915_gem_evict_vm(vm, true);
if (ret) if (ret)
return ret; return ret;
} while (1); } while (1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment