[PATCH 39/43] timeline-hwsp

Chris Wilson chris at chris-wilson.co.uk
Fri Dec 28 15:35:39 UTC 2018


---
 drivers/gpu/drm/i915/i915_drv.h      |   4 ++
 drivers/gpu/drm/i915/i915_gem.c      |   2 +
 drivers/gpu/drm/i915/i915_timeline.c | 100 ++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/i915_timeline.h |  11 +++
 4 files changed, 115 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b53173a2d2bd..05b8b4cfd0eb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1958,6 +1958,10 @@ struct drm_i915_private {
 		struct mutex timeline_lock;
 		struct list_head timelines;
 
+		/* Pack multiple timelines' seqnos into the same page */
+		struct i915_vma *timeline_hwsp;
+		u64 timeline_free;
+
 		struct list_head active_rings;
 		struct list_head closed_vma;
 		u32 active_requests;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 4afb380ea5af..2d924841d8ee 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -5296,6 +5296,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
 		mutex_unlock(&dev_priv->drm.struct_mutex);
 	}
 
+	i915_timelines_fini(dev_priv);
 	i915_gem_drain_freed_objects(dev_priv);
 	return ret;
 }
@@ -5322,6 +5323,7 @@ void i915_gem_fini(struct drm_i915_private *dev_priv)
 
 	intel_uc_fini_misc(dev_priv);
 	i915_gem_cleanup_userptr(dev_priv);
+	i915_timelines_fini(dev_priv);
 
 	i915_gem_drain_freed_objects(dev_priv);
 
diff --git a/drivers/gpu/drm/i915/i915_timeline.c b/drivers/gpu/drm/i915/i915_timeline.c
index c4e7ad179d86..ab0c996b0ea7 100644
--- a/drivers/gpu/drm/i915/i915_timeline.c
+++ b/drivers/gpu/drm/i915/i915_timeline.c
@@ -9,6 +9,54 @@
 #include "i915_timeline.h"
 #include "i915_syncmap.h"
 
+static void get_seqno_locked(struct drm_i915_private *i915,
+			     struct i915_timeline *timeline)
+{
+	struct i915_vma *vma;
+	void *vaddr;
+	int offset;
+
+	offset = __builtin_ffsll(i915->gt.timeline_free);
+	if (offset-- == 0 && i915->gt.timeline_hwsp) {
+		i915_vma_put(i915->gt.timeline_hwsp);
+		i915->gt.timeline_hwsp = NULL;
+	}
+
+	vma = i915->gt.timeline_hwsp;
+	if (!vma) {
+		struct drm_i915_gem_object *bo;
+
+		BUILD_BUG_ON(BITS_PER_TYPE(u64) * CACHELINE_BYTES > PAGE_SIZE);
+		bo = i915_gem_object_create_internal(i915, PAGE_SIZE);
+		if (!bo)
+			return;
+
+		i915_gem_object_set_cache_level(bo, I915_CACHE_LLC);
+
+		vma = i915_vma_instance(bo, &i915->ggtt.vm, NULL);
+		if (IS_ERR(vma))
+			return;
+
+		i915->gt.timeline_hwsp = vma;
+		i915->gt.timeline_free = ~0ull;
+		offset = 0;
+	}
+
+	vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB);
+	if (IS_ERR(vaddr))
+		return;
+
+	timeline->hwsp_ggtt = i915_vma_get(vma);
+	timeline->hwsp_offset = offset * CACHELINE_BYTES;
+
+	timeline->hwsp_seqno =
+		memset(vaddr + timeline->hwsp_offset,
+		       0,
+		       sizeof(*timeline->hwsp_seqno));
+
+	i915->gt.timeline_free &= ~BIT_ULL(offset);
+}
+
 void i915_timeline_init(struct drm_i915_private *i915,
 			struct i915_timeline *timeline,
 			const char *name)
