| From e32f87dc59aba60a50e356b641560d201ba4049c Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sat, 9 May 2020 12:52:17 +0100 |
| Subject: drm/i915: Handle idling during i915_gem_evict_something busy loops |
| |
| From: Chris Wilson <chris@chris-wilson.co.uk> |
| |
| [ Upstream commit 955da9d77435acac066139e9d7f7723ce7204a1d ] |
| |
| i915_gem_evict_something() is charged with finding a slot within the GTT |
| that we may reuse. Since our goal is not to stall, we first look for a |
| slot that only overlaps idle vma. To this end, on the first pass we move |
| any active vma to the end of the search list. However, we only stopped |
| moving active vma after we see the first active vma twice. If during the |
| search, that first active vma completed, we would not notice and keep on |
| extending the search list. |
| |
| Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/1746 |
| Fixes: 2850748ef876 ("drm/i915: Pull i915_vma_pin under the vm->mutex") |
| Fixes: b1e3177bd1d8 ("drm/i915: Coordinate i915_active with its own mutex") |
| Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> |
| Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> |
| Cc: <stable@vger.kernel.org> # v5.5+ |
| Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> |
| Link: https://patchwork.freedesktop.org/patch/msgid/20200509115217.26853-1-chris@chris-wilson.co.uk |
| (cherry picked from commit 73e28cc40bf00b5d168cb8f5cff1ae63e9097446) |
| Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/gpu/drm/i915/i915_gem_evict.c | 26 ++++++++++++-------------- |
| 1 file changed, 12 insertions(+), 14 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c |
| index 0697bedebeef2..d99df9c337089 100644 |
| --- a/drivers/gpu/drm/i915/i915_gem_evict.c |
| +++ b/drivers/gpu/drm/i915/i915_gem_evict.c |
| @@ -130,6 +130,13 @@ i915_gem_evict_something(struct i915_address_space *vm, |
| active = NULL; |
| INIT_LIST_HEAD(&eviction_list); |
| list_for_each_entry_safe(vma, next, &vm->bound_list, vm_link) { |
| + if (vma == active) { /* now seen this vma twice */ |
| + if (flags & PIN_NONBLOCK) |
| + break; |
| + |
| + active = ERR_PTR(-EAGAIN); |
| + } |
| + |
| /* |
| * We keep this list in a rough least-recently scanned order |
| * of active elements (inactive elements are cheap to reap). |
| @@ -145,21 +152,12 @@ i915_gem_evict_something(struct i915_address_space *vm, |
| * To notice when we complete one full cycle, we record the |
| * first active element seen, before moving it to the tail. |
| */ |
| - if (i915_vma_is_active(vma)) { |
| - if (vma == active) { |
| - if (flags & PIN_NONBLOCK) |
| - break; |
| - |
| - active = ERR_PTR(-EAGAIN); |
| - } |
| - |
| - if (active != ERR_PTR(-EAGAIN)) { |
| - if (!active) |
| - active = vma; |
| + if (active != ERR_PTR(-EAGAIN) && i915_vma_is_active(vma)) { |
| + if (!active) |
| + active = vma; |
| |
| - list_move_tail(&vma->vm_link, &vm->bound_list); |
| - continue; |
| - } |
| + list_move_tail(&vma->vm_link, &vm->bound_list); |
| + continue; |
| } |
| |
| if (mark_free(&scan, vma, flags, &eviction_list)) |
| -- |
| 2.20.1 |
| |