[Intel-gfx] [RFC 07/11] drm/i915/guc: Add a second client, to be used for preemption

Michał Winiarski michal.winiarski at intel.com
Thu Feb 23 19:14:17 UTC 2017


From: Dave Gordon <david.s.gordon at intel.com>

This second client is created with priority KMD_HIGH, and marked
as preemptive.

v2: Rebase, cleanup, use an array for the second client.

Signed-off-by: Dave Gordon <david.s.gordon at intel.com>
Signed-off-by: Michał Winiarski <michal.winiarski at intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c        |  8 +--
 drivers/gpu/drm/i915/i915_guc_submission.c | 86 ++++++++++++++++++++----------
 drivers/gpu/drm/i915/intel_uc.h            |  9 +++-
 3 files changed, 71 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 1a28b52..10490bf 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2514,7 +2514,7 @@ static int i915_guc_info(struct seq_file *m, void *data)
 	enum intel_engine_id id;
 	u64 total;
 
-	if (!guc->execbuf_client) {
+	if (!guc->client[NORMAL]) {
 		seq_printf(m, "GuC submission %s\n",
 			   HAS_GUC_SCHED(dev_priv) ?
 			   "disabled" :
@@ -2542,8 +2542,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);
+	seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->client[NORMAL]);
+	i915_guc_client_info(m, dev_priv, guc->client[NORMAL]);
+	seq_printf(m, "\nGuC preempt client @ %p:\n", guc->client[PREEMPT]);
+	i915_guc_client_info(m, dev_priv, guc->client[PREEMPT]);
 
 	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 3080735..2a658b9 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -247,6 +247,8 @@ static void guc_ctx_desc_init(struct intel_guc *guc,
 	memset(&desc, 0, sizeof(desc));
 
 	desc.attribute = GUC_CTX_DESC_ATTR_ACTIVE | GUC_CTX_DESC_ATTR_KERNEL;
+	if (client->priority <= GUC_CTX_PRIORITY_HIGH)
+		desc.attribute |= GUC_CTX_DESC_ATTR_PREEMPT;
 	desc.context_id = client->ctx_index;
 	desc.priority = client->priority;
 	desc.db_id = client->doorbell_id;
@@ -344,7 +346,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 *client = request->i915->guc.execbuf_client;
+	struct i915_guc_client *client = request->i915->guc.client[NORMAL];
 	struct guc_process_desc *desc = client->vaddr +
 					client->proc_desc_offset;
 	u32 freespace;
@@ -368,7 +370,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 *client = request->i915->guc.execbuf_client;
+	struct i915_guc_client *client = request->i915->guc.client[NORMAL];
 
 	GEM_BUG_ON(READ_ONCE(client->wq_rsvd) < wqi_size);
 
@@ -518,7 +520,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 = guc->client[NORMAL];
 	int b_ret;
 
 	spin_lock(&client->wq_lock);
@@ -747,8 +749,8 @@ struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size)
 }
 
 static void
