diff mbox series

[v3,63/63] drm/i915: Keep lazy reference to userptr pages

Message ID 20201015112627.1142745-64-maarten.lankhorst@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series drm/i915: Remove obj->mm.lock! | expand

Commit Message

Maarten Lankhorst Oct. 15, 2020, 11:26 a.m. UTC
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 28 +++++++++++++++------
 1 file changed, 20 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
index b0c1cc5fa917..0ae737871f84 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
@@ -71,6 +71,13 @@  static bool i915_gem_userptr_invalidate(struct mmu_interval_notifier *mni,
 
 	mmu_interval_set_seq(mni, cur_seq);
 
+	/* drop the lazy reference we kept */
+	if (!obj->userptr.page_ref && obj->userptr.pvec) {
+		unpin_user_pages(obj->userptr.pvec, obj->base.size >> PAGE_SHIFT);
+		kvfree(obj->userptr.pvec);
+		obj->userptr.pvec = NULL;
+	}
+
 	spin_unlock(&i915->mm.notifier_lock);
 
 	/* we will unbind on next submission, still have userptr pins */
@@ -94,12 +101,12 @@  i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj)
 					    &i915_gem_userptr_notifier_ops);
 }
 
-static void i915_gem_object_userptr_drop_ref(struct drm_i915_gem_object *obj)
+static void i915_gem_object_userptr_drop_ref(struct drm_i915_gem_object *obj, bool free)
 {
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 
 	spin_lock(&i915->mm.notifier_lock);
-	if (!--obj->userptr.page_ref) {
+	if (!--obj->userptr.page_ref && free) {
 		const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
 
 		unpin_user_pages(obj->userptr.pvec, num_pages);
@@ -162,7 +169,7 @@  static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
 	return 0;
 
 err:
-	i915_gem_object_userptr_drop_ref(obj);
+	i915_gem_object_userptr_drop_ref(obj, true);
 err_free:
 	kfree(st);
 	return ret;
@@ -220,7 +227,7 @@  i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj,
 	sg_free_table(pages);
 	kfree(pages);
 
-	i915_gem_object_userptr_drop_ref(obj);
+	i915_gem_object_userptr_drop_ref(obj, true);
 }
 
 static int i915_gem_object_userptr_unbind(struct drm_i915_gem_object *obj, bool get_pages)
@@ -320,10 +327,8 @@  int i915_gem_object_userptr_submit_init(struct drm_i915_gem_object *obj)
 	}
 
 	if (!obj->userptr.page_ref++) {
-		obj->userptr.pvec = pvec;
+		swap(obj->userptr.pvec, pvec);
 		obj->userptr.notifier_seq = notifier_seq;
-
-		pvec = NULL;
 	}
 
 out_unlock:
@@ -352,7 +357,7 @@  int i915_gem_object_userptr_submit_done(struct drm_i915_gem_object *obj)
 
 void i915_gem_object_userptr_submit_fini(struct drm_i915_gem_object *obj)
 {
-	i915_gem_object_userptr_drop_ref(obj);
+	i915_gem_object_userptr_drop_ref(obj, false);
 }
 
 static void
@@ -360,6 +365,13 @@  i915_gem_userptr_release(struct drm_i915_gem_object *obj)
 {
 	mmu_interval_notifier_remove(&obj->userptr.notifier);
 	obj->userptr.notifier.mm = NULL;
+	GEM_WARN_ON(obj->userptr.page_ref);
+
+	if (obj->userptr.pvec) {
+		unpin_user_pages(obj->userptr.pvec, obj->base.size >> PAGE_SHIFT);
+		kvfree(obj->userptr.pvec);
+		obj->userptr.pvec = NULL;
+	}
 }
 
 static int