[36/39] drm/i915: Move list of timelines under its own lock

Submitted by Chris Wilson on Dec. 7, 2018, 9:27 a.m.

Details

Message ID 20181207092735.10509-36-chris@chris-wilson.co.uk
State New
Series "Series without cover letter"
Headers show

Commit Message

Chris Wilson Dec. 7, 2018, 9:27 a.m.
Currently, the list of timelines is serialised by the struct_mutex, but
to alleviate difficulties with using that mutex in future, move the
list management under its own dedicated mutex.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_drv.h                  |  1 +
 drivers/gpu/drm/i915/i915_gem.c                  | 10 ++++++++++
 drivers/gpu/drm/i915/i915_request.c              |  2 ++
 drivers/gpu/drm/i915/i915_timeline.c             | 11 +++++++----
 drivers/gpu/drm/i915/i915_timeline.h             |  1 +
 drivers/gpu/drm/i915/selftests/mock_gem_device.c |  4 ++++
 drivers/gpu/drm/i915/selftests/mock_timeline.c   |  3 ++-
 7 files changed, 27 insertions(+), 5 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9f89184a7d3a..b6be1a34e0d6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1957,6 +1957,7 @@  struct drm_i915_private {
 		void (*resume)(struct drm_i915_private *);
 		void (*cleanup_engine)(struct intel_engine_cs *engine);
 
+		struct mutex timeline_lock;
 		struct list_head timelines;
 
 		struct list_head active_rings;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index b7fb8f364165..d06b2cb0c752 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3430,11 +3430,17 @@  int i915_gem_wait_for_idle(struct drm_i915_private *i915,
 
 		lockdep_assert_held(&i915->drm.struct_mutex);
 
+		mutex_lock(&i915->gt.timeline_lock);
 		list_for_each_entry(tl, &i915->gt.timelines, link) {
+			mutex_unlock(&i915->gt.timeline_lock);
+
 			timeout = wait_for_timeline(tl, flags, timeout);
 			if (timeout < 0)
 				return timeout;
+
+			mutex_lock(&i915->gt.timeline_lock);
 		}
+		mutex_unlock(&i915->gt.timeline_lock);
 		if (GEM_SHOW_DEBUG() && !timeout) {
 			/* Presume that timeout was non-zero to begin with! */
 			dev_warn(&i915->drm.pdev->dev,
@@ -5435,7 +5441,9 @@  int i915_gem_init_early(struct drm_i915_private *dev_priv)
 	if (!dev_priv->priorities)
 		goto err_dependencies;
 
+	mutex_init(&dev_priv->gt.timeline_lock);
 	INIT_LIST_HEAD(&dev_priv->gt.timelines);
+
 	INIT_LIST_HEAD(&dev_priv->gt.active_rings);
 	INIT_LIST_HEAD(&dev_priv->gt.closed_vma);
 
@@ -5479,7 +5487,9 @@  void i915_gem_cleanup_early(struct drm_i915_private *dev_priv)
 	GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list));
 	GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count));
 	WARN_ON(dev_priv->mm.object_count);
+
 	WARN_ON(!list_empty(&dev_priv->gt.timelines));
+	mutex_destroy(&dev_priv->gt.timeline_lock);
 
 	kmem_cache_destroy(dev_priv->priorities);
 	kmem_cache_destroy(dev_priv->dependencies);
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index c3a4ae3c685b..0e0870b80e23 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -160,8 +160,10 @@  static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno)
 		kthread_unpark(engine->breadcrumbs.signaler);
 	}
 
+	mutex_lock(&i915->gt.timeline_lock);
 	list_for_each_entry(timeline, &i915->gt.timelines, link)
 		memset(timeline->global_sync, 0, sizeof(timeline->global_sync));
+	mutex_unlock(&i915->gt.timeline_lock);
 
 	i915->gt.request_serial = seqno;
 
