[PATCH 57/62] mm-active

Chris Wilson chris at chris-wilson.co.uk
Sun Jun 21 21:29:11 UTC 2020


---
 drivers/gpu/drm/i915/gem/i915_gem_object.c    | 23 +++++++++
 .../gpu/drm/i915/gem/i915_gem_object_types.h  |  2 +
 drivers/gpu/drm/i915/gem/i915_gem_pages.c     | 50 ++++++++++++++++---
 drivers/gpu/drm/i915/i915_active.c            | 18 +++++++
 drivers/gpu/drm/i915/i915_active.h            |  7 +++
 5 files changed, 93 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 37b3fb0eb943..b7fc0da239f5 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -26,6 +26,7 @@
 
 #include "display/intel_frontbuffer.h"
 #include "gt/intel_gt.h"
+#include "i915_active.h"
 #include "i915_drv.h"
 #include "i915_gem_clflush.h"
 #include "i915_gem_context.h"
@@ -49,6 +50,24 @@ void i915_gem_object_free(struct drm_i915_gem_object *obj)
 	return kmem_cache_free(global.slab_objects, obj);
 }
 
+static int i915_mm_active(struct i915_active *ref)
+{
+	struct drm_i915_gem_object *obj =
+		container_of(ref, typeof(*obj), mm.active);
+
+	i915_gem_object_get(obj);
+	return 0;
+}
+
+__i915_active_call
+static void i915_mm_retire(struct i915_active *ref)
+{
+	struct drm_i915_gem_object *obj =
+		container_of(ref, typeof(*obj), mm.active);
+
+	i915_gem_object_put(obj);
+}
+
 void i915_gem_object_init(struct drm_i915_gem_object *obj,
 			  const struct drm_i915_gem_object_ops *ops,
 			  struct lock_class_key *key)
@@ -70,6 +89,8 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
 	obj->mm.madv = I915_MADV_WILLNEED;
 	INIT_RADIX_TREE(&obj->mm.get_page.radix, GFP_KERNEL | __GFP_NOWARN);
 	mutex_init(&obj->mm.get_page.lock);
+
+	i915_active_init(&obj->mm.active, i915_mm_active, i915_mm_retire);
 }
 
 /**
@@ -149,6 +170,8 @@ static void __i915_gem_free_object_rcu(struct rcu_head *head)
 		container_of(head, typeof(*obj), rcu);
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 
+	i915_active_fini(&obj->mm.active);
+
 	dma_resv_fini(&obj->base._resv);
 	i915_gem_object_free(obj);
 
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
index dbb33aac7828..668b249fd109 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -189,6 +189,8 @@ struct drm_i915_gem_object {
 		atomic_t pages_pin_count;
 		atomic_t shrink_pin;
 
+		struct i915_active active;
+
 		/**
 		 * Memory region for this object.
 		 */
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
index be051239e0ac..fb9a228c5b69 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -81,23 +81,57 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
 	}
 }
 
-int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
+static int __i915_gem_object_wait_for_pages(struct drm_i915_gem_object *obj)
+{
+	int err;
+
+	err = i915_active_wait_for_exclusive(&obj->mm.active);
+	if (err)
+		return err;
+
+	if (IS_ERR(obj->mm.pages))
+		return PTR_ERR(obj->mm.pages);
+
+	return 0;
+}
+
+static int ____i915_gem_object_get_pages_async(struct drm_i915_gem_object *obj)
 {
-	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	int err;
 
+	if (i915_gem_object_has_pages(obj))
+		return PTR_ERR_OR_ZERO(obj->mm.pages);
+
+	if (i915_active_has_exclusive(&obj->mm.active))
+		return 0;
+
 	if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) {
-		drm_dbg(&i915->drm,
+		drm_dbg(obj->base.dev,
 			"Attempting to obtain a purgeable object\n");
 		return -EFAULT;
 	}
 
+	err = i915_active_acquire(&obj->mm.active);
+	if (err)
+		return err;
+
 	err = obj->ops->get_pages(obj);
-	GEM_BUG_ON(!err && !i915_gem_object_has_pages(obj));
+	i915_active_release(&obj->mm.active);
 
 	return err;
 }
 
+int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
+{
+	int err;
+
+	err = ____i915_gem_object_get_pages_async(obj);
+	if (err)
+		return err;
+
+	return __i915_gem_object_wait_for_pages(obj);
+}
+
 /* Ensure that the associated pages are gathered from the backing storage
  * and pinned into our object. i915_gem_object_pin_pages() may be called
  * multiple times before they are released by a single call to
@@ -201,14 +235,16 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj)
 int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
 {
 	struct sg_table *pages;
+	int err;
 
 	/* May be called by shrinker from within get_pages() (on another bo) */
 	lockdep_assert_held(&obj->base.resv->lock.base);
 
-	if (i915_gem_object_has_pinned_pages(obj))
-		return -EBUSY;
+	err = i915_active_wait(&obj->mm.active);
+	if (err)
+		return err;
 
-	if (unlikely(atomic_read(&obj->mm.pages_pin_count)))
+	if (i915_gem_object_has_pinned_pages(obj))
 		return -EBUSY;
 
 	i915_gem_object_release_mmap_offset(obj);
diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c
index 3f595446fd44..886685d6e1e2 100644
--- a/drivers/gpu/drm/i915/i915_active.c
+++ b/drivers/gpu/drm/i915/i915_active.c
@@ -1073,6 +1073,24 @@ int i915_active_fence_set(struct i915_active_fence *active,
 	return err;
 }
 
+int i915_active_fence_wait(struct i915_active_fence *active)
+{
+	struct dma_fence *fence;
+	int err;
+
+	if (GEM_WARN_ON(is_barrier(active)))
+		return -EBUSY;
+
+	fence = i915_active_fence_get(active);
+	if (!fence)
+		return 0;
+
+	err = dma_fence_wait(fence, true);
+	dma_fence_put(fence);
+
+	return err;
+}
+
 void i915_active_noop(struct dma_fence *fence, struct dma_fence_cb *cb)
 {
 	active_fence_cb(fence, cb);
diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h
index 2e0bcb3289ec..eefcc2344509 100644
--- a/drivers/gpu/drm/i915/i915_active.h
+++ b/drivers/gpu/drm/i915/i915_active.h
@@ -123,6 +123,8 @@ i915_active_fence_isset(const struct i915_active_fence *active)
 	return rcu_access_pointer(active->fence);
 }
 
+int i915_active_fence_wait(struct i915_active_fence *active);
+
 /*
  * GPU activity tracking
  *
@@ -191,6 +193,11 @@ static inline int i915_active_wait(struct i915_active *ref)
 	return __i915_active_wait(ref, TASK_INTERRUPTIBLE);
 }
 
+static inline int i915_active_wait_for_exclusive(struct i915_active *ref)
+{
+	return i915_active_fence_wait(&ref->excl);
+}
+
 int i915_sw_fence_await_active(struct i915_sw_fence *fence,
 			       struct i915_active *ref,
 			       unsigned int flags);
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list