+ if (ret)
i915_gem_object_put(vma->obj);
- return false;
- }
} else {
/* Dead objects don't need pins */
atomic_and(~I915_VMA_PIN_MASK, &vma->flags);
}
- return true;
+ return ret;
}
-static void ungrab_vma(struct i915_vma *vma)
+static void ungrab_vma(struct i915_vma *vma, struct i915_gem_ww_ctx
*ww)
{
if (dying_vma(vma))
return;
- i915_gem_object_unlock(vma->obj);
+ if (!ww)
+ i915_gem_object_unlock(vma->obj);
+
i915_gem_object_put(vma->obj);
}
-static bool
+static int
mark_free(struct drm_mm_scan *scan,
struct i915_gem_ww_ctx *ww,
struct i915_vma *vma,
unsigned int flags,
struct list_head *unwind)
{
+ int err;
+
if (i915_vma_is_pinned(vma))
- return false;
+ return -ENOSPC;
- if (!grab_vma(vma, ww))
- return false;
+ err = grab_vma(vma, ww);
+ if (err)
+ return err;
list_add(&vma->evict_link, unwind);
- return drm_mm_scan_add_block(scan, &vma->node);
+ if (!drm_mm_scan_add_block(scan, &vma->node))
+ return -ENOSPC;
+
+ return 0;
}
static bool defer_evict(struct i915_vma *vma)
@@ -150,6 +159,7 @@ i915_gem_evict_something(struct
i915_address_space *vm,
enum drm_mm_insert_mode mode;
struct i915_vma *active;
int ret;
+ int err = 0;
lockdep_assert_held(&vm->mutex);
trace_i915_gem_evict(vm, min_size, alignment, flags);
@@ -210,17 +220,23 @@ i915_gem_evict_something(struct
i915_address_space *vm,
continue;
}
- if (mark_free(&scan, ww, vma, flags, &eviction_list))
+ err = mark_free(&scan, ww, vma, flags,
&eviction_list);
+ if (!err)
goto found;
+ if (err == -EDEADLK)
+ break;
}
/* Nothing found, clean up and bail out! */
list_for_each_entry_safe(vma, next, &eviction_list,
evict_link) {
ret = drm_mm_scan_remove_block(&scan, &vma->node);
BUG_ON(ret);
- ungrab_vma(vma);
+ ungrab_vma(vma, ww);
}
+ if (err == -EDEADLK)
+ return err;
+
/*
* Can we unpin some objects such as idle hw contents,
* or pending flips? But since only the GGTT has global
entries
@@ -267,7 +283,7 @@ i915_gem_evict_something(struct
i915_address_space *vm,
__i915_vma_pin(vma);
} else {
list_del(&vma->evict_link);
- ungrab_vma(vma);
+ ungrab_vma(vma, ww);
}
}
@@ -277,17 +293,21 @@ i915_gem_evict_something(struct
i915_address_space *vm,
__i915_vma_unpin(vma);
if (ret == 0)
ret = __i915_vma_unbind(vma);
- ungrab_vma(vma);
+ ungrab_vma(vma, ww);
}
while (ret == 0 && (node = drm_mm_scan_color_evict(&scan))) {
vma = container_of(node, struct i915_vma, node);
/* If we find any non-objects (!vma), we cannot evict
them */
- if (vma->node.color != I915_COLOR_UNEVICTABLE &&
- grab_vma(vma, ww)) {
- ret = __i915_vma_unbind(vma);
- ungrab_vma(vma);
+ if (vma->node.color != I915_COLOR_UNEVICTABLE) {
+ ret = grab_vma(vma, ww);
+ if (!ret) {
+ ret = __i915_vma_unbind(vma);
+ ungrab_vma(vma, ww);
+ } else if (ret != -EDEADLK) {
+ ret = -ENOSPC;
+ }
} else {
ret = -ENOSPC;
}
@@ -382,8 +402,11 @@ int i915_gem_evict_for_node(struct
i915_address_space *vm,
break;
}
- if (!grab_vma(vma, ww)) {
- ret = -ENOSPC;
+ ret = grab_vma(vma, ww);
+ if (ret) {
+ if (ret != -EDEADLK)
+ ret = -ENOSPC;
+
break;
}
@@ -405,7 +428,7 @@ int i915_gem_evict_for_node(struct
i915_address_space *vm,
if (ret == 0)
ret = __i915_vma_unbind(vma);
- ungrab_vma(vma);
+ ungrab_vma(vma, ww);
}
return ret;