[PATCH 09/14] drm/i915/gt: Acquire gt wakeref before context.pin_mutex

Chris Wilson chris at chris-wilson.co.uk
Tue Dec 31 17:32:02 UTC 2019


Pull the gt wakeref outside of the context.pin_mutex to reduce the
amount of work we have to perform under the first context pinning. Being
the first context pinning, it should not contend with anything, but
reducing the lock duration here removes the low hanging fruit that may
mask a real issue later.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/gt/intel_context.c | 56 ++++++++++++++++++++-----
 1 file changed, 46 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c
index fbaa9df6f436..c25d2be2ae0f 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.c
+++ b/drivers/gpu/drm/i915/gt/intel_context.c
@@ -13,6 +13,7 @@
 #include "intel_context.h"
 #include "intel_engine.h"
 #include "intel_engine_pm.h"
+#include "intel_gt_pm.h"
 #include "intel_ring.h"
 
 static struct i915_global_context {
@@ -43,12 +44,49 @@ intel_context_create(struct intel_engine_cs *engine)
 	return ce;
 }
 
+static void context_pm_get(struct intel_context *ce)
+{
+	struct intel_engine_cs *engine = ce->engine;
+	struct intel_gt *gt = engine->gt;
+
+	intel_gt_pm_get(gt);
+	if (is_power_of_2(engine->mask)) {
+		intel_engine_pm_get(engine);
+	} else {
+		intel_engine_mask_t tmp, mask = engine->mask;
+
+		for_each_engine_masked(engine, gt, mask, tmp)
+			intel_engine_pm_get(engine);
+	}
+}
+
+static void context_pm_put(struct intel_context *ce)
+{
+	struct intel_engine_cs *engine = ce->engine;
+	struct intel_gt *gt = engine->gt;
+
+	if (is_power_of_2(engine->mask)) {
+		intel_engine_pm_put(engine);
+	} else {
+		intel_engine_mask_t tmp, mask = engine->mask;
+
+		for_each_engine_masked(engine, gt, mask, tmp)
+			intel_engine_pm_put(engine);
+	}
+	intel_gt_pm_put(gt);
+}
+
 int __intel_context_do_pin(struct intel_context *ce)
 {
-	int err;
+	int err = 0;
 
-	if (mutex_lock_interruptible(&ce->pin_mutex))
-		return -EINTR;
+	/* Reduce contention on ce->pin_mutex by pulling the wakeup outside */
+	context_pm_get(ce);
+
+	if (mutex_lock_interruptible(&ce->pin_mutex)) {
+		err = -EINTR;
+		goto out_pm;
+	}
 
 	if (likely(!atomic_read(&ce->pin_count))) {
 		intel_wakeref_t wakeref;
@@ -56,16 +94,15 @@ int __intel_context_do_pin(struct intel_context *ce)
 		if (unlikely(!test_bit(CONTEXT_ALLOC_BIT, &ce->flags))) {
 			err = ce->ops->alloc(ce);
 			if (unlikely(err))
-				goto err;
+				goto out_unlock;
 
 			__set_bit(CONTEXT_ALLOC_BIT, &ce->flags);
 		}
 
-		err = 0;
 		with_intel_runtime_pm(ce->engine->uncore->rpm, wakeref)
 			err = ce->ops->pin(ce);
 		if (err)
-			goto err;
+			goto out_unlock;
 
 		CE_TRACE(ce, "pin ring:{head:%04x, tail:%04x}\n",
 			 ce->ring->head, ce->ring->tail);
@@ -76,11 +113,10 @@ int __intel_context_do_pin(struct intel_context *ce)
 	atomic_inc(&ce->pin_count);
 	GEM_BUG_ON(!intel_context_is_pinned(ce)); /* no overflow! */
 
+out_unlock:
 	mutex_unlock(&ce->pin_mutex);
-	return 0;
-
-err:
-	mutex_unlock(&ce->pin_mutex);
+out_pm:
+	context_pm_put(ce);
 	return err;
 }
 
-- 
2.25.0.rc0



More information about the Intel-gfx-trybot mailing list