[PATCH 55/56] mm-active

Chris Wilson chris at chris-wilson.co.uk
Sat Jun 20 18:31:25 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     | 33 +++++++++++++++++--
 drivers/gpu/drm/i915/i915_active.c            | 18 ++++++++++
 drivers/gpu/drm/i915/i915_active.h            |  7 ++++
 drivers/gpu/drm/i915/i915_vma.c               |  8 +++++
 6 files changed, 88 insertions(+), 3 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..cfc29043cbf0 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -81,6 +81,20 @@ void __i915_gem_object_set_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;
+}
+
 int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
@@ -92,10 +106,18 @@ int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
 		return -EFAULT;
 	}
 
-	err = obj->ops->get_pages(obj);
-	GEM_BUG_ON(!err && !i915_gem_object_has_pages(obj));
+	if (!i915_active_has_exclusive(&obj->mm.active)) {
+		err = i915_active_acquire(&obj->mm.active);
+		if (err)
+			return err;
 
-	return err;
+		err = obj->ops->get_pages(obj);
+		i915_active_release(&obj->mm.active);
+		if (err)
+			return err;
+	}
+
+	return __i915_gem_object_wait_for_pages(obj);
 }
 
 /* Ensure that the associated pages are gathered from the backing storage
@@ -201,6 +223,7 @@ __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);
@@ -211,6 +234,10 @@ int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
 	if (unlikely(atomic_read(&obj->mm.pages_pin_count)))
 		return -EBUSY;
 
+	err = i915_active_wait(&obj->mm.active);
+	if (err)
+		return err;
+
 	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 71ad0d452680..a0dd8fc20b8e 100644
--- a/drivers/gpu/drm/i915/i915_active.c
+++ b/drivers/gpu/drm/i915/i915_active.c
@@ -1077,6 +1077,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 042502abefe5..923ed27497d8 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
  *
@@ -190,6 +192,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);
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index efb9eacf59b9..9717a8f05c63 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -435,6 +435,8 @@ int i915_vma_bind(struct i915_vma *vma,
 		 * execution and not content or object's backing store lifetime.
 		 */
 		prev = i915_active_set_exclusive(&vma->active, &work->base.dma);
+		if (!prev && vma->obj)
+			prev = i915_active_fence_get(&vma->obj->mm.active.excl);
 		if (prev) {
 			__i915_sw_fence_await_dma_fence(&work->base.chain,
 							prev,
@@ -449,6 +451,12 @@ int i915_vma_bind(struct i915_vma *vma,
 			work->pinned = vma->obj;
 		}
 	} else {
+		if (vma->obj) {
+			ret = i915_active_wait_for_exclusive(&vma->obj->mm.active);
+			if (ret)
+				return ret;
+		}
+
 		ret = vma->ops->bind_vma(vma, cache_level, bind_flags);
 		if (ret)
 			return ret;
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list