@@ -23,8 +71,10 @@ void i915_timeline_init(struct drm_i915_private *i915,
 
 	timeline->i915 = i915;
 	timeline->name = name;
+	timeline->pin_count = 0;
 
 	mutex_lock(&i915->gt.timeline_lock);
+	get_seqno_locked(i915, timeline);
 	list_add(&timeline->link, &i915->gt.timelines);
 	mutex_unlock(&i915->gt.timeline_lock);
 
@@ -69,13 +119,22 @@ void i915_timelines_park(struct drm_i915_private *i915)
 
 void i915_timeline_fini(struct i915_timeline *timeline)
 {
+	struct drm_i915_private *i915 = timeline->i915;
+
+	GEM_BUG_ON(timeline->pin_count);
 	GEM_BUG_ON(!list_empty(&timeline->requests));
 
 	i915_syncmap_free(&timeline->sync);
 
-	mutex_lock(&timeline->i915->gt.timeline_lock);
+	mutex_lock(&i915->gt.timeline_lock);
 	list_del(&timeline->link);
-	mutex_unlock(&timeline->i915->gt.timeline_lock);
+	if (timeline->hwsp_ggtt == i915->gt.timeline_hwsp)
+		i915->gt.timeline_free |=
+			BIT_ULL(timeline->hwsp_offset / CACHELINE_BYTES);
+	mutex_unlock(&i915->gt.timeline_lock);
+
+	i915_gem_object_unpin_map(timeline->hwsp_ggtt->obj);
+	i915_vma_put(timeline->hwsp_ggtt);
 }
 
 struct i915_timeline *
@@ -93,6 +152,34 @@ i915_timeline_create(struct drm_i915_private *i915, const char *name)
 	return timeline;
 }
 
+int i915_timeline_pin(struct i915_timeline *tl)
+{
+	int err;
+
+	if (tl->pin_count++)
+		return 0;
+	GEM_BUG_ON(!tl->pin_count);
+
+	err = i915_vma_pin(tl->hwsp_ggtt, 0, 0, PIN_GLOBAL | PIN_HIGH);
+	if (err)
+		goto unpin;
+
+	return 0;
+
+unpin:
+	tl->pin_count = 0;
+	return err;
+}
+
+void i915_timeline_unpin(struct i915_timeline *tl)
+{
+	GEM_BUG_ON(!tl->pin_count);
+	if (--tl->pin_count)
+		return;
+
+	__i915_vma_unpin(tl->hwsp_ggtt);
+}
+
 void __i915_timeline_free(struct kref *kref)
 {
 	struct i915_timeline *timeline =
@@ -102,6 +189,15 @@ void __i915_timeline_free(struct kref *kref)
 	kfree(timeline);
 }
 
+void i915_timelines_fini(struct drm_i915_private *i915)
+{
+	if (!i915->gt.timeline_hwsp)
+		return;
+
+	i915_vma_put(i915->gt.timeline_hwsp);
+	i915->gt.timeline_hwsp = NULL;
+}
+
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftests/mock_timeline.c"
 #include "selftests/i915_timeline.c"
diff --git a/drivers/gpu/drm/i915/i915_timeline.h b/drivers/gpu/drm/i915/i915_timeline.h
index c6f051541a01..85462f8341bf 100644
--- a/drivers/gpu/drm/i915/i915_timeline.h
+++ b/drivers/gpu/drm/i915/i915_timeline.h
@@ -32,6 +32,8 @@
 #include "i915_syncmap.h"
 #include "i915_utils.h"
 
+struct i915_vma;
+
 struct i915_timeline {
 	u64 fence_context;
 	u32 seqno;
@@ -40,6 +42,11 @@ struct i915_timeline {
 #define TIMELINE_CLIENT 0 /* default subclass */
 #define TIMELINE_ENGINE 1
 
+	unsigned int pin_count;
+	const u32 *hwsp_seqno;
+	struct i915_vma *hwsp_ggtt;
+	u32 hwsp_offset;
+
 	/**
 	 * List of breadcrumbs associated with GPU requests currently
 	 * outstanding.
@@ -135,6 +142,10 @@ static inline bool i915_timeline_sync_is_later(struct i915_timeline *tl,
 	return __i915_timeline_sync_is_later(tl, fence->context, fence->seqno);
 }
 
+int i915_timeline_pin(struct i915_timeline *tl);
+void i915_timeline_unpin(struct i915_timeline *tl);
+
 void i915_timelines_park(struct drm_i915_private *i915);
+void i915_timelines_fini(struct drm_i915_private *i915);
 
 #endif
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list