[PATCH] drm/i915/gem: Avoid waiting inside mmu_notifier_invalidate_range

Chris Wilson chris at chris-wilson.co.uk
Fri May 22 23:22:51 UTC 2020


Since the userptr may be invalidated from inside a reclaim path, we
cannot wait on unbinding the object as we may hold any number of locks,
including the active reference of the object we are trying to
invalidate. E.g.

[<0>] __i915_active_wait+0x70/0xc0 [i915]
[<0>] i915_vma_unbind+0x2f/0x110 [i915]
[<0>] i915_gem_object_unbind+0x17c/0x350 [i915]
[<0>] userptr_mn_invalidate_range_start+0xb6/0x140 [i915]
[<0>] __mmu_notifier_invalidate_range_start+0x105/0x150
[<0>] try_to_unmap_one+0x7fb/0x900
[<0>] rmap_walk_file+0xe4/0x240
[<0>] try_to_unmap+0x85/0xc0
[<0>] shrink_page_list+0x885/0xe80
[<0>] shrink_inactive_list+0x155/0x260
[<0>] shrink_lruvec+0x4ec/0x5f0
[<0>] shrink_node+0x15b/0x410
[<0>] try_to_free_pages+0x169/0x3a0
[<0>] __alloc_pages_slowpath.constprop.0+0x251/0xa00
[<0>] __alloc_pages_nodemask+0x144/0x170
[<0>] new_slab+0x259/0x280
[<0>] ___slab_alloc.isra.0.constprop.0+0x3dd/0x460
[<0>] __slab_alloc.isra.0.constprop.0+0x9/0x10
[<0>] kmem_cache_alloc+0x11a/0x130
[<0>] alloc_pd+0x17/0x60 [i915]
[<0>] __gen8_ppgtt_alloc+0x2d7/0x350 [i915]
[<0>] gen8_ppgtt_alloc+0x35/0x70 [i915]
[<0>] ppgtt_bind_vma+0x29/0x70 [i915]

This situation only occurs when the lru page shrinker tries to sacrifice
one the objects it is trying to allocate for. However, we do have to
wait for an active object so that we can revoke access to the page
range.

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/1702
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 22 ++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
index 8b0708708671..10ff6f9d623a 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
@@ -83,6 +83,22 @@ __i915_gem_userptr_set_active(struct drm_i915_gem_object *obj, bool value)
 	spin_unlock(&mo->mn->lock);
 }
 
+static int
+revoke_pages(struct drm_i915_gem_object *obj)
+{
+	int err;
+
+	err = i915_gem_object_wait(obj, I915_WAIT_ALL, MAX_SCHEDULE_TIMEOUT);
+	if (err)
+		return err;
+
+	err = i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_BARRIER);
+	if (err)
+		return err;
+
+	return __i915_gem_object_put_pages(obj);
+}
+
 static int
 userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
 				  const struct mmu_notifier_range *range)
@@ -126,11 +142,7 @@ userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
 		}
 		spin_unlock(&mn->lock);
 
-		ret = i915_gem_object_unbind(obj,
-					     I915_GEM_OBJECT_UNBIND_ACTIVE |
-					     I915_GEM_OBJECT_UNBIND_BARRIER);
-		if (ret == 0)
-			ret = __i915_gem_object_put_pages(obj);
+		ret = revoke_pages(obj);
 		i915_gem_object_put(obj);
 		if (ret)
 			return ret;
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list