-guc_client_free(struct drm_i915_private *dev_priv,
-		struct i915_guc_client *client)
+__guc_client_free(struct drm_i915_private *dev_priv,
+		  struct i915_guc_client *client)
 {
 	struct intel_guc *guc = &dev_priv->guc;
 
@@ -805,7 +807,7 @@ static bool guc_doorbell_check(struct intel_guc *guc, uint16_t db_id)
  */
 static void guc_init_doorbell_hw(struct intel_guc *guc)
 {
-	struct i915_guc_client *client = guc->execbuf_client;
+	struct i915_guc_client *client = guc->client[NORMAL];
 	uint16_t db_id;
 	int i, err;
 
@@ -836,7 +838,7 @@ static void guc_init_doorbell_hw(struct intel_guc *guc)
 }
 
 /**
- * guc_client_alloc() - Allocate an i915_guc_client
+ * __guc_client_alloc() - Allocate an i915_guc_client
  * @dev_priv:	driver private data structure
  * @priority:	four levels priority _CRITICAL, _HIGH, _NORMAL and _LOW
  * 		The kernel client to replace ExecList submission is created with
@@ -845,8 +847,8 @@ static void guc_init_doorbell_hw(struct intel_guc *guc)
  * Return:	An i915_guc_client object if success, else NULL.
  */
 static struct i915_guc_client *
-guc_client_alloc(struct drm_i915_private *dev_priv,
-		 uint32_t priority)
+__guc_client_alloc(struct drm_i915_private *dev_priv,
+		   uint32_t priority)
 {
 	struct i915_guc_client *client;
 	struct intel_guc *guc = &dev_priv->guc;
@@ -910,7 +912,7 @@ guc_client_alloc(struct drm_i915_private *dev_priv,
 	guc_ctx_desc_init(guc, client);
 
 	/* For runtime client allocation we need to enable the doorbell. Not
-	 * required yet for the static execbuf_client as this special kernel
+	 * required yet for the static client as this special kernel
 	 * client is enabled from i915_guc_submission_enable().
 	 *
 	 * guc_update_doorbell_id(guc, client, db_id);
@@ -924,7 +926,7 @@ guc_client_alloc(struct drm_i915_private *dev_priv,
 	return client;
 
 err:
-	guc_client_free(dev_priv, client);
+	__guc_client_free(dev_priv, client);
 	return NULL;
 }
 
@@ -1021,6 +1023,45 @@ static void guc_addon_create(struct intel_guc *guc)
 	kunmap(page);
 }
 
+static void guc_free_clients(struct drm_i915_private *dev_priv)
+{
+	struct intel_guc *guc = &dev_priv->guc;
+	struct i915_guc_client *client;
+
+	client = fetch_and_zero(&guc->client[NORMAL]);
+	if (client)
+		__guc_client_free(dev_priv, client);
+
+	client = fetch_and_zero(&guc->client[PREEMPT]);
+	if (client)
+		__guc_client_free(dev_priv, client);
+}
+
+static int guc_alloc_clients(struct drm_i915_private *dev_priv)
+{
+	struct intel_guc *guc = &dev_priv->guc;
+
+	guc->client[NORMAL] = __guc_client_alloc(dev_priv,
+						 GUC_CTX_PRIORITY_KMD_NORMAL);
+	if (!guc->client[NORMAL]) {
+		DRM_ERROR("Failed to create GuC client for execbuf!\n");
+		goto err;
+	}
+
+	guc->client[PREEMPT] = __guc_client_alloc(dev_priv,
+						  GUC_CTX_PRIORITY_KMD_HIGH);
+	if (!guc->client[PREEMPT]) {
+		DRM_ERROR("Failed to create GuC client for execbuf!\n");
+		goto err;
+	}
+
+	return 0;
+
+err:
+	guc_free_clients(dev_priv);
+	return -ENOMEM;
+}
+
 /*
  * Set up the memory resources to be shared with the GuC.  At this point,
  * we require just one object that can be mapped through the GGTT.
@@ -1055,18 +1096,12 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
 	intel_guc_log_create(guc);
 	guc_addon_create(guc);
 
-	guc->execbuf_client = guc_client_alloc(dev_priv,
-					       GUC_CTX_PRIORITY_KMD_NORMAL);
-	if (!guc->execbuf_client) {
-		DRM_ERROR("Failed to create GuC client for execbuf!\n");
-		goto err;
+	if (guc_alloc_clients(dev_priv) != 0) {
+		i915_guc_submission_fini(dev_priv);
+		return -ENOMEM;
 	}
 
 	return 0;
-
-err:
-	i915_guc_submission_fini(dev_priv);
-	return -ENOMEM;
 }
 
 static void guc_reset_wq(struct i915_guc_client *client)
@@ -1083,7 +1118,7 @@ static void guc_reset_wq(struct i915_guc_client *client)
 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 i915_guc_client *client = guc->client[NORMAL];
 	struct intel_engine_cs *engine;
 	enum intel_engine_id id;
 
@@ -1129,7 +1164,7 @@ void i915_guc_submission_disable(struct drm_i915_private *dev_priv)
 {
 	struct intel_guc *guc = &dev_priv->guc;
 
-	if (!guc->execbuf_client)
+	if (!guc->client[NORMAL])
 		return;
 
 	/* Revert back to manual ELSP submission */
@@ -1139,13 +1174,8 @@ 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;
-
-	client = fetch_and_zero(&guc->execbuf_client);
-	if (!client)
-		return;
 
-	guc_client_free(dev_priv, client);
+	guc_free_clients(dev_priv);
 
 	i915_vma_unpin_and_release(&guc->ads_vma);
 	i915_vma_unpin_and_release(&guc->log.vma);
diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h
index d74f4d3..9dcd8fa 100644
--- a/drivers/gpu/drm/i915/intel_uc.h
+++ b/drivers/gpu/drm/i915/intel_uc.h
@@ -146,6 +146,13 @@ struct intel_guc_log {
 	u32 flush_count[GUC_MAX_LOG_BUFFER];
 };
 
+#define I915_GUC_NUM_CLIENTS 2
+
+enum i915_guc_client_id {
+        NORMAL = 0,
+        PREEMPT
+};
+
 struct intel_guc {
 	struct intel_uc_fw fw;
 	struct intel_guc_log log;
@@ -157,7 +164,7 @@ struct intel_guc {
 	struct i915_vma *ctx_pool_vma;
 	struct ida ctx_ids;
 
-	struct i915_guc_client *execbuf_client;
+	struct i915_guc_client *client[I915_GUC_NUM_CLIENTS];
 
 	DECLARE_BITMAP(doorbell_bitmap, GUC_MAX_DOORBELLS);
 	uint32_t db_cacheline;		/* Cyclic counter mod pagesize	*/
-- 
2.9.3



More information about the Intel-gfx mailing list