[PATCH 10/10] drm/i915/guc: Keep a wq per engine

Chris Wilson chris at chris-wilson.co.uk
Mon Nov 21 10:13:43 UTC 2016


Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_debugfs.c        |   6 +-
 drivers/gpu/drm/i915/i915_guc_submission.c | 114 ++++++++++++-----------------
 drivers/gpu/drm/i915/intel_guc.h           |   2 -
 drivers/gpu/drm/i915/intel_ringbuffer.h    |   2 +
 4 files changed, 51 insertions(+), 73 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 2521a91762e7..350d4a849cba 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2478,8 +2478,10 @@ static int i915_guc_info(struct seq_file *m, void *data)
 	}
 	seq_printf(m, "\t%s: %llu\n", "Total", total);
 
-	seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->execbuf_client);
-	i915_guc_client_info(m, dev_priv, guc->execbuf_client);
+	for_each_engine(engine, dev_priv, id) {
+		seq_printf(m, "\nGuC %s client\n", engine->name);
+		i915_guc_client_info(m, dev_priv, engine->guc_client);
+	}
 
 	i915_guc_log_info(m, dev_priv);
 
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index e12ff881d38d..31ab64502f48 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -157,8 +157,7 @@ static int host2guc_release_doorbell(struct intel_guc *guc,
 	return host2guc_action(guc, data, 2);
 }
 