diff --git a/drivers/gpu/drm/i915/i915_timeline.c b/drivers/gpu/drm/i915/i915_timeline.c
index 4667cc08c416..c4e7ad179d86 100644
--- a/drivers/gpu/drm/i915/i915_timeline.c
+++ b/drivers/gpu/drm/i915/i915_timeline.c
@@ -13,8 +13,6 @@  void i915_timeline_init(struct drm_i915_private *i915,
 			struct i915_timeline *timeline,
 			const char *name)
 {
-	lockdep_assert_held(&i915->drm.struct_mutex);
-
 	/*
 	 * Ideally we want a set of engines on a single leaf as we expect
 	 * to mostly be tracking synchronisation between engines. It is not
@@ -23,9 +21,12 @@  void i915_timeline_init(struct drm_i915_private *i915,
 	 */
 	BUILD_BUG_ON(KSYNCMAP < I915_NUM_ENGINES);
 
+	timeline->i915 = i915;
 	timeline->name = name;
 
+	mutex_lock(&i915->gt.timeline_lock);
 	list_add(&timeline->link, &i915->gt.timelines);
+	mutex_unlock(&i915->gt.timeline_lock);
 
 	/* Called during early_init before we know how many engines there are */
 
@@ -53,8 +54,7 @@  void i915_timelines_park(struct drm_i915_private *i915)
 {
 	struct i915_timeline *timeline;
 
-	lockdep_assert_held(&i915->drm.struct_mutex);
-
+	mutex_lock(&i915->gt.timeline_lock);
 	list_for_each_entry(timeline, &i915->gt.timelines, link) {
 		/*
 		 * All known fences are completed so we can scrap
@@ -64,6 +64,7 @@  void i915_timelines_park(struct drm_i915_private *i915)
 		 */
 		i915_syncmap_free(&timeline->sync);
 	}
+	mutex_unlock(&i915->gt.timeline_lock);
 }
 
 void i915_timeline_fini(struct i915_timeline *timeline)
@@ -72,7 +73,9 @@  void i915_timeline_fini(struct i915_timeline *timeline)
 
 	i915_syncmap_free(&timeline->sync);
 
+	mutex_lock(&timeline->i915->gt.timeline_lock);
 	list_del(&timeline->link);
+	mutex_unlock(&timeline->i915->gt.timeline_lock);
 }
 
 struct i915_timeline *
diff --git a/drivers/gpu/drm/i915/i915_timeline.h b/drivers/gpu/drm/i915/i915_timeline.h
index ebd71b487220..46b32bf20f25 100644
--- a/drivers/gpu/drm/i915/i915_timeline.h
+++ b/drivers/gpu/drm/i915/i915_timeline.h
@@ -74,6 +74,7 @@  struct i915_timeline {
 
 	struct list_head link;
 	const char *name;
+	struct drm_i915_private *i915;
 
 	struct kref kref;
 };
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index 4a25d2a344f2..b2292eb609f8 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -74,7 +74,9 @@  static void mock_device_release(struct drm_device *dev)
 	mutex_lock(&i915->drm.struct_mutex);
 	mock_fini_ggtt(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
+
 	WARN_ON(!list_empty(&i915->gt.timelines));
+	mutex_destroy(&i915->gt.timeline_lock);
 
 	destroy_workqueue(i915->wq);
 
@@ -227,7 +229,9 @@  struct drm_i915_private *mock_gem_device(void)
 	if (!i915->priorities)
 		goto err_dependencies;
 
+	mutex_init(&i915->gt.timeline_lock);
 	INIT_LIST_HEAD(&i915->gt.timelines);
+
 	INIT_LIST_HEAD(&i915->gt.active_rings);
 	INIT_LIST_HEAD(&i915->gt.closed_vma);
 
diff --git a/drivers/gpu/drm/i915/selftests/mock_timeline.c b/drivers/gpu/drm/i915/selftests/mock_timeline.c
index dcf3b16f5a07..cf39ccd9fc05 100644
--- a/drivers/gpu/drm/i915/selftests/mock_timeline.c
+++ b/drivers/gpu/drm/i915/selftests/mock_timeline.c
@@ -10,6 +10,7 @@ 
 
 void mock_timeline_init(struct i915_timeline *timeline, u64 context)
 {
+	timeline->i915 = NULL;
 	timeline->fence_context = context;
 
 	spin_lock_init(&timeline->lock);
@@ -24,5 +25,5 @@  void mock_timeline_init(struct i915_timeline *timeline, u64 context)
 
 void mock_timeline_fini(struct i915_timeline *timeline)
 {
-	i915_timeline_fini(timeline);
+	i915_syncmap_free(&timeline->sync);
 }