-static int host2guc_sample_forcewake(struct intel_guc *guc,
-				     struct i915_guc_client *client)
+static int host2guc_sample_forcewake(struct intel_guc *guc)
 {
 	struct drm_i915_private *dev_priv = guc_to_i915(guc);
 	u32 data[2];
@@ -457,7 +456,7 @@ static void guc_ctx_desc_fini(struct intel_guc *guc,
 int i915_guc_wq_reserve(struct drm_i915_gem_request *request)
 {
 	const size_t wqi_size = sizeof(struct guc_wq_item);
-	struct i915_guc_client *gc = request->i915->guc.execbuf_client;
+	struct i915_guc_client *gc = request->engine->guc_client;
 	struct guc_process_desc *desc = gc->vaddr + gc->proc_desc_offset;
 	u32 freespace;
 	int ret;
@@ -480,7 +479,7 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *request)
 void i915_guc_wq_unreserve(struct drm_i915_gem_request *request)
 {
 	const size_t wqi_size = sizeof(struct guc_wq_item);
-	struct i915_guc_client *gc = request->i915->guc.execbuf_client;
+	struct i915_guc_client *gc = request->engine->guc_client;
 
 	GEM_BUG_ON(READ_ONCE(gc->wq_rsvd) < wqi_size);
 
@@ -622,7 +621,7 @@ static void __i915_guc_submit(struct drm_i915_gem_request *rq)
 	struct intel_engine_cs *engine = rq->engine;
 	unsigned int engine_id = engine->id;
 	struct intel_guc *guc = &rq->i915->guc;
-	struct i915_guc_client *client = guc->execbuf_client;
+	struct i915_guc_client *client = engine->guc_client;
 	int b_ret;
 
 	spin_lock(&client->wq_lock);
@@ -746,59 +745,28 @@ guc_client_free(struct drm_i915_private *dev_priv,
 	kfree(client);
 }
 
-/* Check that a doorbell register is in the expected state */
-static bool guc_doorbell_check(struct intel_guc *guc, uint16_t db_id)
+static void guc_init_doorbell_hw(struct intel_guc *guc)
 {
 	struct drm_i915_private *dev_priv = guc_to_i915(guc);
-	i915_reg_t drbreg = GEN8_DRBREGL(db_id);
-	uint32_t value = I915_READ(drbreg);
-	bool enabled = (value & GUC_DOORBELL_ENABLED) != 0;
-	bool expected = test_bit(db_id, guc->doorbell_bitmap);
-
-	if (enabled == expected)
-		return true;
-
-	DRM_DEBUG_DRIVER("Doorbell %d (reg 0x%x) 0x%x, should be %s\n",
-			 db_id, drbreg.reg, value,
-			 expected ? "active" : "inactive");
-
-	return false;
-}
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 
-/*
- * Borrow the first client to set up & tear down each unused doorbell
- * in turn, to ensure that all doorbell h/w is (re)initialised.
- */
-static void guc_init_doorbell_hw(struct intel_guc *guc)
-{
-	struct i915_guc_client *client = guc->execbuf_client;
-	uint16_t db_id;
-	int i, err;
+	for_each_engine(engine, dev_priv, id)
+		guc_disable_doorbell(guc, engine->guc_client);
 
-	guc_disable_doorbell(guc, client);
+	for_each_engine(engine, dev_priv, id) {
+		struct i915_guc_client *client = engine->guc_client;
+		uint16_t db_id;
+		int err;
 
-	for (i = 0; i < GUC_MAX_DOORBELLS; ++i) {
-		/* Skip if doorbell is OK */
-		if (guc_doorbell_check(guc, i))
-			continue;
+		db_id = select_doorbell_register(guc, client->priority);
+		WARN_ON(db_id == GUC_INVALID_DOORBELL_ID);
 
-		err = guc_update_doorbell_id(guc, client, i);
+		err = guc_update_doorbell_id(guc, client, db_id);
 		if (err)
-			DRM_DEBUG_DRIVER("Doorbell %d update failed, err %d\n",
-					i, err);
+			DRM_WARN("Failed to restore doorbell to %d, err %d\n",
+				 db_id, err);
 	}
-
-	db_id = select_doorbell_register(guc, client->priority);
-	WARN_ON(db_id == GUC_INVALID_DOORBELL_ID);
-
-	err = guc_update_doorbell_id(guc, client, db_id);
-	if (err)
-		DRM_WARN("Failed to restore doorbell to %d, err %d\n",
-			 db_id, err);
-
-	/* Read back & verify all doorbell registers */
-	for (i = 0; i < GUC_MAX_DOORBELLS; ++i)
-		(void)guc_doorbell_check(guc, i);
 }
 
 /**
@@ -1484,6 +1452,8 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
 	const size_t poolsize = GUC_MAX_GPU_CONTEXTS * ctxsize;
 	const size_t gemsize = round_up(poolsize, PAGE_SIZE);
 	struct intel_guc *guc = &dev_priv->guc;
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	struct i915_vma *vma;
 
 	if (!HAS_GUC_SCHED(dev_priv))
@@ -1509,13 +1479,16 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
 	guc_log_create(guc);
 	guc_addon_create(guc);
 
-	guc->execbuf_client = guc_client_alloc(dev_priv,
-					       INTEL_INFO(dev_priv)->ring_mask,
-					       GUC_CTX_PRIORITY_KMD_NORMAL,
-					       dev_priv->kernel_context);
-	if (!guc->execbuf_client) {
-		DRM_ERROR("Failed to create GuC client for execbuf!\n");
-		goto err;
+	for_each_engine(engine, dev_priv, id) {
+		engine->guc_client =
+			guc_client_alloc(dev_priv,
+					 intel_engine_flag(engine),
+					 GUC_CTX_PRIORITY_KMD_NORMAL,
+					 dev_priv->kernel_context);
+		if (!engine->guc_client) {
+			DRM_ERROR("Failed to create GuC client for execbuf!\n");
+			goto err;
+		}
 	}
 
 	return 0;
@@ -1538,25 +1511,25 @@ static void guc_reset_wq(struct i915_guc_client *gc)
 int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
 {
 	struct intel_guc *guc = &dev_priv->guc;
-	struct i915_guc_client *client = guc->execbuf_client;
 	struct intel_engine_cs *engine;
 	enum intel_engine_id id;
 
-	if (!client)
+	if (!HAS_GUC_SCHED(dev_priv))
 		return -ENODEV;
 
-	guc_reset_wq(client);
-	host2guc_sample_forcewake(guc, client);
+	host2guc_sample_forcewake(guc);
 	guc_init_doorbell_hw(guc);
 
 	/* Take over from manual control of ELSP (execlists) */
 	for_each_engine(engine, dev_priv, id) {
+		struct i915_guc_client *client = engine->guc_client;
 		struct drm_i915_gem_request *rq;
 
 		engine->submit_request = i915_guc_submit;
 		engine->schedule = NULL;
 
 		/* Replay the current set of previously submitted requests */
+		guc_reset_wq(client);
 		list_for_each_entry(rq, &engine->timeline->requests, link) {
 			client->wq_rsvd += sizeof(struct guc_wq_item);
 			__i915_guc_submit(rq);
@@ -1568,9 +1541,7 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
 
 void i915_guc_submission_disable(struct drm_i915_private *dev_priv)
 {
-	struct intel_guc *guc = &dev_priv->guc;
-
-	if (!guc->execbuf_client)
+	if (!HAS_GUC_SCHED(dev_priv))
 		return;
 
 	/* Revert back to manual ELSP submission */
@@ -1580,13 +1551,18 @@ void i915_guc_submission_disable(struct drm_i915_private *dev_priv)
 void i915_guc_submission_fini(struct drm_i915_private *dev_priv)
 {
 	struct intel_guc *guc = &dev_priv->guc;
-	struct i915_guc_client *client;
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 
-	client = fetch_and_zero(&guc->execbuf_client);
-	if (!client)
-		return;
+	for_each_engine(engine, dev_priv, id) {
+		struct i915_guc_client *client;
 
-	guc_client_free(dev_priv, client);
+		client = fetch_and_zero(&engine->guc_client);
+		if (!client)
+			continue;
+
+		guc_client_free(dev_priv, client);
+	}
 
 	i915_vma_unpin_and_release(&guc->ads_vma);
 	i915_vma_unpin_and_release(&guc->log.vma);
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index dc570a6d612e..6c0bf7f1202e 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -150,8 +150,6 @@ struct intel_guc {
 	struct i915_vma *ctx_pool_vma;
 	struct ida ctx_ids;
 
-	struct i915_guc_client *execbuf_client;
-
 	DECLARE_BITMAP(doorbell_bitmap, GUC_MAX_DOORBELLS);
 	uint32_t db_cacheline;		/* Cyclic counter mod pagesize	*/
 
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 3466b4e77e7c..bf22efad97ae 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -355,6 +355,8 @@ struct intel_engine_cs {
 	bool preempt_wa;
 	u32 ctx_desc_template;
 
+	struct i915_guc_client *guc_client;
+
 	struct i915_gem_context *last_context;
 
 	struct intel_engine_hangcheck hangcheck;
-- 
2.10.2



More information about the Intel-gfx-trybot mailing list