All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] Preemption with GuC, third attempt
@ 2017-10-19 18:36 Michał Winiarski
  2017-10-19 18:36 ` [PATCH 01/14] drm/i915/guc: Do not use 0 for GuC doorbell cookie Michał Winiarski
                   ` (15 more replies)
  0 siblings, 16 replies; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx

It turns out that preempt failures were caused by GuC not expecting multiple
workitems when preempt action was requested.
Another thing that deserves attention is the workaround for missing
USER_INTERRUPT. The value I've used for the delayed work timer is just a
semi-educated guess at this point.
There's also small oneline doorbell cleanup (we weren't observing any problems
with it, but Sagar pointed out that doorbell cookie with value 0 seems to be
reserved), and removal of unused variable (pointed out by Michel)

Dave Gordon (1):
  drm/i915/guc: Add a second client, to be used for preemption

Michał Winiarski (13):
  drm/i915/guc: Do not use 0 for GuC doorbell cookie
  drm/i915/guc: Extract GuC stage desc pool creation into a helper
  drm/i915/guc: Allocate separate shared data object for GuC
    communication
  drm/i915/guc: Initialize GuC before restarting engines
  drm/i915/guc: Add preemption action to GuC firmware interface
  drm/i915/guc: Split guc_wq_item_append
  drm/i915: Extract "emit write" part of emit breadcrumb functions
  drm/i915: Add information needed to track engine preempt state
  drm/i915/guc: Keep request->priority for its lifetime
  drm/i915: Rename helpers used for unwinding, use macro for can_preempt
  drm/i915/guc: Preemption! With GuC
  drm/i915/guc: Workaround the missing user interrupt after preemption
  HAX Enable GuC Submission for CI

 drivers/gpu/drm/i915/i915_debugfs.c        |  11 +-
 drivers/gpu/drm/i915/i915_drv.c            |   5 +-
 drivers/gpu/drm/i915/i915_drv.h            |   2 +
 drivers/gpu/drm/i915/i915_gem.c            |  20 +-
 drivers/gpu/drm/i915/i915_gem_gtt.c        |   8 +-
 drivers/gpu/drm/i915/i915_guc_submission.c | 511 +++++++++++++++++++++++------
 drivers/gpu/drm/i915/i915_params.h         |   4 +-
 drivers/gpu/drm/i915/intel_engine_cs.c     |   6 +-
 drivers/gpu/drm/i915/intel_guc.c           |  14 +-
 drivers/gpu/drm/i915/intel_guc.h           |  20 +-
 drivers/gpu/drm/i915/intel_guc_fwif.h      |  40 +++
 drivers/gpu/drm/i915/intel_lrc.c           |  56 ++--
 drivers/gpu/drm/i915/intel_lrc.h           |   1 -
 drivers/gpu/drm/i915/intel_ringbuffer.h    |  53 +++
 drivers/gpu/drm/i915/intel_uncore.c        |   2 +-
 15 files changed, 575 insertions(+), 178 deletions(-)

-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 01/14] drm/i915/guc: Do not use 0 for GuC doorbell cookie
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-21  6:28   ` Sagar Arun Kamble
  2017-10-19 18:36 ` [PATCH 02/14] drm/i915/guc: Extract GuC stage desc pool creation into a helper Michał Winiarski
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx

Apparently, this value is reserved and may be interpreted as changing
doorbell ownership. Even though we're not observing any side effects
now, let's skip over it to be consistent with the spec.

Suggested-by: Sagar Arun Kamble <sagar.a.kamble@intel.com>
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
---
 drivers/gpu/drm/i915/i915_guc_submission.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index a2e8114b739d..02ca2a412c62 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -475,9 +475,10 @@ static void guc_ring_doorbell(struct i915_guc_client *client)
 	/* pointer of current doorbell cacheline */
 	db = __get_doorbell(client);
 
-	/* we're not expecting the doorbell cookie to change behind our back */
+	/* we're not expecting the doorbell cookie to change behind our back,
+	 * we also need to treat 0 as a reserved value */
 	cookie = READ_ONCE(db->cookie);
-	WARN_ON_ONCE(xchg(&db->cookie, cookie + 1) != cookie);
+	WARN_ON_ONCE(xchg(&db->cookie, cookie + 1 ?: cookie + 2) != cookie);
 
 	/* XXX: doorbell was lost and need to acquire it again */
 	GEM_BUG_ON(db->db_status != GUC_DOORBELL_ENABLED);
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 02/14] drm/i915/guc: Extract GuC stage desc pool creation into a helper
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
  2017-10-19 18:36 ` [PATCH 01/14] drm/i915/guc: Do not use 0 for GuC doorbell cookie Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-19 18:36 ` [PATCH v2 03/14] drm/i915/guc: Allocate separate shared data object for GuC communication Michał Winiarski
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx

Since it's a two-step process, we can have a cleaner error handling in
the caller if we do the allocations in a helper.

Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Jeff McGee <jeff.mcgee@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Oscar Mateo <oscar.mateo@intel.com>
Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
---
 drivers/gpu/drm/i915/i915_guc_submission.c | 65 +++++++++++++++++-------------
 1 file changed, 38 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 02ca2a412c62..4891eb1d9289 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -311,6 +311,37 @@ static void guc_proc_desc_init(struct intel_guc *guc,
 	desc->priority = client->priority;
 }
 
+static int guc_stage_desc_pool_create(struct intel_guc *guc)
+{
+	struct i915_vma *vma;
+	void *vaddr;
+
+	vma = intel_guc_allocate_vma(guc,
+				     PAGE_ALIGN(sizeof(struct guc_stage_desc) *
+				     GUC_MAX_STAGE_DESCRIPTORS));
+	if (IS_ERR(vma))
+		return PTR_ERR(vma);
+
+	vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB);
+	if (IS_ERR(vaddr)) {
+		i915_vma_unpin_and_release(&vma);
+		return PTR_ERR(vaddr);
+	}
+
+	guc->stage_desc_pool = vma;
+	guc->stage_desc_pool_vaddr = vaddr;
+	ida_init(&guc->stage_ids);
+
+	return 0;
+}
+
+static void guc_stage_desc_pool_destroy(struct intel_guc *guc)
+{
+	ida_destroy(&guc->stage_ids);
+	i915_gem_object_unpin_map(guc->stage_desc_pool->obj);
+	i915_vma_unpin_and_release(&guc->stage_desc_pool);
+}
+
 /*
  * Initialise/clear the stage descriptor shared with the GuC firmware.
  *
@@ -972,47 +1003,29 @@ static void guc_ads_destroy(struct intel_guc *guc)
 int i915_guc_submission_init(struct drm_i915_private *dev_priv)
 {
 	struct intel_guc *guc = &dev_priv->guc;
-	struct i915_vma *vma;
-	void *vaddr;
 	int ret;
 
 	if (guc->stage_desc_pool)
 		return 0;
 
-	vma = intel_guc_allocate_vma(guc,
-				PAGE_ALIGN(sizeof(struct guc_stage_desc) *
-					GUC_MAX_STAGE_DESCRIPTORS));
-	if (IS_ERR(vma))
-		return PTR_ERR(vma);
-
-	guc->stage_desc_pool = vma;
-
-	vaddr = i915_gem_object_pin_map(guc->stage_desc_pool->obj, I915_MAP_WB);
-	if (IS_ERR(vaddr)) {
-		ret = PTR_ERR(vaddr);
-		goto err_vma;
-	}
-
-	guc->stage_desc_pool_vaddr = vaddr;
+	ret = guc_stage_desc_pool_create(guc);
+	if (ret)
+		return ret;
 
 	ret = intel_guc_log_create(guc);
 	if (ret < 0)
-		goto err_vaddr;
+		goto err_stage_desc_pool;
 
 	ret = guc_ads_create(guc);
 	if (ret < 0)
 		goto err_log;
 
-	ida_init(&guc->stage_ids);
-
 	return 0;
 
 err_log:
 	intel_guc_log_destroy(guc);
-err_vaddr:
-	i915_gem_object_unpin_map(guc->stage_desc_pool->obj);
-err_vma:
-	i915_vma_unpin_and_release(&guc->stage_desc_pool);
+err_stage_desc_pool:
+	guc_stage_desc_pool_destroy(guc);
 	return ret;
 }
 
@@ -1020,11 +1033,9 @@ void i915_guc_submission_fini(struct drm_i915_private *dev_priv)
 {
 	struct intel_guc *guc = &dev_priv->guc;
 
-	ida_destroy(&guc->stage_ids);
 	guc_ads_destroy(guc);
 	intel_guc_log_destroy(guc);
-	i915_gem_object_unpin_map(guc->stage_desc_pool->obj);
-	i915_vma_unpin_and_release(&guc->stage_desc_pool);
+	guc_stage_desc_pool_destroy(guc);
 }
 
 static void guc_interrupts_capture(struct drm_i915_private *dev_priv)
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 03/14] drm/i915/guc: Allocate separate shared data object for GuC communication
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
  2017-10-19 18:36 ` [PATCH 01/14] drm/i915/guc: Do not use 0 for GuC doorbell cookie Michał Winiarski
  2017-10-19 18:36 ` [PATCH 02/14] drm/i915/guc: Extract GuC stage desc pool creation into a helper Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-19 18:36 ` [PATCH 04/14] drm/i915/guc: Initialize GuC before restarting engines Michał Winiarski
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx

We were using first page of kernel context render state for sharing data
with GuC. While it's justified by the fact that those pages are not used
(note, GuC still enforces this layout and refuses to work if we remove
the extra page in front), it's also confusing (why are we using this
particular page?). Let's allocate a separate object instead.

v2: Drop kernel_context from GuC suspend/resume action handlers (Michel)

Suggested-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Jeff McGee <jeff.mcgee@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Oscar Mateo <oscar.mateo@intel.com>
Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
---
 drivers/gpu/drm/i915/i915_guc_submission.c | 36 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_guc.c           | 14 ++----------
 drivers/gpu/drm/i915/intel_guc.h           |  2 ++
 3 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 4891eb1d9289..7097d81f4ac2 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -437,6 +437,33 @@ static void guc_stage_desc_fini(struct intel_guc *guc,
 	memset(desc, 0, sizeof(*desc));
 }
 
+static int guc_shared_data_create(struct intel_guc *guc)
+{
+	struct i915_vma *vma;
+	void *vaddr;
+
+	vma = intel_guc_allocate_vma(guc, PAGE_SIZE);
+	if (IS_ERR(vma))
+		return PTR_ERR(vma);
+
+	vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB);
+	if (IS_ERR(vaddr)) {
+		i915_vma_unpin_and_release(&vma);
+		return PTR_ERR(vaddr);
+	}
+
+	guc->shared_data = vma;
+	guc->shared_data_vaddr = vaddr;
+
+	return 0;
+}
+
+static void guc_shared_data_destroy(struct intel_guc *guc)
+{
+	i915_gem_object_unpin_map(guc->shared_data->obj);
+	i915_vma_unpin_and_release(&guc->shared_data);
+}
+
 /* Construct a Work Item and append it to the GuC's Work Queue */
 static void guc_wq_item_append(struct i915_guc_client *client,
 			       struct drm_i915_gem_request *rq)
@@ -1012,9 +1039,13 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
 	if (ret)
 		return ret;
 
+	ret = guc_shared_data_create(guc);
+	if (ret)
+		goto err_stage_desc_pool;
+
 	ret = intel_guc_log_create(guc);
 	if (ret < 0)
-		goto err_stage_desc_pool;
+		goto err_shared_data;
 
 	ret = guc_ads_create(guc);
 	if (ret < 0)
@@ -1024,6 +1055,8 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
 
 err_log:
 	intel_guc_log_destroy(guc);
+err_shared_data:
+	guc_shared_data_destroy(guc);
 err_stage_desc_pool:
 	guc_stage_desc_pool_destroy(guc);
 	return ret;
@@ -1035,6 +1068,7 @@ void i915_guc_submission_fini(struct drm_i915_private *dev_priv)
 
 	guc_ads_destroy(guc);
 	intel_guc_log_destroy(guc);
+	guc_shared_data_destroy(guc);
 	guc_stage_desc_pool_destroy(guc);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c
index 10037c0fdf95..f74d50fdaeb0 100644
--- a/drivers/gpu/drm/i915/intel_guc.c
+++ b/drivers/gpu/drm/i915/intel_guc.c
@@ -268,7 +268,6 @@ int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset)
 int intel_guc_suspend(struct drm_i915_private *dev_priv)
 {
 	struct intel_guc *guc = &dev_priv->guc;
-	struct i915_gem_context *ctx;
 	u32 data[3];
 
 	if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS)
@@ -276,14 +275,10 @@ int intel_guc_suspend(struct drm_i915_private *dev_priv)
 
 	gen9_disable_guc_interrupts(dev_priv);
 
-	ctx = dev_priv->kernel_context;
-
 	data[0] = INTEL_GUC_ACTION_ENTER_S_STATE;
 	/* any value greater than GUC_POWER_D0 */
 	data[1] = GUC_POWER_D1;
-	/* first page is shared data with GuC */
-	data[2] = guc_ggtt_offset(ctx->engine[RCS].state) +
-		  LRC_GUCSHR_PN * PAGE_SIZE;
+	data[2] = guc_ggtt_offset(guc->shared_data);
 
 	return intel_guc_send(guc, data, ARRAY_SIZE(data));
 }
@@ -295,7 +290,6 @@ int intel_guc_suspend(struct drm_i915_private *dev_priv)
 int intel_guc_resume(struct drm_i915_private *dev_priv)
 {
 	struct intel_guc *guc = &dev_priv->guc;
-	struct i915_gem_context *ctx;
 	u32 data[3];
 
 	if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS)
@@ -304,13 +298,9 @@ int intel_guc_resume(struct drm_i915_private *dev_priv)
 	if (i915_modparams.guc_log_level >= 0)
 		gen9_enable_guc_interrupts(dev_priv);
 
-	ctx = dev_priv->kernel_context;
-
 	data[0] = INTEL_GUC_ACTION_EXIT_S_STATE;
 	data[1] = GUC_POWER_D0;
-	/* first page is shared data with GuC */
-	data[2] = guc_ggtt_offset(ctx->engine[RCS].state) +
-		  LRC_GUCSHR_PN * PAGE_SIZE;
+	data[2] = guc_ggtt_offset(guc->shared_data);
 
 	return intel_guc_send(guc, data, ARRAY_SIZE(data));
 }
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 418450b1ae27..aa1583167b0a 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -54,6 +54,8 @@ struct intel_guc {
 	struct i915_vma *stage_desc_pool;
 	void *stage_desc_pool_vaddr;
 	struct ida stage_ids;
+	struct i915_vma *shared_data;
+	void *shared_data_vaddr;
 
 	struct i915_guc_client *execbuf_client;
 
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 04/14] drm/i915/guc: Initialize GuC before restarting engines
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
                   ` (2 preceding siblings ...)
  2017-10-19 18:36 ` [PATCH v2 03/14] drm/i915/guc: Allocate separate shared data object for GuC communication Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-25 18:44   ` Chris Wilson
  2017-10-19 18:36 ` [PATCH 05/14] drm/i915/guc: Add preemption action to GuC firmware interface Michał Winiarski
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx; +Cc: Mika Kuoppala

Now that we're handling request resubmission the same way as regular
submission (from the tasklet), we can move GuC initialization earlier,
before restarting the engines. This way, we're no longer being in the
state of flux during engine restart - we're already in user requested
submission mode.

Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Michel Thierry <michel.thierry@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Cc: Oscar Mateo <oscar.mateo@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem.c            | 10 +++++-----
 drivers/gpu/drm/i915/i915_guc_submission.c |  7 -------
 drivers/gpu/drm/i915/intel_lrc.c           |  2 +-
 3 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index d699ea3ab80b..ef14c6d570dc 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4881,6 +4881,11 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
 		goto out;
 	}
 
+	/* We can't enable contexts until all firmware is loaded */
+	ret = intel_uc_init_hw(dev_priv);
+	if (ret)
+		goto out;
+
 	/* Need to do basic initialisation of all rings first: */
 	ret = __i915_gem_restart_engines(dev_priv);
 	if (ret)
@@ -4888,11 +4893,6 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
 
 	intel_mocs_init_l3cc_table(dev_priv);
 
-	/* We can't enable contexts until all firmware is loaded */
-	ret = intel_uc_init_hw(dev_priv);
-	if (ret)
-		goto out;
-
 out:
 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 	return ret;
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 7097d81f4ac2..0bd1fcffa78d 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -1189,14 +1189,7 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
 
 	for_each_engine(engine, dev_priv, id) {
 		struct intel_engine_execlists * const execlists = &engine->execlists;
-		/* The tasklet was initialised by execlists, and may be in
-		 * a state of flux (across a reset) and so we just want to
-		 * take over the callback without changing any other state
-		 * in the tasklet.
-		 */
 		execlists->irq_tasklet.func = i915_guc_irq_handler;
-		clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted);
-		tasklet_schedule(&execlists->irq_tasklet);
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 7f45dd7dc3e5..a1e177258e3c 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1463,7 +1463,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine)
 	execlists->preempt = false;
 
 	/* After a GPU reset, we may have requests to replay */
-	if (!i915_modparams.enable_guc_submission && execlists->first)
+	if (execlists->first)
 		tasklet_schedule(&execlists->irq_tasklet);
 
 	return 0;
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 05/14] drm/i915/guc: Add preemption action to GuC firmware interface
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
                   ` (3 preceding siblings ...)
  2017-10-19 18:36 ` [PATCH 04/14] drm/i915/guc: Initialize GuC before restarting engines Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-19 18:36 ` [PATCH v2 06/14] drm/i915/guc: Add a second client, to be used for preemption Michał Winiarski
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx

We're using GuC action to request preemption. However, after requesting
preemption we need to wait for GuC to finish its own post-processing
before we start submitting our requests. Firmware is using shared
context to report its status.
Let's update GuC firmware interface with those new definitions.

Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Jeff McGee <jeff.mcgee@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Oscar Mateo <oscar.mateo@intel.com>
Reviewed-by: Jeff McGee <jeff.mcgee@intel.com>
---
 drivers/gpu/drm/i915/intel_guc_fwif.h | 40 +++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 80c507435458..bc9897f96e56 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -544,9 +544,36 @@ union guc_log_control {
 	u32 value;
 } __packed;
 
+struct guc_ctx_report {
+	u32 report_return_status;
+	u32 reserved1[64];
+	u32 affected_count;
+	u32 reserved2[2];
+} __packed;
+
+/* GuC Shared Context Data Struct */
+struct guc_shared_ctx_data {
+	u32 addr_of_last_preempted_data_low;
+	u32 addr_of_last_preempted_data_high;
+	u32 addr_of_last_preempted_data_high_tmp;
+	u32 padding;
+	u32 is_mapped_to_proxy;
+	u32 proxy_ctx_id;
+	u32 engine_reset_ctx_id;
+	u32 media_reset_count;
+	u32 reserved1[8];
+	u32 uk_last_ctx_switch_reason;
+	u32 was_reset;
+	u32 lrca_gpu_addr;
+	u64 execlist_ctx;
+	u32 reserved2[66];
+	struct guc_ctx_report preempt_ctx_report[GUC_MAX_ENGINES_NUM];
+} __packed;
+
 /* This Action will be programmed in C180 - SOFT_SCRATCH_O_REG */
 enum intel_guc_action {
 	INTEL_GUC_ACTION_DEFAULT = 0x0,
+	INTEL_GUC_ACTION_REQUEST_PREEMPTION = 0x2,
 	INTEL_GUC_ACTION_SAMPLE_FORCEWAKE = 0x6,
 	INTEL_GUC_ACTION_ALLOCATE_DOORBELL = 0x10,
 	INTEL_GUC_ACTION_DEALLOCATE_DOORBELL = 0x20,
@@ -562,6 +589,19 @@ enum intel_guc_action {
 	INTEL_GUC_ACTION_LIMIT
 };
 
+enum intel_guc_preempt_options {
+	INTEL_GUC_PREEMPT_OPTION_IMMEDIATE = 0x1,
+	INTEL_GUC_PREEMPT_OPTION_DROP_WORK_Q = 0x4,
+	INTEL_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q = 0x8,
+};
+
+enum intel_guc_report_status {
+	INTEL_GUC_REPORT_STATUS_UNKNOWN = 0x0,
+	INTEL_GUC_REPORT_STATUS_ACKED = 0x1,
+	INTEL_GUC_REPORT_STATUS_ERROR = 0x2,
+	INTEL_GUC_REPORT_STATUS_COMPLETE = 0x4,
+};
+
 /*
  * The GuC sends its response to a command by overwriting the
  * command in SS0. The response is distinguishable from a command
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 06/14] drm/i915/guc: Add a second client, to be used for preemption
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
                   ` (4 preceding siblings ...)
  2017-10-19 18:36 ` [PATCH 05/14] drm/i915/guc: Add preemption action to GuC firmware interface Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-19 19:36   ` Michal Wajdeczko
  2017-10-19 18:36 ` [PATCH 07/14] drm/i915/guc: Split guc_wq_item_append Michał Winiarski
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx; +Cc: Dave Gordon

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

This second client is created with priority KMD_HIGH, and marked
as preemptive. This will allow us to request preemption using GuC actions.

v2: Extract clients creation into a helper, debugfs fixups. (Michał)
Recreate doorbell on init. (Daniele)
Move clients into an array.

Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Jeff McGee <jeff.mcgee@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Oscar Mateo <oscar.mateo@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c        |  11 +--
 drivers/gpu/drm/i915/i915_guc_submission.c | 107 ++++++++++++++++++++---------
 drivers/gpu/drm/i915/intel_guc.h           |   9 ++-
 drivers/gpu/drm/i915/intel_uncore.c        |   2 +-
 4 files changed, 91 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index c65e381b85f3..daf7a16a4ee2 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2459,7 +2459,7 @@ static bool check_guc_submission(struct seq_file *m)
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	const struct intel_guc *guc = &dev_priv->guc;
 
-	if (!guc->execbuf_client) {
+	if (!guc->client[SUBMIT]) {
 		seq_printf(m, "GuC submission %s\n",
 			   HAS_GUC_SCHED(dev_priv) ?
 			   "disabled" :
@@ -2474,6 +2474,7 @@ static int i915_guc_info(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	const struct intel_guc *guc = &dev_priv->guc;
+	u32 i;
 
 	if (!check_guc_submission(m))
 		return 0;
@@ -2482,8 +2483,10 @@ static int i915_guc_info(struct seq_file *m, void *data)
 	seq_printf(m, "\t%*pb\n", GUC_NUM_DOORBELLS, guc->doorbell_bitmap);
 	seq_printf(m, "Doorbell next cacheline: 0x%x\n\n", guc->db_cacheline);
 
-	seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->execbuf_client);
-	i915_guc_client_info(m, dev_priv, guc->execbuf_client);
+	for (i = 0; i < I915_GUC_NUM_CLIENTS; i++) {
+		seq_printf(m, "\nGuC client @ %p:\n", guc->client[i]);
+		i915_guc_client_info(m, dev_priv, guc->client[i]);
+	}
 
 	i915_guc_log_info(m, dev_priv);
 
@@ -2497,7 +2500,7 @@ static int i915_guc_stage_pool(struct seq_file *m, void *data)
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	const struct intel_guc *guc = &dev_priv->guc;
 	struct guc_stage_desc *desc = guc->stage_desc_pool_vaddr;
-	struct i915_guc_client *client = guc->execbuf_client;
+	struct i915_guc_client *client = guc->client[SUBMIT];
 	unsigned int tmp;
 	int index;
 
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 0bd1fcffa78d..d8b8125aa4cc 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -33,10 +33,11 @@
  *
  * GuC client:
  * A i915_guc_client refers to a submission path through GuC. Currently, there
- * is only one of these (the execbuf_client) and this one is charged with all
- * submissions to the GuC. This struct is the owner of a doorbell, a process
- * descriptor and a workqueue (all of them inside a single gem object that
- * contains all required pages for these elements).
+ * are two clients. One of them (SUBMIT) is charged with all submissions to the
+ * GuC, the other one (PREEMPT) is responsible for preempting the SUBMIT one.
+ * This struct is the owner of a doorbell, a process descriptor and a workqueue
+ * (all of them inside a single gem object that contains all required pages for
+ * these elements).
  *
  * GuC stage descriptor:
  * During initialization, the driver allocates a static pool of 1024 such
@@ -363,6 +364,8 @@ static void guc_stage_desc_init(struct intel_guc *guc,
 	memset(desc, 0, sizeof(*desc));
 
 	desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE | GUC_STAGE_DESC_ATTR_KERNEL;
+	if (client->priority <= GUC_CLIENT_PRIORITY_HIGH)
+		desc->attribute |= GUC_STAGE_DESC_ATTR_PREEMPT;
 	desc->stage_id = client->stage_id;
 	desc->priority = client->priority;
 	desc->db_id = client->doorbell_id;
@@ -553,7 +556,7 @@ static void i915_guc_submit(struct intel_engine_cs *engine)
 {
 	struct drm_i915_private *dev_priv = engine->i915;
 	struct intel_guc *guc = &dev_priv->guc;
-	struct i915_guc_client *client = guc->execbuf_client;
+	struct i915_guc_client *client = guc->client[SUBMIT];
 	struct intel_engine_execlists * const execlists = &engine->execlists;
 	struct execlist_port *port = execlists->port;
 	const unsigned int engine_id = engine->id;
@@ -750,10 +753,11 @@ static int __reset_doorbell(struct i915_guc_client* client, u16 db_id)
  */
 static int guc_init_doorbell_hw(struct intel_guc *guc)
 {
-	struct i915_guc_client *client = guc->execbuf_client;
+	struct i915_guc_client *client = guc->client[SUBMIT];
 	bool recreate_first_client = false;
 	u16 db_id;
 	int ret;
+	u32 i;
 
 	/* For unused doorbells, make sure they are disabled */
 	for_each_clear_bit(db_id, guc->doorbell_bitmap, GUC_NUM_DOORBELLS) {
@@ -761,7 +765,7 @@ static int guc_init_doorbell_hw(struct intel_guc *guc)
 			continue;
 
 		if (has_doorbell(client)) {
-			/* Borrow execbuf_client (we will recreate it later) */
+			/* Borrow submit client (we will recreate it later) */
 			destroy_doorbell(client);
 			recreate_first_client = true;
 		}
@@ -780,14 +784,14 @@ static int guc_init_doorbell_hw(struct intel_guc *guc)
 		__update_doorbell_desc(client, client->doorbell_id);
 	}
 
-	/* Now for every client (and not only execbuf_client) make sure their
+	/* Now for every client (not only submission client) make sure their
 	 * doorbells are known by the GuC */
-	//for (client = client_list; client != NULL; client = client->next)
+	for (i = 0; i < I915_GUC_NUM_CLIENTS; i++)
 	{
-		ret = __create_doorbell(client);
+		ret = __create_doorbell(guc->client[i]);
 		if (ret) {
 			DRM_ERROR("Couldn't recreate client %u doorbell: %d\n",
-				client->stage_id, ret);
+				  guc->client[i]->stage_id, ret);
 			return ret;
 		}
 	}
@@ -914,6 +918,47 @@ static void guc_client_free(struct i915_guc_client *client)
 	kfree(client);
 }
 
+static int guc_clients_create(struct intel_guc *guc)
+{
+	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+	struct i915_guc_client *client;
+
+	client = guc_client_alloc(dev_priv,
+				  INTEL_INFO(dev_priv)->ring_mask,
+				  GUC_CLIENT_PRIORITY_KMD_NORMAL,
+				  dev_priv->kernel_context);
+	if (IS_ERR(client)) {
+		DRM_ERROR("Failed to create GuC client for submission!\n");
+		return PTR_ERR(client);
+	}
+	guc->client[SUBMIT] = client;
+
+	client = guc_client_alloc(dev_priv,
+				  INTEL_INFO(dev_priv)->ring_mask,
+				  GUC_CLIENT_PRIORITY_KMD_HIGH,
+				  dev_priv->preempt_context);
+	if (IS_ERR(client)) {
+		DRM_ERROR("Failed to create GuC client for preemption!\n");
+		guc_client_free(guc->client[SUBMIT]);
+		guc->client[SUBMIT] = NULL;
+		return PTR_ERR(client);
+	}
+	guc->client[PREEMPT] = client;
+
+	return 0;
+}
+
+static void guc_clients_destroy(struct intel_guc *guc)
+{
+	struct i915_guc_client *client;
+	u32 i;
+
+	for (i = 0; i < I915_GUC_NUM_CLIENTS; i++) {
+		client = fetch_and_zero(&guc->client[i]);
+		guc_client_free(client);
+	}
+}
+
 static void guc_policy_init(struct guc_policy *policy)
 {
 	policy->execution_quantum = POLICY_DEFAULT_EXECUTION_QUANTUM_US;
@@ -1143,7 +1188,6 @@ static void guc_interrupts_release(struct drm_i915_private *dev_priv)
 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;
 	int err;
@@ -1161,28 +1205,29 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
 		     sizeof(struct guc_wq_item) *
 		     I915_NUM_ENGINES > GUC_WQ_SIZE);
 
-	if (!client) {
-		client = guc_client_alloc(dev_priv,
-					  INTEL_INFO(dev_priv)->ring_mask,
-					  GUC_CLIENT_PRIORITY_KMD_NORMAL,
-					  dev_priv->kernel_context);
-		if (IS_ERR(client)) {
-			DRM_ERROR("Failed to create GuC client for execbuf!\n");
-			return PTR_ERR(client);
-		}
-
-		guc->execbuf_client = client;
+	/*
+	 * We're being called on both module initialization and on reset,
+	 * until this flow is changed, we're using regular client presence to
+	 * determine which case are we in, and whether we should allocate new
+	 * clients or just reset their workqueues.
+	 */
+	if (!guc->client[SUBMIT]) {
+		GEM_BUG_ON(guc->client[PREEMPT]);
+		err = guc_clients_create(guc);
+		if (err)
+			return err;
+	} else {
+		guc_reset_wq(guc->client[SUBMIT]);
+		guc_reset_wq(guc->client[PREEMPT]);
 	}
 
 	err = intel_guc_sample_forcewake(guc);
 	if (err)
-		goto err_execbuf_client;
-
-	guc_reset_wq(client);
+		goto err_free_clients;
 
 	err = guc_init_doorbell_hw(guc);
 	if (err)
-		goto err_execbuf_client;
+		goto err_free_clients;
 
 	/* Take over from manual control of ELSP (execlists) */
 	guc_interrupts_capture(dev_priv);
@@ -1194,9 +1239,8 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
 
 	return 0;
 
-err_execbuf_client:
-	guc_client_free(guc->execbuf_client);
-	guc->execbuf_client = NULL;
+err_free_clients:
+	guc_clients_destroy(guc);
 	return err;
 }
 
@@ -1209,6 +1253,5 @@ void i915_guc_submission_disable(struct drm_i915_private *dev_priv)
 	/* Revert back to manual ELSP submission */
 	intel_engines_reset_default_submission(dev_priv);
 
-	guc_client_free(guc->execbuf_client);
-	guc->execbuf_client = NULL;
+	guc_clients_destroy(guc);
 }
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index aa1583167b0a..15eadf27b7ae 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -39,6 +39,13 @@
  * pool and doorbells. intel_guc owns a i915_guc_client to replace the legacy
  * ExecList submission.
  */
+
+#define I915_GUC_NUM_CLIENTS 2
+enum i915_guc_client_id {
+	SUBMIT = 0,
+	PREEMPT
+};
+
 struct intel_guc {
 	struct intel_uc_fw fw;
 	struct intel_guc_log log;
@@ -57,7 +64,7 @@ struct intel_guc {
 	struct i915_vma *shared_data;
 	void *shared_data_vaddr;
 
-	struct i915_guc_client *execbuf_client;
+	struct i915_guc_client *client[I915_GUC_NUM_CLIENTS];
 
 	DECLARE_BITMAP(doorbell_bitmap, GUC_NUM_DOORBELLS);
 	/* Cyclic counter mod pagesize	*/
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 20e3c65c0999..3d91d8a28d9f 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -1795,7 +1795,7 @@ bool intel_has_gpu_reset(struct drm_i915_private *dev_priv)
 bool intel_has_reset_engine(struct drm_i915_private *dev_priv)
 {
 	return (dev_priv->info.has_reset_engine &&
-		!dev_priv->guc.execbuf_client &&
+		!dev_priv->guc.client[SUBMIT] &&
 		i915_modparams.reset >= 2);
 }
 
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 07/14] drm/i915/guc: Split guc_wq_item_append
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
                   ` (5 preceding siblings ...)
  2017-10-19 18:36 ` [PATCH v2 06/14] drm/i915/guc: Add a second client, to be used for preemption Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-19 18:36 ` [PATCH v2 08/14] drm/i915: Extract "emit write" part of emit breadcrumb functions Michał Winiarski
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx

We're using a special preempt context for HW to preempt into. We don't
want to emit any requests there, but we still need to wrap this context
into a valid GuC work item.
Let's cleanup the functions operating on GuC work items.
We can extract guc_request_add - responsible for adding GuC work item and
ringing the doorbell, and guc_wq_item_append - used by the function
above, not tied to the concept of gem request.

Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jeff McGee <jeff.mcgee@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Oscar Mateo <oscar.mateo@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Jeff McGee <jeff.mcgee@intel.com>
---
 drivers/gpu/drm/i915/i915_guc_submission.c | 55 ++++++++++++++++--------------
 1 file changed, 30 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index d8b8125aa4cc..c0fdcdb8c41d 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -71,7 +71,7 @@
  * WQ_TYPE_INORDER is needed to support legacy submission via GuC, which
  * represents in-order queue. The kernel driver packs ring tail pointer and an
  * ELSP context descriptor dword into Work Item.
- * See guc_wq_item_append()
+ * See guc_add_request()
  *
  * ADS:
  * The Additional Data Struct (ADS) has pointers for different buffers used by
@@ -390,7 +390,7 @@ static void guc_stage_desc_init(struct intel_guc *guc,
 		 * submission or, in other words, not using a direct submission
 		 * model) the KMD's LRCA is not used for any work submission.
 		 * Instead, the GuC uses the LRCA of the user mode context (see
-		 * guc_wq_item_append below).
+		 * guc_add_request below).
 		 */
 		lrc->context_desc = lower_32_bits(ce->lrc_desc);
 
@@ -469,22 +469,18 @@ static void guc_shared_data_destroy(struct intel_guc *guc)
 
 /* Construct a Work Item and append it to the GuC's Work Queue */
 static void guc_wq_item_append(struct i915_guc_client *client,
-			       struct drm_i915_gem_request *rq)
+			       u32 target_engine, u32 context_desc,
+			       u32 ring_tail, u32 fence_id)
 {
 	/* wqi_len is in DWords, and does not include the one-word header */
 	const size_t wqi_size = sizeof(struct guc_wq_item);
 	const u32 wqi_len = wqi_size / sizeof(u32) - 1;
-	struct intel_engine_cs *engine = rq->engine;
-	struct i915_gem_context *ctx = rq->ctx;
 	struct guc_process_desc *desc = __get_process_desc(client);
 	struct guc_wq_item *wqi;
-	u32 ring_tail, wq_off;
+	u32 wq_off;
 
 	lockdep_assert_held(&client->wq_lock);
 
-	ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64);
-	GEM_BUG_ON(ring_tail > WQ_RING_TAIL_MAX);
-
 	/* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we
 	 * should not have the case where structure wqi is across page, neither
 	 * wrapped to the beginning. This simplifies the implementation below.
@@ -506,15 +502,14 @@ static void guc_wq_item_append(struct i915_guc_client *client,
 	/* Now fill in the 4-word work queue item */
 	wqi->header = WQ_TYPE_INORDER |
 		      (wqi_len << WQ_LEN_SHIFT) |
-		      (engine->guc_id << WQ_TARGET_SHIFT) |
+		      (target_engine << WQ_TARGET_SHIFT) |
 		      WQ_NO_WCFLUSH_WAIT;
-
-	wqi->context_desc = lower_32_bits(intel_lr_context_descriptor(ctx, engine));
-
+	wqi->context_desc = context_desc;
 	wqi->submit_element_info = ring_tail << WQ_RING_TAIL_SHIFT;
-	wqi->fence_id = rq->global_seqno;
+	GEM_BUG_ON(ring_tail > WQ_RING_TAIL_MAX);
+	wqi->fence_id = fence_id;
 
-	/* Postincrement WQ tail for next time. */
+	/* Make the update visible to GuC */
 	WRITE_ONCE(desc->tail, (wq_off + wqi_size) & (GUC_WQ_SIZE - 1));
 }
 
@@ -545,6 +540,25 @@ static void guc_ring_doorbell(struct i915_guc_client *client)
 	GEM_BUG_ON(db->db_status != GUC_DOORBELL_ENABLED);
 }
 
+static void guc_add_request(struct intel_guc *guc,
+			    struct drm_i915_gem_request *rq)
+{
+	struct i915_guc_client *client = guc->client[SUBMIT];
+	struct intel_engine_cs *engine = rq->engine;
+	u32 ctx_desc = lower_32_bits(intel_lr_context_descriptor(rq->ctx, engine));
+	u32 ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64);
+
+	spin_lock(&client->wq_lock);
+
+	guc_wq_item_append(client, engine->guc_id, ctx_desc,
+			   ring_tail, rq->global_seqno);
+	guc_ring_doorbell(client);
+
+	client->submissions[engine->id] += 1;
+
+	spin_unlock(&client->wq_lock);
+}
+
 /**
  * i915_guc_submit() - Submit commands through GuC
  * @engine: engine associated with the commands
@@ -556,10 +570,8 @@ static void i915_guc_submit(struct intel_engine_cs *engine)
 {
 	struct drm_i915_private *dev_priv = engine->i915;
 	struct intel_guc *guc = &dev_priv->guc;
-	struct i915_guc_client *client = guc->client[SUBMIT];
 	struct intel_engine_execlists * const execlists = &engine->execlists;
 	struct execlist_port *port = execlists->port;
-	const unsigned int engine_id = engine->id;
 	unsigned int n;
 
 	for (n = 0; n < execlists_num_ports(execlists); n++) {
@@ -573,14 +585,7 @@ static void i915_guc_submit(struct intel_engine_cs *engine)
 			if (i915_vma_is_map_and_fenceable(rq->ring->vma))
 				POSTING_READ_FW(GUC_STATUS);
 
-			spin_lock(&client->wq_lock);
-
-			guc_wq_item_append(client, rq);
-			guc_ring_doorbell(client);
-
-			client->submissions[engine_id] += 1;
-
-			spin_unlock(&client->wq_lock);
+			guc_add_request(guc, rq);
 		}
 	}
 }
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 08/14] drm/i915: Extract "emit write" part of emit breadcrumb functions
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
                   ` (6 preceding siblings ...)
  2017-10-19 18:36 ` [PATCH 07/14] drm/i915/guc: Split guc_wq_item_append Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-19 18:36 ` [PATCH 09/14] drm/i915: Add information needed to track engine preempt state Michał Winiarski
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx

Let's separate the "emit" part from touching any internal structures,
this way we can have a generic "emit coherent GGTT write" function.
We would like to reuse this functionality for emitting HWSP write, to
confirm that preempt-to-idle has finished.

v2: Reorder args to match emit_pipe_control, s/render/rcs (Chris)

Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/intel_lrc.c        | 28 +++++++-----------------
 drivers/gpu/drm/i915/intel_ringbuffer.h | 38 +++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index a1e177258e3c..f9852c422ea0 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1783,10 +1783,8 @@ static void gen8_emit_breadcrumb(struct drm_i915_gem_request *request, u32 *cs)
 	/* w/a: bit 5 needs to be zero for MI_FLUSH_DW address. */
 	BUILD_BUG_ON(I915_GEM_HWS_INDEX_ADDR & (1 << 5));
 
-	*cs++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW;
-	*cs++ = intel_hws_seqno_address(request->engine) | MI_FLUSH_DW_USE_GTT;
-	*cs++ = 0;
-	*cs++ = request->global_seqno;
+	cs = gen8_emit_ggtt_write(cs, request->global_seqno,
+				  intel_hws_seqno_address(request->engine));
 	*cs++ = MI_USER_INTERRUPT;
 	*cs++ = MI_NOOP;
 	request->tail = intel_ring_offset(request, cs);
@@ -1796,24 +1794,14 @@ static void gen8_emit_breadcrumb(struct drm_i915_gem_request *request, u32 *cs)
 }
 static const int gen8_emit_breadcrumb_sz = 6 + WA_TAIL_DWORDS;
 
-static void gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request,
+static void gen8_emit_breadcrumb_rcs(struct drm_i915_gem_request *request,
 					u32 *cs)
 {
 	/* We're using qword write, seqno should be aligned to 8 bytes. */
 	BUILD_BUG_ON(I915_GEM_HWS_INDEX & 1);
 
-	/* w/a for post sync ops following a GPGPU operation we
-	 * need a prior CS_STALL, which is emitted by the flush
-	 * following the batch.
-	 */
-	*cs++ = GFX_OP_PIPE_CONTROL(6);
-	*cs++ = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_CS_STALL |
-		PIPE_CONTROL_QW_WRITE;
-	*cs++ = intel_hws_seqno_address(request->engine);
-	*cs++ = 0;
-	*cs++ = request->global_seqno;
-	/* We're thrashing one dword of HWS. */
-	*cs++ = 0;
+	cs = gen8_emit_ggtt_write_rcs(cs, request->global_seqno,
+				      intel_hws_seqno_address(request->engine));
 	*cs++ = MI_USER_INTERRUPT;
 	*cs++ = MI_NOOP;
 	request->tail = intel_ring_offset(request, cs);
@@ -1821,7 +1809,7 @@ static void gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request,
 
 	gen8_emit_wa_tail(request, cs);
 }
-static const int gen8_emit_breadcrumb_render_sz = 8 + WA_TAIL_DWORDS;
+static const int gen8_emit_breadcrumb_rcs_sz = 8 + WA_TAIL_DWORDS;
 
 static int gen8_init_rcs_context(struct drm_i915_gem_request *req)
 {
@@ -1977,8 +1965,8 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
 		engine->init_hw = gen8_init_render_ring;
 	engine->init_context = gen8_init_rcs_context;
 	engine->emit_flush = gen8_emit_flush_render;
-	engine->emit_breadcrumb = gen8_emit_breadcrumb_render;
-	engine->emit_breadcrumb_sz = gen8_emit_breadcrumb_render_sz;
+	engine->emit_breadcrumb = gen8_emit_breadcrumb_rcs;
+	engine->emit_breadcrumb_sz = gen8_emit_breadcrumb_rcs_sz;
 
 	ret = intel_engine_create_scratch(engine, PAGE_SIZE);
 	if (ret)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 17186f067408..fe8e52c839dd 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -833,6 +833,44 @@ static inline u32 *gen8_emit_pipe_control(u32 *batch, u32 flags, u32 offset)
 	return batch + 6;
 }
 
+static inline u32 *
+gen8_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset)
+{
+	/* We're using qword write, offset should be aligned to 8 bytes. */
+	GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
+
+	/* w/a for post sync ops following a GPGPU operation we
+	 * need a prior CS_STALL, which is emitted by the flush
+	 * following the batch.
+	 */
+	*cs++ = GFX_OP_PIPE_CONTROL(6);
+	*cs++ = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_CS_STALL |
+		PIPE_CONTROL_QW_WRITE;
+	*cs++ = gtt_offset;
+	*cs++ = 0;
+	*cs++ = value;
+	/* We're thrashing one dword of HWS. */
+	*cs++ = 0;
+
+	return cs;
+}
+
+static inline u32 *
+gen8_emit_ggtt_write(u32 *cs, u32 value, u32 gtt_offset)
+{
+	/* w/a: bit 5 needs to be zero for MI_FLUSH_DW address. */
+	GEM_BUG_ON(gtt_offset & (1 << 5));
+	/* Offset should be aligned to 8 bytes for both (QW/DW) write types */
+	GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
+
+	*cs++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW;
+	*cs++ = gtt_offset | MI_FLUSH_DW_USE_GTT;
+	*cs++ = 0;
+	*cs++ = value;
+
+	return cs;
+}
+
 bool intel_engine_is_idle(struct intel_engine_cs *engine);
 bool intel_engines_are_idle(struct drm_i915_private *dev_priv);
 
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 09/14] drm/i915: Add information needed to track engine preempt state
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
                   ` (7 preceding siblings ...)
  2017-10-19 18:36 ` [PATCH v2 08/14] drm/i915: Extract "emit write" part of emit breadcrumb functions Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-19 18:36 ` [PATCH 10/14] drm/i915/guc: Keep request->priority for its lifetime Michał Winiarski
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx

We shouldn't inspect ELSP context status (or any other bits depending on
specific submission backend) when using GuC submission.
Let's use another piece of HWSP for preempt context, to write its bit of
information, meaning that preemption has finished, and hardware is now
idle.

Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jeff McGee <jeff.mcgee@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Oscar Mateo <oscar.mateo@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Jeff McGee <jeff.mcgee@intel.com>
---
 drivers/gpu/drm/i915/intel_ringbuffer.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index fe8e52c839dd..8ad9a33e803b 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -593,6 +593,8 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value)
  */
 #define I915_GEM_HWS_INDEX		0x30
 #define I915_GEM_HWS_INDEX_ADDR (I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT)
+#define I915_GEM_HWS_PREEMPT_INDEX	0x32
+#define I915_GEM_HWS_PREEMPT_ADDR (I915_GEM_HWS_PREEMPT_INDEX << MI_STORE_DWORD_INDEX_SHIFT)
 #define I915_GEM_HWS_SCRATCH_INDEX	0x40
 #define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH_INDEX << MI_STORE_DWORD_INDEX_SHIFT)
 
@@ -745,6 +747,11 @@ static inline u32 intel_hws_seqno_address(struct intel_engine_cs *engine)
 	return engine->status_page.ggtt_offset + I915_GEM_HWS_INDEX_ADDR;
 }
 
+static inline u32 intel_hws_preempt_done_address(struct intel_engine_cs *engine)
+{
+	return engine->status_page.ggtt_offset + I915_GEM_HWS_PREEMPT_ADDR;
+}
+
 /* intel_breadcrumbs.c -- user interrupt bottom-half for waiters */
 int intel_engine_init_breadcrumbs(struct intel_engine_cs *engine);
 
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 10/14] drm/i915/guc: Keep request->priority for its lifetime
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
                   ` (8 preceding siblings ...)
  2017-10-19 18:36 ` [PATCH 09/14] drm/i915: Add information needed to track engine preempt state Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-19 18:36 ` [PATCH v2 11/14] drm/i915: Rename helpers used for unwinding, use macro for can_preempt Michał Winiarski
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx

We also want to support preemption with GuC submission backend.
In order to do that, we need to remember the priority, like we do on
execlists path.

Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jeff McGee <jeff.mcgee@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_guc_submission.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index c0fdcdb8c41d..e47a5000fc03 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -659,7 +659,6 @@ static void i915_guc_dequeue(struct intel_engine_cs *engine)
 			}
 
 			INIT_LIST_HEAD(&rq->priotree.link);
-			rq->priotree.priority = INT_MAX;
 
 			__i915_gem_request_submit(rq);
 			trace_i915_gem_request_in(rq, port_index(port, execlists));
@@ -694,6 +693,7 @@ static void i915_guc_irq_handler(unsigned long data)
 	rq = port_request(&port[0]);
 	while (rq && i915_gem_request_completed(rq)) {
 		trace_i915_gem_request_out(rq);
+		rq->priotree.priority = INT_MAX;
 		i915_gem_request_put(rq);
 
 		execlists_port_complete(execlists, port);
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v2 11/14] drm/i915: Rename helpers used for unwinding, use macro for can_preempt
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
                   ` (9 preceding siblings ...)
  2017-10-19 18:36 ` [PATCH 10/14] drm/i915/guc: Keep request->priority for its lifetime Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-19 19:18   ` Chris Wilson
  2017-10-19 19:20   ` Chris Wilson
  2017-10-19 18:36 ` [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC Michał Winiarski
                   ` (4 subsequent siblings)
  15 siblings, 2 replies; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx

We would also like to make use of execlist_cancel_port_requests and
unwind_incomplete_requests in GuC preemption backend.
Let's rename the functions to use the correct prefixes, so that we can
simply add the declarations in the following patch.
Similar thing for applies for can_preempt, except we're introducing
HAS_LOGICAL_RING_PREEMPTION macro instad, converting other users that
were previously touching device info directly.

v2: s/intel_engine/execlists and pass execlists to unwind (Chris)

Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c        |  2 +-
 drivers/gpu/drm/i915/i915_drv.h        |  2 ++
 drivers/gpu/drm/i915/intel_engine_cs.c |  6 +++---
 drivers/gpu/drm/i915/intel_lrc.c       | 24 +++++++++++-------------
 4 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 3db5851756f0..7b871802ae36 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -372,7 +372,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
 			value |= I915_SCHEDULER_CAP_ENABLED;
 			value |= I915_SCHEDULER_CAP_PRIORITY;
 
-			if (INTEL_INFO(dev_priv)->has_logical_ring_preemption &&
+			if (HAS_LOGICAL_RING_PREEMPTION(dev_priv) &&
 			    i915_modparams.enable_execlists &&
 			    !i915_modparams.enable_guc_submission)
 				value |= I915_SCHEDULER_CAP_PREEMPTION;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3c2649c27f88..caa8e79b38b2 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3135,6 +3135,8 @@ intel_info(const struct drm_i915_private *dev_priv)
 
 #define HAS_LOGICAL_RING_CONTEXTS(dev_priv) \
 		((dev_priv)->info.has_logical_ring_contexts)
+#define HAS_LOGICAL_RING_PREEMPTION(dev_priv) \
+		((dev_priv)->info.has_logical_ring_preemption)
 #define USES_PPGTT(dev_priv)		(i915_modparams.enable_ppgtt)
 #define USES_FULL_PPGTT(dev_priv)	(i915_modparams.enable_ppgtt >= 2)
 #define USES_FULL_48BIT_PPGTT(dev_priv)	(i915_modparams.enable_ppgtt == 3)
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index a47a9c6bea52..db590d34ed48 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -620,7 +620,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine)
 	 * Similarly the preempt context must always be available so that
 	 * we can interrupt the engine at any time.
 	 */
-	if (INTEL_INFO(engine->i915)->has_logical_ring_preemption) {
+	if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) {
 		ring = engine->context_pin(engine,
 					   engine->i915->preempt_context);
 		if (IS_ERR(ring)) {
@@ -651,7 +651,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine)
 err_breadcrumbs:
 	intel_engine_fini_breadcrumbs(engine);
 err_unpin_preempt:
-	if (INTEL_INFO(engine->i915)->has_logical_ring_preemption)
+	if (HAS_LOGICAL_RING_PREEMPTION(engine->i915))
 		engine->context_unpin(engine, engine->i915->preempt_context);
 err_unpin_kernel:
 	engine->context_unpin(engine, engine->i915->kernel_context);
@@ -679,7 +679,7 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
 	intel_engine_cleanup_cmd_parser(engine);
 	i915_gem_batch_pool_fini(&engine->batch_pool);
 
-	if (INTEL_INFO(engine->i915)->has_logical_ring_preemption)
+	if (HAS_LOGICAL_RING_PREEMPTION(engine->i915))
 		engine->context_unpin(engine, engine->i915->preempt_context);
 	engine->context_unpin(engine, engine->i915->kernel_context);
 }
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index f9852c422ea0..dd4708904c85 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -354,8 +354,11 @@ static void unwind_wa_tail(struct drm_i915_gem_request *rq)
 	assert_ring_tail_valid(rq->ring, rq->tail);
 }
 
-static void unwind_incomplete_requests(struct intel_engine_cs *engine)
+static void execlists_unwind_incomplete_requests(
+		const struct intel_engine_execlists * const execlists)
 {
+	struct intel_engine_cs *engine =
+		container_of(execlists, typeof(*engine), execlists);
 	struct drm_i915_gem_request *rq, *rn;
 	struct i915_priolist *uninitialized_var(p);
 	int last_prio = I915_PRIORITY_INVALID;
@@ -515,11 +518,6 @@ static void inject_preempt_context(struct intel_engine_cs *engine)
 	elsp_write(ce->lrc_desc, elsp);
 }
 
-static bool can_preempt(struct intel_engine_cs *engine)
-{
-	return INTEL_INFO(engine->i915)->has_logical_ring_preemption;
-}
-
 static void execlists_dequeue(struct intel_engine_cs *engine)
 {
 	struct intel_engine_execlists * const execlists = &engine->execlists;
@@ -567,7 +565,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
 		if (port_count(&port[0]) > 1)
 			goto unlock;
 
-		if (can_preempt(engine) &&
+		if (HAS_LOGICAL_RING_PREEMPTION(engine->i915) &&
 		    rb_entry(rb, struct i915_priolist, node)->priority >
 		    max(last->priotree.priority, 0)) {
 			/*
@@ -688,7 +686,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
 }
 
 static void
-execlist_cancel_port_requests(struct intel_engine_execlists *execlists)
+execlists_cancel_port_requests(struct intel_engine_execlists * const execlists)
 {
 	struct execlist_port *port = execlists->port;
 	unsigned int num_ports = execlists_num_ports(execlists);
@@ -714,7 +712,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine)
 	spin_lock_irqsave(&engine->timeline->lock, flags);
 
 	/* Cancel the requests on the HW and clear the ELSP tracker. */
-	execlist_cancel_port_requests(execlists);
+	execlists_cancel_port_requests(execlists);
 
 	/* Mark all executing requests as skipped. */
 	list_for_each_entry(rq, &engine->timeline->requests, link) {
@@ -855,10 +853,10 @@ static void intel_lrc_irq_handler(unsigned long data)
 
 			if (status & GEN8_CTX_STATUS_ACTIVE_IDLE &&
 			    buf[2*head + 1] == PREEMPT_ID) {
-				execlist_cancel_port_requests(execlists);
+				execlists_cancel_port_requests(execlists);
 
 				spin_lock_irq(&engine->timeline->lock);
-				unwind_incomplete_requests(engine);
+				execlists_unwind_incomplete_requests(execlists);
 				spin_unlock_irq(&engine->timeline->lock);
 
 				GEM_BUG_ON(!execlists->preempt);
@@ -1520,10 +1518,10 @@ static void reset_common_ring(struct intel_engine_cs *engine,
 	 * guessing the missed context-switch events by looking at what
 	 * requests were completed.
 	 */
-	execlist_cancel_port_requests(execlists);
+	execlists_cancel_port_requests(execlists);
 
 	/* Push back any incomplete requests for replay after the reset. */
-	unwind_incomplete_requests(engine);
+	execlists_unwind_incomplete_requests(execlists);
 
 	spin_unlock_irqrestore(&engine->timeline->lock, flags);
 
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
                   ` (10 preceding siblings ...)
  2017-10-19 18:36 ` [PATCH v2 11/14] drm/i915: Rename helpers used for unwinding, use macro for can_preempt Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-19 19:14   ` Chris Wilson
                     ` (5 more replies)
  2017-10-19 18:36 ` [PATCH 13/14] drm/i915/guc: Workaround the missing user interrupt after preemption Michał Winiarski
                   ` (3 subsequent siblings)
  15 siblings, 6 replies; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx

Pretty similar to what we have on execlists.
We're reusing most of the GEM code, however, due to GuC quirks we need a
couple of extra bits.
Preemption is implemented as GuC action, and actions can be pretty slow.
Because of that, we're using a mutex to serialize them. Since we're
requesting preemption from the tasklet, the task of creating a workitem
and wrapping it in GuC action is delegated to a worker.

To distinguish that preemption has finished, we're using additional
piece of HWSP, and since we're not getting context switch interrupts,
we're also adding a user interrupt.

The fact that our special preempt context has completed unfortunately
doesn't mean that we're ready to submit new work. We also need to wait
for GuC to finish its own processing.

v2: Don't compile out the wait for GuC, handle workqueue flush on reset,
no need for ordered workqueue, put on a reviewer hat when looking at my own
patches (Chris)
Move struct work around in intel_guc, move user interruput outside of
conditional (Michał)
Keep ring around rather than chase though intel_context

v3: Extract WA for flushing ggtt writes to a helper (Chris)
Keep work_struct in intel_guc rather than engine (Michał)
Use ordered workqueue for inject_preempt worker to avoid GuC quirks.

Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jeff McGee <jeff.mcgee@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Oscar Mateo <oscar.mateo@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c            |   3 +-
 drivers/gpu/drm/i915/i915_gem.c            |  10 ++
 drivers/gpu/drm/i915/i915_guc_submission.c | 206 +++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_guc.h           |   8 ++
 drivers/gpu/drm/i915/intel_lrc.c           |   4 +-
 drivers/gpu/drm/i915/intel_lrc.h           |   1 -
 drivers/gpu/drm/i915/intel_ringbuffer.h    |   8 ++
 7 files changed, 222 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 7b871802ae36..af745749509c 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -373,8 +373,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
 			value |= I915_SCHEDULER_CAP_PRIORITY;
 
 			if (HAS_LOGICAL_RING_PREEMPTION(dev_priv) &&
-			    i915_modparams.enable_execlists &&
-			    !i915_modparams.enable_guc_submission)
+			    i915_modparams.enable_execlists)
 				value |= I915_SCHEDULER_CAP_PREEMPTION;
 		}
 		break;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index ef14c6d570dc..7d52baf4f3bd 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2904,6 +2904,16 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine)
 	tasklet_kill(&engine->execlists.irq_tasklet);
 	tasklet_disable(&engine->execlists.irq_tasklet);
 
+	/*
+	 * We're using worker to queue preemption requests from the tasklet in
+	 * GuC submission mode.
+	 * Even though tasklet was disabled, we may still have a worker queued.
+	 * Let's make sure that all workers scheduled before disabling the
+	 * tasklet are completed before continuing with the reset.
+	 */
+	if (i915_modparams.enable_guc_submission)
+		flush_workqueue(engine->i915->guc.preempt_wq);
+
 	if (engine->irq_seqno_barrier)
 		engine->irq_seqno_barrier(engine);
 
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index e47a5000fc03..a11ed4deff4b 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -559,6 +559,105 @@ static void guc_add_request(struct intel_guc *guc,
 	spin_unlock(&client->wq_lock);
 }
 
+/*
+ * When we're doing submissions using regular execlists backend, writing to
+ * ELSP from CPU side is enough to make sure that writes to ringbuffer pages
+ * pinned in mappable aperture portion of GGTT are visible to command streamer.
+ * Writes done by GuC on our behalf are not guaranteeing such ordering,
+ * therefore, to ensure the flush, we're issuing a POSTING READ.
+ */
+static void flush_ggtt_writes(struct i915_vma *vma)
+{
+	struct drm_i915_private *dev_priv = to_i915(vma->obj->base.dev);
+
+	if (i915_vma_is_map_and_fenceable(vma))
+		POSTING_READ_FW(GUC_STATUS);
+}
+
+#define GUC_PREEMPT_FINISHED 0x1
+#define GUC_PREEMPT_BREADCRUMB_DWORDS 0x8
+static void inject_preempt_context(struct work_struct *work)
+{
+	struct guc_preempt_work *preempt_work =
+		container_of(work, typeof(*preempt_work), work);
+	struct intel_engine_cs *engine = preempt_work->engine;
+	struct intel_guc *guc = &engine->i915->guc;
+	struct i915_guc_client *client = guc->client[PREEMPT];
+	struct intel_ring *ring = client->owner->engine[engine->id].ring;
+	u32 ctx_desc = lower_32_bits(intel_lr_context_descriptor(client->owner,
+								 engine));
+	u32 *cs = ring->vaddr + ring->tail;
+	u32 data[7];
+
+	if (engine->id == RCS) {
+		cs = gen8_emit_ggtt_write_rcs(cs, GUC_PREEMPT_FINISHED,
+				intel_hws_preempt_done_address(engine));
+	} else {
+		cs = gen8_emit_ggtt_write(cs, GUC_PREEMPT_FINISHED,
+				intel_hws_preempt_done_address(engine));
+		*cs++ = MI_NOOP;
+		*cs++ = MI_NOOP;
+	}
+	*cs++ = MI_USER_INTERRUPT;
+	*cs++ = MI_NOOP;
+
+	GEM_BUG_ON(!IS_ALIGNED(ring->size,
+			       GUC_PREEMPT_BREADCRUMB_DWORDS * sizeof(u32)));
+	GEM_BUG_ON((void*)cs - (ring->vaddr + ring->tail) !=
+		   GUC_PREEMPT_BREADCRUMB_DWORDS * sizeof(u32));
+
+	ring->tail += GUC_PREEMPT_BREADCRUMB_DWORDS * sizeof(u32);
+	ring->tail &= (ring->size - 1);
+
+	flush_ggtt_writes(ring->vma);
+
+	spin_lock_irq(&client->wq_lock);
+	guc_wq_item_append(client, engine->guc_id, ctx_desc,
+			   ring->tail / sizeof(u64), 0);
+	spin_unlock_irq(&client->wq_lock);
+
+	data[0] = INTEL_GUC_ACTION_REQUEST_PREEMPTION;
+	data[1] = client->stage_id;
+	data[2] = INTEL_GUC_PREEMPT_OPTION_IMMEDIATE |
+		  INTEL_GUC_PREEMPT_OPTION_DROP_WORK_Q |
+		  INTEL_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q;
+	data[3] = engine->guc_id;
+	data[4] = guc->client[SUBMIT]->priority;
+	data[5] = guc->client[SUBMIT]->stage_id;
+	data[6] = guc_ggtt_offset(guc->shared_data);
+
+	if (WARN_ON(intel_guc_send(guc, data, ARRAY_SIZE(data)))) {
+		WRITE_ONCE(engine->execlists.preempt, false);
+		tasklet_schedule(&engine->execlists.irq_tasklet);
+	}
+}
+
+/*
+ * We're using user interrupt and HWSP value to mark that preemption has
+ * finished and GPU is idle. Normally, we could unwind and continue similar to
+ * execlists submission path. Unfortunately, with GuC we also need to wait for
+ * it to finish its own postprocessing, before attempting to submit. Otherwise
+ * GuC may silently ignore our submissions, and thus we risk losing request at
+ * best, executing out-of-order and causing kernel panic at worst.
+ */
+#define GUC_PREEMPT_POSTPROCESS_DELAY_MS 10
+static void wait_for_guc_preempt_report(struct intel_engine_cs *engine)
+{
+	struct intel_guc *guc = &engine->i915->guc;
+	struct guc_shared_ctx_data *data = guc->shared_data_vaddr;
+	struct guc_ctx_report *report = &data->preempt_ctx_report[engine->guc_id];
+
+	WARN_ON(wait_for_atomic(report->report_return_status ==
+				INTEL_GUC_REPORT_STATUS_COMPLETE,
+				GUC_PREEMPT_POSTPROCESS_DELAY_MS));
+	/* GuC is expecting that we're also going to clear the affected context
+	 * counter, let's also reset the return status to not depend on GuC
+	 * resetting it after recieving another preempt action */
+	report->affected_count = 0;
+	report->report_return_status = INTEL_GUC_REPORT_STATUS_UNKNOWN;
+}
+
+
 /**
  * i915_guc_submit() - Submit commands through GuC
  * @engine: engine associated with the commands
@@ -568,8 +667,7 @@ static void guc_add_request(struct intel_guc *guc,
  */
 static void i915_guc_submit(struct intel_engine_cs *engine)
 {
-	struct drm_i915_private *dev_priv = engine->i915;
-	struct intel_guc *guc = &dev_priv->guc;
+	struct intel_guc *guc = &engine->i915->guc;
 	struct intel_engine_execlists * const execlists = &engine->execlists;
 	struct execlist_port *port = execlists->port;
 	unsigned int n;
@@ -582,8 +680,7 @@ static void i915_guc_submit(struct intel_engine_cs *engine)
 		if (rq && count == 0) {
 			port_set(&port[n], port_pack(rq, ++count));
 
-			if (i915_vma_is_map_and_fenceable(rq->ring->vma))
-				POSTING_READ_FW(GUC_STATUS);
+			flush_ggtt_writes(rq->ring->vma);
 
 			guc_add_request(guc, rq);
 		}
@@ -635,13 +732,31 @@ static void i915_guc_dequeue(struct intel_engine_cs *engine)
 	bool submit = false;
 	struct rb_node *rb;
 
-	if (port_isset(port))
-		port++;
-
 	spin_lock_irq(&engine->timeline->lock);
 	rb = execlists->first;
 	GEM_BUG_ON(rb_first(&execlists->queue) != rb);
-	while (rb) {
+
+	if (!rb)
+		goto unlock;
+
+	if (HAS_LOGICAL_RING_PREEMPTION(engine->i915) && port_isset(port)) {
+		struct guc_preempt_work *preempt_work =
+			&engine->i915->guc.preempt_work[engine->id];
+
+		if (rb_entry(rb, struct i915_priolist, node)->priority >
+		    max(port_request(port)->priotree.priority, 0)) {
+			WRITE_ONCE(execlists->preempt, true);
+			queue_work(engine->i915->guc.preempt_wq,
+				   &preempt_work->work);
+			goto unlock;
+		} else if (port_isset(last_port)) {
+			goto unlock;
+		}
+
+		port++;
+	}
+
+	do {
 		struct i915_priolist *p = rb_entry(rb, typeof(*p), node);
 		struct drm_i915_gem_request *rq, *rn;
 
@@ -671,13 +786,14 @@ static void i915_guc_dequeue(struct intel_engine_cs *engine)
 		INIT_LIST_HEAD(&p->requests);
 		if (p->priority != I915_PRIORITY_NORMAL)
 			kmem_cache_free(engine->i915->priorities, p);
-	}
+	} while (rb);
 done:
 	execlists->first = rb;
 	if (submit) {
 		port_assign(port, last);
 		i915_guc_submit(engine);
 	}
+unlock:
 	spin_unlock_irq(&engine->timeline->lock);
 }
 
@@ -686,10 +802,23 @@ static void i915_guc_irq_handler(unsigned long data)
 	struct intel_engine_cs * const engine = (struct intel_engine_cs *)data;
 	struct intel_engine_execlists * const execlists = &engine->execlists;
 	struct execlist_port *port = execlists->port;
-	const struct execlist_port * const last_port =
-		&execlists->port[execlists->port_mask];
 	struct drm_i915_gem_request *rq;
 
+	if (READ_ONCE(execlists->preempt) &&
+	    intel_read_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX) ==
+	    GUC_PREEMPT_FINISHED) {
+		execlists_cancel_port_requests(&engine->execlists);
+
+		spin_lock_irq(&engine->timeline->lock);
+		execlists_unwind_incomplete_requests(execlists);
+		spin_unlock_irq(&engine->timeline->lock);
+
+		wait_for_guc_preempt_report(engine);
+
+		WRITE_ONCE(execlists->preempt, false);
+		intel_write_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX, 0);
+	}
+
 	rq = port_request(&port[0]);
 	while (rq && i915_gem_request_completed(rq)) {
 		trace_i915_gem_request_out(rq);
@@ -701,7 +830,7 @@ static void i915_guc_irq_handler(unsigned long data)
 		rq = port_request(&port[0]);
 	}
 
-	if (!port_isset(last_port))
+	if (!READ_ONCE(execlists->preempt))
 		i915_guc_dequeue(engine);
 }
 
@@ -1073,6 +1202,50 @@ static void guc_ads_destroy(struct intel_guc *guc)
 	i915_vma_unpin_and_release(&guc->ads_vma);
 }
 
+static int guc_preempt_work_create(struct intel_guc *guc)
+{
+	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+
+	/*
+	 * Even though both sending GuC action, and adding a new workitem to
+	 * GuC workqueue are serialized (each with its own locking), since
+	 * we're using mutliple engines, it's possible that we're going to
+	 * issue a preempt request with two (or more - each for different
+	 * engine) workitems in GuC queue. In this situation, GuC may submit
+	 * all of them, which will make us very confused.
+	 * Our preemption contexts may even already be complete - before we
+	 * even had the chance to sent the preempt action to GuC!. Rather
+	 * than introducing yet another lock, we can just use ordered workqueue
+	 * to make sure we're always sending a single preemption request with a
+	 * single workitem.
+	 */
+	guc->preempt_wq = alloc_ordered_workqueue("i915-guc_preempt",
+						  WQ_HIGHPRI);
+	if (!guc->preempt_wq)
+		return -ENOMEM;
+
+	for_each_engine(engine, dev_priv, id) {
+		guc->preempt_work[id].engine = engine;
+		INIT_WORK(&guc->preempt_work[id].work, inject_preempt_context);
+	}
+
+	return 0;
+}
+
+static void guc_preempt_work_destroy(struct intel_guc *guc)
+{
+	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+
+	for_each_engine(engine, dev_priv, id)
+		cancel_work_sync(&guc->preempt_work[id].work);
+
+	destroy_workqueue(guc->preempt_wq);
+}
+
 /*
  * Set up the memory resources to be shared with the GuC (via the GGTT)
  * at firmware loading time.
@@ -1097,12 +1270,18 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
 	if (ret < 0)
 		goto err_shared_data;
 
+	ret = guc_preempt_work_create(guc);
+	if (ret)
+		goto err_log;
+
 	ret = guc_ads_create(guc);
 	if (ret < 0)
-		goto err_log;
+		goto err_wq;
 
 	return 0;
 
+err_wq:
+	guc_preempt_work_destroy(guc);
 err_log:
 	intel_guc_log_destroy(guc);
 err_shared_data:
@@ -1117,6 +1296,7 @@ void i915_guc_submission_fini(struct drm_i915_private *dev_priv)
 	struct intel_guc *guc = &dev_priv->guc;
 
 	guc_ads_destroy(guc);
+	guc_preempt_work_destroy(guc);
 	intel_guc_log_destroy(guc);
 	guc_shared_data_destroy(guc);
 	guc_stage_desc_pool_destroy(guc);
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 15eadf27b7ae..7273a6be7dc1 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -46,6 +46,11 @@ enum i915_guc_client_id {
 	PREEMPT
 };
 
+struct guc_preempt_work {
+	struct intel_engine_cs *engine;
+	struct work_struct work;
+};
+
 struct intel_guc {
 	struct intel_uc_fw fw;
 	struct intel_guc_log log;
@@ -66,6 +71,9 @@ struct intel_guc {
 
 	struct i915_guc_client *client[I915_GUC_NUM_CLIENTS];
 
+	struct guc_preempt_work preempt_work[I915_NUM_ENGINES];
+	struct workqueue_struct *preempt_wq;
+
 	DECLARE_BITMAP(doorbell_bitmap, GUC_NUM_DOORBELLS);
 	/* Cyclic counter mod pagesize	*/
 	u32 db_cacheline;
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index dd4708904c85..d2327b36cf71 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -354,7 +354,7 @@ static void unwind_wa_tail(struct drm_i915_gem_request *rq)
 	assert_ring_tail_valid(rq->ring, rq->tail);
 }
 
-static void execlists_unwind_incomplete_requests(
+void execlists_unwind_incomplete_requests(
 		const struct intel_engine_execlists * const execlists)
 {
 	struct intel_engine_cs *engine =
@@ -685,7 +685,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
 		execlists_submit_ports(engine);
 }
 
-static void
+void
 execlists_cancel_port_requests(struct intel_engine_execlists * const execlists)
 {
 	struct execlist_port *port = execlists->port;
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
index 689fde1a63a9..17182ce29674 100644
--- a/drivers/gpu/drm/i915/intel_lrc.h
+++ b/drivers/gpu/drm/i915/intel_lrc.h
@@ -107,7 +107,6 @@ intel_lr_context_descriptor(struct i915_gem_context *ctx,
 	return ctx->engine[engine->id].lrc_desc;
 }
 
-
 /* Execlists */
 int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv,
 				    int enable_execlists);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 8ad9a33e803b..5a68499bf3eb 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -525,6 +525,12 @@ struct intel_engine_cs {
 	u32 (*get_cmd_length_mask)(u32 cmd_header);
 };
 
+void
+execlists_cancel_port_requests(struct intel_engine_execlists * const execlists);
+
+void execlists_unwind_incomplete_requests(
+		const struct intel_engine_execlists * const execlists);
+
 static inline unsigned int
 execlists_num_ports(const struct intel_engine_execlists * const execlists)
 {
@@ -543,6 +549,8 @@ execlists_port_complete(struct intel_engine_execlists * const execlists,
 	memset(port + m, 0, sizeof(struct execlist_port));
 }
 
+
+
 static inline unsigned int
 intel_engine_flag(const struct intel_engine_cs *engine)
 {
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 13/14] drm/i915/guc: Workaround the missing user interrupt after preemption
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
                   ` (11 preceding siblings ...)
  2017-10-19 18:36 ` [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-19 19:44   ` Chris Wilson
  2017-10-20 16:08   ` Chris Wilson
  2017-10-19 18:36 ` [PATCH 14/14] HAX Enable GuC Submission for CI Michał Winiarski
                   ` (2 subsequent siblings)
  15 siblings, 2 replies; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx

With GuC, we're scheduling tasklet on USER_INTERRUPT - since some work
has completed, perhaps we're able to submit some more work. We're doing
similar thing for preemption - after preemption has completed, it's time
to schedule the tasklet and submit more work (since the engine is now
idle). Unfortunately, we can hit the scenarios where the preemption is
done, but the interrupt is nowhere to be seen. To work around the
problem, let's use a delayed work that's kicking the tasklet if
preemption is done, and queueing itself otherwise.

Testcase: igt/gem_exec_whisper/*-priority
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jeff McGee <jeff.mcgee@intel.com>
Cc: John Harrison <john.c.harrison@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_guc_submission.c | 36 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_guc.h           |  1 +
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index a11ed4deff4b..dbb03b5481d2 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -574,6 +574,26 @@ static void flush_ggtt_writes(struct i915_vma *vma)
 		POSTING_READ_FW(GUC_STATUS);
 }
 
+#define GUC_LOST_IRQ_WORK_DELAY_MS 100
+static void guc_lost_user_interrupt(struct work_struct *work)
+{
+	struct guc_preempt_work *preempt_work =
+		container_of(to_delayed_work(work), typeof(*preempt_work),
+			     lost_irq_work);
+	struct intel_engine_cs *engine = preempt_work->engine;
+	struct intel_guc *guc = &engine->i915->guc;
+	struct guc_shared_ctx_data *data = guc->shared_data_vaddr;
+	struct guc_ctx_report *report = &data->preempt_ctx_report[engine->guc_id];
+
+	if (report->report_return_status == INTEL_GUC_REPORT_STATUS_COMPLETE)
+		tasklet_schedule(&engine->execlists.irq_tasklet);
+	else
+		queue_delayed_work(guc->preempt_wq,
+				   &preempt_work->lost_irq_work,
+				   msecs_to_jiffies(GUC_LOST_IRQ_WORK_DELAY_MS));
+
+}
+
 #define GUC_PREEMPT_FINISHED 0x1
 #define GUC_PREEMPT_BREADCRUMB_DWORDS 0x8
 static void inject_preempt_context(struct work_struct *work)
@@ -629,7 +649,13 @@ static void inject_preempt_context(struct work_struct *work)
 	if (WARN_ON(intel_guc_send(guc, data, ARRAY_SIZE(data)))) {
 		WRITE_ONCE(engine->execlists.preempt, false);
 		tasklet_schedule(&engine->execlists.irq_tasklet);
+
+		return;
 	}
+
+	queue_delayed_work(engine->i915->guc.preempt_wq,
+			   &preempt_work->lost_irq_work,
+			   msecs_to_jiffies(GUC_LOST_IRQ_WORK_DELAY_MS));
 }
 
 /*
@@ -647,6 +673,10 @@ static void wait_for_guc_preempt_report(struct intel_engine_cs *engine)
 	struct guc_shared_ctx_data *data = guc->shared_data_vaddr;
 	struct guc_ctx_report *report = &data->preempt_ctx_report[engine->guc_id];
 
+	/* If we landed here, it means that we didn't lose an interrupt, and
+	 * we can safely cancel the worker */
+	cancel_delayed_work(&guc->preempt_work[engine->id].lost_irq_work);
+
 	WARN_ON(wait_for_atomic(report->report_return_status ==
 				INTEL_GUC_REPORT_STATUS_COMPLETE,
 				GUC_PREEMPT_POSTPROCESS_DELAY_MS));
@@ -1229,6 +1259,8 @@ static int guc_preempt_work_create(struct intel_guc *guc)
 	for_each_engine(engine, dev_priv, id) {
 		guc->preempt_work[id].engine = engine;
 		INIT_WORK(&guc->preempt_work[id].work, inject_preempt_context);
+		INIT_DELAYED_WORK(&guc->preempt_work[id].lost_irq_work,
+				  guc_lost_user_interrupt);
 	}
 
 	return 0;
@@ -1240,8 +1272,10 @@ static void guc_preempt_work_destroy(struct intel_guc *guc)
 	struct intel_engine_cs *engine;
 	enum intel_engine_id id;
 
-	for_each_engine(engine, dev_priv, id)
+	for_each_engine(engine, dev_priv, id) {
+		cancel_delayed_work_sync(&guc->preempt_work[id].lost_irq_work);
 		cancel_work_sync(&guc->preempt_work[id].work);
+	}
 
 	destroy_workqueue(guc->preempt_wq);
 }
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 7273a6be7dc1..0c9338b5c4b8 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -49,6 +49,7 @@ enum i915_guc_client_id {
 struct guc_preempt_work {
 	struct intel_engine_cs *engine;
 	struct work_struct work;
+	struct delayed_work lost_irq_work;
 };
 
 struct intel_guc {
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 14/14] HAX Enable GuC Submission for CI
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
                   ` (12 preceding siblings ...)
  2017-10-19 18:36 ` [PATCH 13/14] drm/i915/guc: Workaround the missing user interrupt after preemption Michał Winiarski
@ 2017-10-19 18:36 ` Michał Winiarski
  2017-10-19 19:11 ` ✗ Fi.CI.BAT: failure for Preemption with GuC, third attempt Patchwork
  2017-10-26 21:21 ` Patchwork
  15 siblings, 0 replies; 32+ messages in thread
From: Michał Winiarski @ 2017-10-19 18:36 UTC (permalink / raw)
  To: intel-gfx

Also:
Revert "drm/i915/guc: Assert that we switch between known ggtt->invalidate functions"

This reverts commit 04f7b24eccdfae680a36e9825fe0d61dcd5ed528.
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 8 ++------
 drivers/gpu/drm/i915/i915_params.h  | 4 ++--
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 527a2d2d6281..74479ea31d60 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3568,17 +3568,13 @@ int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv)
 
 void i915_ggtt_enable_guc(struct drm_i915_private *i915)
 {
-	GEM_BUG_ON(i915->ggtt.invalidate != gen6_ggtt_invalidate);
-
 	i915->ggtt.invalidate = guc_ggtt_invalidate;
 }
 
 void i915_ggtt_disable_guc(struct drm_i915_private *i915)
 {
-	/* We should only be called after i915_ggtt_enable_guc() */
-	GEM_BUG_ON(i915->ggtt.invalidate != guc_ggtt_invalidate);
-
-	i915->ggtt.invalidate = gen6_ggtt_invalidate;
+	if (i915->ggtt.invalidate == guc_ggtt_invalidate)
+		i915->ggtt.invalidate = gen6_ggtt_invalidate;
 }
 
 void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
index c7292268ed43..c38cef07b9fe 100644
--- a/drivers/gpu/drm/i915/i915_params.h
+++ b/drivers/gpu/drm/i915/i915_params.h
@@ -44,8 +44,8 @@
 	param(int, disable_power_well, -1) \
 	param(int, enable_ips, 1) \
 	param(int, invert_brightness, 0) \
-	param(int, enable_guc_loading, 0) \
-	param(int, enable_guc_submission, 0) \
+	param(int, enable_guc_loading, 1) \
+	param(int, enable_guc_submission, 1) \
 	param(int, guc_log_level, -1) \
 	param(char *, guc_firmware_path, NULL) \
 	param(char *, huc_firmware_path, NULL) \
-- 
2.13.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* ✗ Fi.CI.BAT: failure for Preemption with GuC, third attempt
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
                   ` (13 preceding siblings ...)
  2017-10-19 18:36 ` [PATCH 14/14] HAX Enable GuC Submission for CI Michał Winiarski
@ 2017-10-19 19:11 ` Patchwork
  2017-10-26 21:21 ` Patchwork
  15 siblings, 0 replies; 32+ messages in thread
From: Patchwork @ 2017-10-19 19:11 UTC (permalink / raw)
  To: Michał Winiarski; +Cc: intel-gfx

== Series Details ==

Series: Preemption with GuC, third attempt
URL   : https://patchwork.freedesktop.org/series/32320/
State : failure

== Summary ==

Series 32320v1 Preemption with GuC, third attempt
https://patchwork.freedesktop.org/api/1.0/series/32320/revisions/1/mbox/

Test gem_ringfill:
        Subgroup basic-default-hang:
                pass       -> DMESG-WARN (fi-skl-6700k)
Test gem_sync:
        Subgroup basic-all:
                pass       -> SKIP       (fi-skl-6700k)
        Subgroup basic-each:
                pass       -> SKIP       (fi-skl-6700k)
        Subgroup basic-many-each:
                pass       -> SKIP       (fi-skl-6700k)
        Subgroup basic-store-all:
                pass       -> SKIP       (fi-skl-6700k)
        Subgroup basic-store-each:
                pass       -> SKIP       (fi-skl-6700k)
Test gem_tiled_blits:
        Subgroup basic:
                pass       -> SKIP       (fi-skl-6700k)
Test gem_tiled_fence_blits:
        Subgroup basic:
                pass       -> SKIP       (fi-skl-6700k)
Test gem_wait:
        Subgroup basic-busy-all:
                pass       -> SKIP       (fi-skl-6700k)
        Subgroup basic-wait-all:
                pass       -> SKIP       (fi-skl-6700k)
        Subgroup basic-await-all:
                pass       -> SKIP       (fi-skl-6700k)
Test gem_workarounds:
        Subgroup basic-read:
                pass       -> SKIP       (fi-skl-6700k)
Test kms_busy:
        Subgroup basic-flip-a:
                pass       -> SKIP       (fi-skl-6700k)
        Subgroup basic-flip-b:
                fail       -> PASS       (fi-gdg-551) fdo#102654
                pass       -> SKIP       (fi-skl-6700k)
        Subgroup basic-flip-c:
                pass       -> SKIP       (fi-skl-6700k) fdo#103097
Test kms_cursor_legacy:
        Subgroup basic-busy-flip-before-cursor-atomic:
                pass       -> SKIP       (fi-skl-6700k)
        Subgroup basic-busy-flip-before-cursor-legacy:
                fail       -> PASS       (fi-gdg-551) fdo#102618
                pass       -> SKIP       (fi-skl-6700k)
        Subgroup basic-flip-after-cursor-varying-size:
                incomplete -> PASS       (fi-skl-6260u)
Test kms_frontbuffer_tracking:
        Subgroup basic:
                pass       -> SKIP       (fi-skl-6700k)
Test kms_pipe_crc_basic:
        Subgroup nonblocking-crc-pipe-b:
                pass       -> DMESG-FAIL (fi-elk-e7500)
        Subgroup nonblocking-crc-pipe-b-frame-sequence:
                pass       -> DMESG-FAIL (fi-elk-e7500)
        Subgroup nonblocking-crc-pipe-c-frame-sequence:
                pass       -> SKIP       (fi-hsw-4770r)
        Subgroup read-crc-pipe-b:
                pass       -> INCOMPLETE (fi-elk-e7500)
Test drv_module_reload:
        Subgroup basic-reload:
                pass       -> DMESG-WARN (fi-skl-6700k)

fdo#102654 https://bugs.freedesktop.org/show_bug.cgi?id=102654
fdo#103097 https://bugs.freedesktop.org/show_bug.cgi?id=103097
fdo#102618 https://bugs.freedesktop.org/show_bug.cgi?id=102618

fi-bdw-5557u     total:289  pass:268  dwarn:0   dfail:0   fail:0   skip:21  time:442s
fi-bdw-gvtdvm    total:289  pass:265  dwarn:0   dfail:0   fail:0   skip:24  time:450s
fi-blb-e6850     total:289  pass:223  dwarn:1   dfail:0   fail:0   skip:65  time:373s
fi-bsw-n3050     total:289  pass:243  dwarn:0   dfail:0   fail:0   skip:46  time:518s
fi-bwr-2160      total:289  pass:183  dwarn:0   dfail:0   fail:0   skip:106 time:265s
fi-bxt-dsi       total:289  pass:259  dwarn:0   dfail:0   fail:0   skip:30  time:501s
fi-bxt-j4205     total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:511s
fi-byt-j1900     total:289  pass:253  dwarn:1   dfail:0   fail:0   skip:35  time:489s
fi-byt-n2820     total:289  pass:249  dwarn:1   dfail:0   fail:0   skip:39  time:480s
fi-cfl-s         total:289  pass:253  dwarn:4   dfail:0   fail:0   skip:32  time:581s
fi-elk-e7500     total:241  pass:188  dwarn:0   dfail:2   fail:0   skip:50 
fi-gdg-551       total:289  pass:178  dwarn:1   dfail:0   fail:1   skip:109 time:249s
fi-glk-1         total:289  pass:261  dwarn:0   dfail:0   fail:0   skip:28  time:581s
fi-hsw-4770      total:289  pass:262  dwarn:0   dfail:0   fail:0   skip:27  time:445s
fi-hsw-4770r     total:289  pass:261  dwarn:0   dfail:0   fail:0   skip:28  time:431s
fi-ilk-650       total:289  pass:228  dwarn:0   dfail:0   fail:0   skip:61  time:442s
fi-ivb-3520m     total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:497s
fi-ivb-3770      total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:455s
fi-kbl-7500u     total:289  pass:264  dwarn:1   dfail:0   fail:0   skip:24  time:487s
fi-kbl-7560u     total:289  pass:270  dwarn:0   dfail:0   fail:0   skip:19  time:578s
fi-kbl-7567u     total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:482s
fi-kbl-r         total:289  pass:262  dwarn:0   dfail:0   fail:0   skip:27  time:584s
fi-pnv-d510      total:289  pass:222  dwarn:1   dfail:0   fail:0   skip:66  time:546s
fi-skl-6260u     total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:445s
fi-skl-6700hq    total:289  pass:263  dwarn:0   dfail:0   fail:0   skip:26  time:654s
fi-skl-6700k     total:289  pass:246  dwarn:2   dfail:0   fail:0   skip:41  time:529s
fi-skl-6770hq    total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:506s
fi-skl-gvtdvm    total:289  pass:266  dwarn:0   dfail:0   fail:0   skip:23  time:456s
fi-snb-2520m     total:289  pass:250  dwarn:0   dfail:0   fail:0   skip:39  time:572s
fi-snb-2600      total:289  pass:249  dwarn:0   dfail:0   fail:0   skip:40  time:414s

9024f1a2827aa921560ee3f985a5b418ef296435 drm-tip: 2017y-10m-19d-12h-57m-03s UTC integration manifest
42f7050e09c9 HAX Enable GuC Submission for CI
e0392a93c335 drm/i915/guc: Workaround the missing user interrupt after preemption
cc6edf2465e4 drm/i915/guc: Preemption! With GuC
4a4a88f2dee4 drm/i915: Rename helpers used for unwinding, use macro for can_preempt
bdfee612afec drm/i915/guc: Keep request->priority for its lifetime
817323b22299 drm/i915: Add information needed to track engine preempt state
3176e1b1d6cd drm/i915: Extract "emit write" part of emit breadcrumb functions
940f7f3df59d drm/i915/guc: Split guc_wq_item_append
a6c6fd69b640 drm/i915/guc: Add a second client, to be used for preemption
7c0155c7f608 drm/i915/guc: Add preemption action to GuC firmware interface
257290af8ae9 drm/i915/guc: Initialize GuC before restarting engines
503486f0e511 drm/i915/guc: Allocate separate shared data object for GuC communication
83fcf0cabbe3 drm/i915/guc: Extract GuC stage desc pool creation into a helper
54aa6fce02f1 drm/i915/guc: Do not use 0 for GuC doorbell cookie

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_6111/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC
  2017-10-19 18:36 ` [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC Michał Winiarski
@ 2017-10-19 19:14   ` Chris Wilson
  2017-10-19 19:16   ` Chris Wilson
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 32+ messages in thread
From: Chris Wilson @ 2017-10-19 19:14 UTC (permalink / raw)
  To: Michał Winiarski, intel-gfx

Quoting Michał Winiarski (2017-10-19 19:36:17)
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index ef14c6d570dc..7d52baf4f3bd 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -2904,6 +2904,16 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine)
>         tasklet_kill(&engine->execlists.irq_tasklet);
>         tasklet_disable(&engine->execlists.irq_tasklet);
>  
> +       /*
> +        * We're using worker to queue preemption requests from the tasklet in
> +        * GuC submission mode.
> +        * Even though tasklet was disabled, we may still have a worker queued.
> +        * Let's make sure that all workers scheduled before disabling the
> +        * tasklet are completed before continuing with the reset.
> +        */
> +       if (i915_modparams.enable_guc_submission)

Don't we have engine->i915->guc.preempt_ctx or something a bit more
specific than a modparam?

> +               flush_workqueue(engine->i915->guc.preempt_wq);

Ok, after some thought, this is the preferred order. If we do the flush
early, we may end up a worker queued before we kill the tasklet. Too
late and tasklet_action spins a little; that's better than parallel
writes into the hw.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC
  2017-10-19 18:36 ` [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC Michał Winiarski
  2017-10-19 19:14   ` Chris Wilson
@ 2017-10-19 19:16   ` Chris Wilson
  2017-10-20  9:00   ` Chris Wilson
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 32+ messages in thread
From: Chris Wilson @ 2017-10-19 19:16 UTC (permalink / raw)
  To: Michał Winiarski, intel-gfx

Quoting Michał Winiarski (2017-10-19 19:36:17)
> diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
> index 689fde1a63a9..17182ce29674 100644
> --- a/drivers/gpu/drm/i915/intel_lrc.h
> +++ b/drivers/gpu/drm/i915/intel_lrc.h
> @@ -107,7 +107,6 @@ intel_lr_context_descriptor(struct i915_gem_context *ctx,
>         return ctx->engine[engine->id].lrc_desc;
>  }
>  
> -
>  /* Execlists */
>  int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv,
>                                     int enable_execlists);
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
> index 8ad9a33e803b..5a68499bf3eb 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> @@ -525,6 +525,12 @@ struct intel_engine_cs {
>         u32 (*get_cmd_length_mask)(u32 cmd_header);
>  };
>  
> +void
> +execlists_cancel_port_requests(struct intel_engine_execlists * const execlists);
> +
> +void execlists_unwind_incomplete_requests(
> +               const struct intel_engine_execlists * const execlists);
> +
>  static inline unsigned int
>  execlists_num_ports(const struct intel_engine_execlists * const execlists)
>  {
> @@ -543,6 +549,8 @@ execlists_port_complete(struct intel_engine_execlists * const execlists,
>         memset(port + m, 0, sizeof(struct execlist_port));
>  }
>  
> +
> +
>  static inline unsigned int

You were doing such a good job at cleaning up the unwanted newlines....
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 11/14] drm/i915: Rename helpers used for unwinding, use macro for can_preempt
  2017-10-19 18:36 ` [PATCH v2 11/14] drm/i915: Rename helpers used for unwinding, use macro for can_preempt Michał Winiarski
@ 2017-10-19 19:18   ` Chris Wilson
  2017-10-19 19:20   ` Chris Wilson
  1 sibling, 0 replies; 32+ messages in thread
From: Chris Wilson @ 2017-10-19 19:18 UTC (permalink / raw)
  To: Michał Winiarski, intel-gfx

Quoting Michał Winiarski (2017-10-19 19:36:16)
> diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
> index f9852c422ea0..dd4708904c85 100644
> --- a/drivers/gpu/drm/i915/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/intel_lrc.c
> @@ -354,8 +354,11 @@ static void unwind_wa_tail(struct drm_i915_gem_request *rq)
>         assert_ring_tail_valid(rq->ring, rq->tail);
>  }
>  
> -static void unwind_incomplete_requests(struct intel_engine_cs *engine)
> +static void execlists_unwind_incomplete_requests(
> +               const struct intel_engine_execlists * const execlists)
>  {
> +       struct intel_engine_cs *engine =
> +               container_of(execlists, typeof(*engine), execlists);

We can't really say its const if we immediately cast it away. We have to
be careful as the compiler may believe us in the caller when we say it's
const...
-Cris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 11/14] drm/i915: Rename helpers used for unwinding, use macro for can_preempt
  2017-10-19 18:36 ` [PATCH v2 11/14] drm/i915: Rename helpers used for unwinding, use macro for can_preempt Michał Winiarski
  2017-10-19 19:18   ` Chris Wilson
@ 2017-10-19 19:20   ` Chris Wilson
  1 sibling, 0 replies; 32+ messages in thread
From: Chris Wilson @ 2017-10-19 19:20 UTC (permalink / raw)
  To: Michał Winiarski, intel-gfx

Quoting Michał Winiarski (2017-10-19 19:36:16)
> @@ -855,10 +853,10 @@ static void intel_lrc_irq_handler(unsigned long data)
>  
>                         if (status & GEN8_CTX_STATUS_ACTIVE_IDLE &&
>                             buf[2*head + 1] == PREEMPT_ID) {
> -                               execlist_cancel_port_requests(execlists);
> +                               execlists_cancel_port_requests(execlists);
>  
>                                 spin_lock_irq(&engine->timeline->lock);
> -                               unwind_incomplete_requests(engine);
> +                               execlists_unwind_incomplete_requests(execlists);
>                                 spin_unlock_irq(&engine->timeline->lock);

For exporting, I vote we move the spin_lock into
execlists_unwind_incomplete_requests().
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 06/14] drm/i915/guc: Add a second client, to be used for preemption
  2017-10-19 18:36 ` [PATCH v2 06/14] drm/i915/guc: Add a second client, to be used for preemption Michał Winiarski
@ 2017-10-19 19:36   ` Michal Wajdeczko
  0 siblings, 0 replies; 32+ messages in thread
From: Michal Wajdeczko @ 2017-10-19 19:36 UTC (permalink / raw)
  To: intel-gfx, Michał Winiarski; +Cc: Dave Gordon

On Thu, 19 Oct 2017 20:36:11 +0200, Michał Winiarski  
<michal.winiarski@intel.com> wrote:

> From: Dave Gordon <david.s.gordon@intel.com>
>
> This second client is created with priority KMD_HIGH, and marked
> as preemptive. This will allow us to request preemption using GuC  
> actions.
>
> v2: Extract clients creation into a helper, debugfs fixups. (Michał)
> Recreate doorbell on init. (Daniele)
> Move clients into an array.
>
> Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
> Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Jeff McGee <jeff.mcgee@intel.com>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> Cc: Oscar Mateo <oscar.mateo@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c        |  11 +--
>  drivers/gpu/drm/i915/i915_guc_submission.c | 107  
> ++++++++++++++++++++---------
>  drivers/gpu/drm/i915/intel_guc.h           |   9 ++-
>  drivers/gpu/drm/i915/intel_uncore.c        |   2 +-
>  4 files changed, 91 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c  
> b/drivers/gpu/drm/i915/i915_debugfs.c
> index c65e381b85f3..daf7a16a4ee2 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2459,7 +2459,7 @@ static bool check_guc_submission(struct seq_file  
> *m)
>  	struct drm_i915_private *dev_priv = node_to_i915(m->private);
>  	const struct intel_guc *guc = &dev_priv->guc;
> -	if (!guc->execbuf_client) {
> +	if (!guc->client[SUBMIT]) {
>  		seq_printf(m, "GuC submission %s\n",
>  			   HAS_GUC_SCHED(dev_priv) ?
>  			   "disabled" :
> @@ -2474,6 +2474,7 @@ static int i915_guc_info(struct seq_file *m, void  
> *data)
>  {
>  	struct drm_i915_private *dev_priv = node_to_i915(m->private);
>  	const struct intel_guc *guc = &dev_priv->guc;
> +	u32 i;
> 	if (!check_guc_submission(m))
>  		return 0;
> @@ -2482,8 +2483,10 @@ static int i915_guc_info(struct seq_file *m, void  
> *data)
>  	seq_printf(m, "\t%*pb\n", GUC_NUM_DOORBELLS, guc->doorbell_bitmap);
>  	seq_printf(m, "Doorbell next cacheline: 0x%x\n\n", guc->db_cacheline);
> -	seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->execbuf_client);
> -	i915_guc_client_info(m, dev_priv, guc->execbuf_client);
> +	for (i = 0; i < I915_GUC_NUM_CLIENTS; i++) {
> +		seq_printf(m, "\nGuC client @ %p:\n", guc->client[i]);
> +		i915_guc_client_info(m, dev_priv, guc->client[i]);
> +	}
> 	i915_guc_log_info(m, dev_priv);
> @@ -2497,7 +2500,7 @@ static int i915_guc_stage_pool(struct seq_file *m,  
> void *data)
>  	struct drm_i915_private *dev_priv = node_to_i915(m->private);
>  	const struct intel_guc *guc = &dev_priv->guc;
>  	struct guc_stage_desc *desc = guc->stage_desc_pool_vaddr;
> -	struct i915_guc_client *client = guc->execbuf_client;
> +	struct i915_guc_client *client = guc->client[SUBMIT];
>  	unsigned int tmp;
>  	int index;
> diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c  
> b/drivers/gpu/drm/i915/i915_guc_submission.c
> index 0bd1fcffa78d..d8b8125aa4cc 100644
> --- a/drivers/gpu/drm/i915/i915_guc_submission.c
> +++ b/drivers/gpu/drm/i915/i915_guc_submission.c
> @@ -33,10 +33,11 @@
>   *
>   * GuC client:
>   * A i915_guc_client refers to a submission path through GuC.  
> Currently, there
> - * is only one of these (the execbuf_client) and this one is charged  
> with all
> - * submissions to the GuC. This struct is the owner of a doorbell, a  
> process
> - * descriptor and a workqueue (all of them inside a single gem object  
> that
> - * contains all required pages for these elements).
> + * are two clients. One of them (SUBMIT) is charged with all  
> submissions to the
> + * GuC, the other one (PREEMPT) is responsible for preempting the  
> SUBMIT one.
> + * This struct is the owner of a doorbell, a process descriptor and a  
> workqueue
> + * (all of them inside a single gem object that contains all required  
> pages for
> + * these elements).

Hmm, it's little unfortunate that SUBMIT and PREEMPT enums are defined
in intel_guc.h while mostly used in guc_submission.c

>   *
>   * GuC stage descriptor:
>   * During initialization, the driver allocates a static pool of 1024  
> such
> @@ -363,6 +364,8 @@ static void guc_stage_desc_init(struct intel_guc  
> *guc,
>  	memset(desc, 0, sizeof(*desc));
> 	desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE |  
> GUC_STAGE_DESC_ATTR_KERNEL;
> +	if (client->priority <= GUC_CLIENT_PRIORITY_HIGH)
> +		desc->attribute |= GUC_STAGE_DESC_ATTR_PREEMPT;
>  	desc->stage_id = client->stage_id;
>  	desc->priority = client->priority;
>  	desc->db_id = client->doorbell_id;
> @@ -553,7 +556,7 @@ static void i915_guc_submit(struct intel_engine_cs  
> *engine)
>  {
>  	struct drm_i915_private *dev_priv = engine->i915;
>  	struct intel_guc *guc = &dev_priv->guc;
> -	struct i915_guc_client *client = guc->execbuf_client;
> +	struct i915_guc_client *client = guc->client[SUBMIT];

what about using helpers like:

static inline
struct i915_guc_client *guc_exec_client(struct intel_guc *guc)
{
	return guc->client[SUBMIT];
}

> +	struct i915_guc_client *client = guc->client[SUBMIT];

>  	struct intel_engine_execlists * const execlists = &engine->execlists;
>  	struct execlist_port *port = execlists->port;
>  	const unsigned int engine_id = engine->id;
> @@ -750,10 +753,11 @@ static int __reset_doorbell(struct  
> i915_guc_client* client, u16 db_id)
>   */
>  static int guc_init_doorbell_hw(struct intel_guc *guc)
>  {
> -	struct i915_guc_client *client = guc->execbuf_client;
> +	struct i915_guc_client *client = guc->client[SUBMIT];
>  	bool recreate_first_client = false;
>  	u16 db_id;
>  	int ret;
> +	u32 i;
> 	/* For unused doorbells, make sure they are disabled */
>  	for_each_clear_bit(db_id, guc->doorbell_bitmap, GUC_NUM_DOORBELLS) {
> @@ -761,7 +765,7 @@ static int guc_init_doorbell_hw(struct intel_guc  
> *guc)
>  			continue;
> 		if (has_doorbell(client)) {
> -			/* Borrow execbuf_client (we will recreate it later) */
> +			/* Borrow submit client (we will recreate it later) */
>  			destroy_doorbell(client);
>  			recreate_first_client = true;
>  		}
> @@ -780,14 +784,14 @@ static int guc_init_doorbell_hw(struct intel_guc  
> *guc)
>  		__update_doorbell_desc(client, client->doorbell_id);
>  	}
> -	/* Now for every client (and not only execbuf_client) make sure their
> +	/* Now for every client (not only submission client) make sure their
>  	 * doorbells are known by the GuC */
> -	//for (client = client_list; client != NULL; client = client->next)
> +	for (i = 0; i < I915_GUC_NUM_CLIENTS; i++)
>  	{
> -		ret = __create_doorbell(client);
> +		ret = __create_doorbell(guc->client[i]);
>  		if (ret) {
>  			DRM_ERROR("Couldn't recreate client %u doorbell: %d\n",
> -				client->stage_id, ret);
> +				  guc->client[i]->stage_id, ret);
>  			return ret;
>  		}
>  	}
> @@ -914,6 +918,47 @@ static void guc_client_free(struct i915_guc_client  
> *client)
>  	kfree(client);
>  }
> +static int guc_clients_create(struct intel_guc *guc)
> +{
> +	struct drm_i915_private *dev_priv = guc_to_i915(guc);
> +	struct i915_guc_client *client;
> +
> +	client = guc_client_alloc(dev_priv,
> +				  INTEL_INFO(dev_priv)->ring_mask,
> +				  GUC_CLIENT_PRIORITY_KMD_NORMAL,
> +				  dev_priv->kernel_context);
> +	if (IS_ERR(client)) {
> +		DRM_ERROR("Failed to create GuC client for submission!\n");
> +		return PTR_ERR(client);
> +	}
> +	guc->client[SUBMIT] = client;
> +
> +	client = guc_client_alloc(dev_priv,
> +				  INTEL_INFO(dev_priv)->ring_mask,
> +				  GUC_CLIENT_PRIORITY_KMD_HIGH,
> +				  dev_priv->preempt_context);
> +	if (IS_ERR(client)) {
> +		DRM_ERROR("Failed to create GuC client for preemption!\n");
> +		guc_client_free(guc->client[SUBMIT]);
> +		guc->client[SUBMIT] = NULL;
> +		return PTR_ERR(client);
> +	}
> +	guc->client[PREEMPT] = client;
> +
> +	return 0;
> +}
> +
> +static void guc_clients_destroy(struct intel_guc *guc)
> +{
> +	struct i915_guc_client *client;
> +	u32 i;
> +
> +	for (i = 0; i < I915_GUC_NUM_CLIENTS; i++) {
> +		client = fetch_and_zero(&guc->client[i]);
> +		guc_client_free(client);
> +	}
> +}
> +
>  static void guc_policy_init(struct guc_policy *policy)
>  {
>  	policy->execution_quantum = POLICY_DEFAULT_EXECUTION_QUANTUM_US;
> @@ -1143,7 +1188,6 @@ static void guc_interrupts_release(struct  
> drm_i915_private *dev_priv)
>  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;
>  	int err;
> @@ -1161,28 +1205,29 @@ int i915_guc_submission_enable(struct  
> drm_i915_private *dev_priv)
>  		     sizeof(struct guc_wq_item) *
>  		     I915_NUM_ENGINES > GUC_WQ_SIZE);
> -	if (!client) {
> -		client = guc_client_alloc(dev_priv,
> -					  INTEL_INFO(dev_priv)->ring_mask,
> -					  GUC_CLIENT_PRIORITY_KMD_NORMAL,
> -					  dev_priv->kernel_context);
> -		if (IS_ERR(client)) {
> -			DRM_ERROR("Failed to create GuC client for execbuf!\n");
> -			return PTR_ERR(client);
> -		}
> -
> -		guc->execbuf_client = client;
> +	/*
> +	 * We're being called on both module initialization and on reset,
> +	 * until this flow is changed, we're using regular client presence to
> +	 * determine which case are we in, and whether we should allocate new
> +	 * clients or just reset their workqueues.
> +	 */
> +	if (!guc->client[SUBMIT]) {
> +		GEM_BUG_ON(guc->client[PREEMPT]);
> +		err = guc_clients_create(guc);
> +		if (err)
> +			return err;
> +	} else {
> +		guc_reset_wq(guc->client[SUBMIT]);
> +		guc_reset_wq(guc->client[PREEMPT]);
>  	}
> 	err = intel_guc_sample_forcewake(guc);
>  	if (err)
> -		goto err_execbuf_client;
> -
> -	guc_reset_wq(client);
> +		goto err_free_clients;
> 	err = guc_init_doorbell_hw(guc);
>  	if (err)
> -		goto err_execbuf_client;
> +		goto err_free_clients;
> 	/* Take over from manual control of ELSP (execlists) */
>  	guc_interrupts_capture(dev_priv);
> @@ -1194,9 +1239,8 @@ int i915_guc_submission_enable(struct  
> drm_i915_private *dev_priv)
> 	return 0;
> -err_execbuf_client:
> -	guc_client_free(guc->execbuf_client);
> -	guc->execbuf_client = NULL;
> +err_free_clients:
> +	guc_clients_destroy(guc);
>  	return err;
>  }
> @@ -1209,6 +1253,5 @@ void i915_guc_submission_disable(struct  
> drm_i915_private *dev_priv)
>  	/* Revert back to manual ELSP submission */
>  	intel_engines_reset_default_submission(dev_priv);
> -	guc_client_free(guc->execbuf_client);
> -	guc->execbuf_client = NULL;
> +	guc_clients_destroy(guc);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_guc.h  
> b/drivers/gpu/drm/i915/intel_guc.h
> index aa1583167b0a..15eadf27b7ae 100644
> --- a/drivers/gpu/drm/i915/intel_guc.h
> +++ b/drivers/gpu/drm/i915/intel_guc.h
> @@ -39,6 +39,13 @@
>   * pool and doorbells. intel_guc owns a i915_guc_client to replace the  
> legacy
>   * ExecList submission.
>   */
> +
> +#define I915_GUC_NUM_CLIENTS 2
> +enum i915_guc_client_id {
> +	SUBMIT = 0,
> +	PREEMPT
> +};
> +
>  struct intel_guc {
>  	struct intel_uc_fw fw;
>  	struct intel_guc_log log;
> @@ -57,7 +64,7 @@ struct intel_guc {
>  	struct i915_vma *shared_data;
>  	void *shared_data_vaddr;
> -	struct i915_guc_client *execbuf_client;
> +	struct i915_guc_client *client[I915_GUC_NUM_CLIENTS];
> 	DECLARE_BITMAP(doorbell_bitmap, GUC_NUM_DOORBELLS);
>  	/* Cyclic counter mod pagesize	*/
> diff --git a/drivers/gpu/drm/i915/intel_uncore.c  
> b/drivers/gpu/drm/i915/intel_uncore.c
> index 20e3c65c0999..3d91d8a28d9f 100644
> --- a/drivers/gpu/drm/i915/intel_uncore.c
> +++ b/drivers/gpu/drm/i915/intel_uncore.c
> @@ -1795,7 +1795,7 @@ bool intel_has_gpu_reset(struct drm_i915_private  
> *dev_priv)
>  bool intel_has_reset_engine(struct drm_i915_private *dev_priv)
>  {
>  	return (dev_priv->info.has_reset_engine &&
> -		!dev_priv->guc.execbuf_client &&
> +		!dev_priv->guc.client[SUBMIT] &&
>  		i915_modparams.reset >= 2);
>  }
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 13/14] drm/i915/guc: Workaround the missing user interrupt after preemption
  2017-10-19 18:36 ` [PATCH 13/14] drm/i915/guc: Workaround the missing user interrupt after preemption Michał Winiarski
@ 2017-10-19 19:44   ` Chris Wilson
  2017-10-20 17:22     ` Chris Wilson
  2017-10-20 16:08   ` Chris Wilson
  1 sibling, 1 reply; 32+ messages in thread
From: Chris Wilson @ 2017-10-19 19:44 UTC (permalink / raw)
  To: Michał Winiarski, intel-gfx

Quoting Michał Winiarski (2017-10-19 19:36:18)
> With GuC, we're scheduling tasklet on USER_INTERRUPT - since some work
> has completed, perhaps we're able to submit some more work. We're doing
> similar thing for preemption - after preemption has completed, it's time
> to schedule the tasklet and submit more work (since the engine is now
> idle). Unfortunately, we can hit the scenarios where the preemption is
> done, but the interrupt is nowhere to be seen. To work around the
> problem, let's use a delayed work that's kicking the tasklet if
> preemption is done, and queueing itself otherwise.

I'm not buying it yet. Missing USER_INTERRUPT would not be guc specific
(surely?) and so we would be getting similar missed-breadcrumb warnings
on skl+. We dedicate a lot of CI towards detecting those...

The first alternative that springs to mind is bad ordering between ggtt
write and MI_USER_INTERRUPT, but that too is common to execlists, and
also results in missed-breadcrumb warnings (which are notable by their
absence). Though having said that, the HWSP ordering issue with
intel_iommu is worrying me that we have similar issues with breadcrumbs
+ intel_iommu. Is iommu a factor?

In short, if this is a problem here, it should be a problem everywhere.
Right?
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC
  2017-10-19 18:36 ` [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC Michał Winiarski
  2017-10-19 19:14   ` Chris Wilson
  2017-10-19 19:16   ` Chris Wilson
@ 2017-10-20  9:00   ` Chris Wilson
  2017-10-20 17:00   ` Chris Wilson
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 32+ messages in thread
From: Chris Wilson @ 2017-10-20  9:00 UTC (permalink / raw)
  To: Michał Winiarski, intel-gfx

Quoting Michał Winiarski (2017-10-19 19:36:17)
> @@ -686,10 +802,23 @@ static void i915_guc_irq_handler(unsigned long data)
>         struct intel_engine_cs * const engine = (struct intel_engine_cs *)data;
>         struct intel_engine_execlists * const execlists = &engine->execlists;
>         struct execlist_port *port = execlists->port;
> -       const struct execlist_port * const last_port =
> -               &execlists->port[execlists->port_mask];
>         struct drm_i915_gem_request *rq;
>  
> +       if (READ_ONCE(execlists->preempt) &&
> +           intel_read_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX) ==
> +           GUC_PREEMPT_FINISHED) {
> +               execlists_cancel_port_requests(&engine->execlists);
> +
> +               spin_lock_irq(&engine->timeline->lock);
> +               execlists_unwind_incomplete_requests(execlists);
> +               spin_unlock_irq(&engine->timeline->lock);
> +
> +               wait_for_guc_preempt_report(engine);
> +
> +               WRITE_ONCE(execlists->preempt, false);
> +               intel_write_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX, 0);
> +       }
> +
>         rq = port_request(&port[0]);
>         while (rq && i915_gem_request_completed(rq)) {
>                 trace_i915_gem_request_out(rq);
> @@ -701,7 +830,7 @@ static void i915_guc_irq_handler(unsigned long data)
>                 rq = port_request(&port[0]);
>         }
>  
> -       if (!port_isset(last_port))
> +       if (!READ_ONCE(execlists->preempt))
>                 i915_guc_dequeue(engine);
>  }

    kworker/u9:1-1687  [000] d..1  2215.658429: inject_preempt_context: GUC WQ tail=330, head=320
    kworker/u9:1-1687  [000] d..1  2215.658429: inject_preempt_context: RING tail=1a0
    kworker/u9:1-1687  [000] ....  2215.658429: inject_preempt_context: PREEMPT: WQI ADDED ring=2, guc_id=1
    kworker/u9:1-1687  [000] ....  2215.658429: inject_preempt_context: PREEMPT: GUC ACTION SENDING ring=2, guc_id=1
          <idle>-0     [003] d.h1  2215.658456: gen8_cs_irq_handler: USER INTERRUPT ring=2, guc_id=1
          <idle>-0     [003] ..s1  2215.658460: i915_guc_irq_handler: PREEMPT: WAITING FOR GUC COMPLETE ring=2, guc_id=1
          <idle>-0     [000] d.h1  2215.658462: gen8_cs_irq_handler: USER INTERRUPT ring=2, guc_id=1
          <idle>-0     [003] ..s1  2215.658473: i915_guc_irq_handler: PREEMPT: FINISHED ring=2, guc_id=1
          <idle>-0     [003] d.s2  2215.658473: i915_gem_request_execute: dev=0, ring=2, ctx=2983, seqno=6, global=0
          <idle>-0     [003] d.s2  2215.658476: i915_gem_request_in: dev=0, ring=2, ctx=2983, seqno=6, global=916, port=0
          <idle>-0     [003] d.s2  2215.658476: i915_gem_request_execute: dev=0, ring=2, ctx=3298, seqno=6, global=0
          <idle>-0     [003] d.s2  2215.658477: i915_gem_request_in: dev=0, ring=2, ctx=3298, seqno=6, global=917, port=1
          <idle>-0     [002] d.h1  2215.658510: gen8_cs_irq_handler: USER INTERRUPT ring=2, guc_id=1
          <idle>-0     [000] d.h1  2215.658517: gen8_cs_irq_handler: USER INTERRUPT ring=2, guc_id=1
          <idle>-0     [002] ..s1  2215.658520: i915_gem_request_out: dev=0, ring=2, ctx=2983, seqno=6, global=916
          <idle>-0     [002] ..s1  2215.658521: i915_gem_request_out: dev=0, ring=2, ctx=3298, seqno=6, global=917
          <idle>-0     [002] d.s2  2215.658521: i915_gem_request_execute: dev=0, ring=2, ctx=3323, seqno=5, global=0
          <idle>-0     [002] d.s2  2215.658522: i915_gem_request_in: dev=0, ring=2, ctx=3323, seqno=5, global=918, port=0
          <idle>-0     [002] d.s2  2215.658523: i915_gem_request_execute: dev=0, ring=2, ctx=3363, seqno=4, global=0
          <idle>-0     [002] d.s2  2215.658524: i915_gem_request_in: dev=0, ring=2, ctx=3363, seqno=4, global=919, port=1
          <idle>-0     [002] d.h1  2215.658569: gen8_cs_irq_handler: USER INTERRUPT ring=2, guc_id=1
          <idle>-0     [002] ..s1  2215.658572: i915_gem_request_out: dev=0, ring=2, ctx=3323, seqno=5, global=918
          <idle>-0     [002] ..s1  2215.658572: i915_gem_request_out: dev=0, ring=2, ctx=3363, seqno=4, global=919
          <idle>-0     [002] d.s2  2215.658573: i915_gem_request_execute: dev=0, ring=2, ctx=3673, seqno=2, global=0
          <idle>-0     [000] d.h1  2215.658574: gen8_cs_irq_handler: USER INTERRUPT ring=2, guc_id=1
          <idle>-0     [002] d.s2  2215.658576: i915_gem_request_in: dev=0, ring=2, ctx=3673, seqno=2, global=920, port=0
          <idle>-0     [002] d.s2  2215.658576: i915_gem_request_execute: dev=0, ring=2, ctx=2783, seqno=3, global=0
          <idle>-0     [002] d.s2  2215.658578: i915_gem_request_in: dev=0, ring=2, ctx=2783, seqno=3, global=921, port=1
     ksoftirqd/0-7     [000] d.H2  2215.658587: i915_gem_request_submit: dev=0, ring=2, ctx=3003, seqno=3, global=0
     ksoftirqd/0-7     [000] d.s1  2215.658591: i915_guc_irq_handler: PREEMPT: WORKER QUEUED ring=2, guc_id=1
          <idle>-0     [002] d.h1  2215.658649: gen8_cs_irq_handler: USER INTERRUPT ring=2, guc_id=1
          <idle>-0     [000] d.h1  2215.658656: gen8_cs_irq_handler: USER INTERRUPT ring=2, guc_id=1
          <idle>-0     [002] ..s1  2215.658659: i915_guc_irq_handler: PREEMPT: IN PROGRESS, NOT DONE ring=2, guc_id=1
          <idle>-0     [002] ..s1  2215.658659: i915_gem_request_out: dev=0, ring=2, ctx=3673, seqno=2, global=920
          <idle>-0     [002] ..s1  2215.658660: i915_gem_request_out: dev=0, ring=2, ctx=2783, seqno=3, global=921
          <idle>-0     [001] d.h2  2215.658663: i915_gem_request_submit: dev=0, ring=2, ctx=4013, seqno=6, global=0
          <idle>-0     [002] dNh2  2215.658725: i915_gem_request_submit: dev=0, ring=2, ctx=2928, seqno=6, global=0
    kworker/u9:1-1687  [000] d..1  2215.660436: inject_preempt_context: GUC WQ tail=340, head=330
    kworker/u9:1-1687  [000] d..1  2215.660436: inject_preempt_context: RING tail=1c0
    kworker/u9:1-1687  [000] ....  2215.660437: inject_preempt_context: PREEMPT: WQI ADDED ring=2, guc_id=1
    kworker/u9:1-1687  [000] ....  2215.660437: inject_preempt_context: PREEMPT: GUC ACTION SENDING ring=2, guc_id=1

This suggests that the decision to queue the preempt-worker is racy, and
not evidence that the USER_INTERRUPT went missing. Do you have a better
example?
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 13/14] drm/i915/guc: Workaround the missing user interrupt after preemption
  2017-10-19 18:36 ` [PATCH 13/14] drm/i915/guc: Workaround the missing user interrupt after preemption Michał Winiarski
  2017-10-19 19:44   ` Chris Wilson
@ 2017-10-20 16:08   ` Chris Wilson
  1 sibling, 0 replies; 32+ messages in thread
From: Chris Wilson @ 2017-10-20 16:08 UTC (permalink / raw)
  To: Michał Winiarski, intel-gfx

Quoting Michał Winiarski (2017-10-19 19:36:18)
> +#define GUC_LOST_IRQ_WORK_DELAY_MS 100
> +static void guc_lost_user_interrupt(struct work_struct *work)
> +{
> +       struct guc_preempt_work *preempt_work =
> +               container_of(to_delayed_work(work), typeof(*preempt_work),
> +                            lost_irq_work);
> +       struct intel_engine_cs *engine = preempt_work->engine;
> +       struct intel_guc *guc = &engine->i915->guc;

Since you switched preempt_work to be stored within intel_guc,
you can use container_of to get to the guc and cut out the dance.
Here and inject_preempt_context.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC
  2017-10-19 18:36 ` [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC Michał Winiarski
                     ` (2 preceding siblings ...)
  2017-10-20  9:00   ` Chris Wilson
@ 2017-10-20 17:00   ` Chris Wilson
  2017-10-23 23:14   ` Daniele Ceraolo Spurio
  2017-10-25 18:15   ` Chris Wilson
  5 siblings, 0 replies; 32+ messages in thread
From: Chris Wilson @ 2017-10-20 17:00 UTC (permalink / raw)
  To: Michał Winiarski, intel-gfx

Quoting Michał Winiarski (2017-10-19 19:36:17)
> @@ -686,10 +802,23 @@ static void i915_guc_irq_handler(unsigned long data)
>         struct intel_engine_cs * const engine = (struct intel_engine_cs *)data;
>         struct intel_engine_execlists * const execlists = &engine->execlists;
>         struct execlist_port *port = execlists->port;
> -       const struct execlist_port * const last_port =
> -               &execlists->port[execlists->port_mask];
>         struct drm_i915_gem_request *rq;
>  
> +       if (READ_ONCE(execlists->preempt) &&
> +           intel_read_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX) ==
> +           GUC_PREEMPT_FINISHED) {
> +               execlists_cancel_port_requests(&engine->execlists);
> +
> +               spin_lock_irq(&engine->timeline->lock);
> +               execlists_unwind_incomplete_requests(execlists);
> +               spin_unlock_irq(&engine->timeline->lock);
> +
> +               wait_for_guc_preempt_report(engine);
> +
> +               WRITE_ONCE(execlists->preempt, false);
> +               intel_write_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX, 0);
> +       }
> +
>         rq = port_request(&port[0]);
>         while (rq && i915_gem_request_completed(rq)) {
>                 trace_i915_gem_request_out(rq);

I don't think we have the ordering right here for
cancel_port_requests(). It should only be called for what are
effectively incomplete requests, or else the
INTEL_CONTEXT_SCHEDULE_PREEMPTED is a misnomer. It doesn't look like it
makes any great difference in the over scheme of things, but I'm tempted
to put a GEM_BUG_ON(i915_gem_request_completed(rq)) there.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 13/14] drm/i915/guc: Workaround the missing user interrupt after preemption
  2017-10-19 19:44   ` Chris Wilson
@ 2017-10-20 17:22     ` Chris Wilson
  2017-10-20 17:42       ` Daniele Ceraolo Spurio
  0 siblings, 1 reply; 32+ messages in thread
From: Chris Wilson @ 2017-10-20 17:22 UTC (permalink / raw)
  To: Michał Winiarski, intel-gfx

Quoting Chris Wilson (2017-10-19 20:44:41)
> Quoting Michał Winiarski (2017-10-19 19:36:18)
> > With GuC, we're scheduling tasklet on USER_INTERRUPT - since some work
> > has completed, perhaps we're able to submit some more work. We're doing
> > similar thing for preemption - after preemption has completed, it's time
> > to schedule the tasklet and submit more work (since the engine is now
> > idle). Unfortunately, we can hit the scenarios where the preemption is
> > done, but the interrupt is nowhere to be seen. To work around the
> > problem, let's use a delayed work that's kicking the tasklet if
> > preemption is done, and queueing itself otherwise.
> 
> I'm not buying it yet.

I think I know what it is. I think it is as simple as us turning off the
irq when there's no more requests being signaled on the engine.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 13/14] drm/i915/guc: Workaround the missing user interrupt after preemption
  2017-10-20 17:22     ` Chris Wilson
@ 2017-10-20 17:42       ` Daniele Ceraolo Spurio
  0 siblings, 0 replies; 32+ messages in thread
From: Daniele Ceraolo Spurio @ 2017-10-20 17:42 UTC (permalink / raw)
  To: Chris Wilson, Michał Winiarski, intel-gfx



On 20/10/17 10:22, Chris Wilson wrote:
> Quoting Chris Wilson (2017-10-19 20:44:41)
>> Quoting Michał Winiarski (2017-10-19 19:36:18)
>>> With GuC, we're scheduling tasklet on USER_INTERRUPT - since some work
>>> has completed, perhaps we're able to submit some more work. We're doing
>>> similar thing for preemption - after preemption has completed, it's time
>>> to schedule the tasklet and submit more work (since the engine is now
>>> idle). Unfortunately, we can hit the scenarios where the preemption is
>>> done, but the interrupt is nowhere to be seen. To work around the
>>> problem, let's use a delayed work that's kicking the tasklet if
>>> preemption is done, and queueing itself otherwise.
>>
>> I'm not buying it yet.
> 
> I think I know what it is. I think it is as simple as us turning off the
> irq when there's no more requests being signaled on the engine.
> -Chris

I can confirm this, I was just about to reply with the same findings ;)
By hackily adding USER_INTERRUPT to irq_keep_mask we've been able to run 
exec_whisper@fds-priority several time in a row with no problems.

Daniele
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 01/14] drm/i915/guc: Do not use 0 for GuC doorbell cookie
  2017-10-19 18:36 ` [PATCH 01/14] drm/i915/guc: Do not use 0 for GuC doorbell cookie Michał Winiarski
@ 2017-10-21  6:28   ` Sagar Arun Kamble
  0 siblings, 0 replies; 32+ messages in thread
From: Sagar Arun Kamble @ 2017-10-21  6:28 UTC (permalink / raw)
  To: Michał Winiarski, intel-gfx



On 10/20/2017 12:06 AM, Michał Winiarski wrote:
> Apparently, this value is reserved and may be interpreted as changing
> doorbell ownership. Even though we're not observing any side effects
> now, let's skip over it to be consistent with the spec.
>
> Suggested-by: Sagar Arun Kamble <sagar.a.kamble@intel.com>
> Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_guc_submission.c | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
> index a2e8114b739d..02ca2a412c62 100644
> --- a/drivers/gpu/drm/i915/i915_guc_submission.c
> +++ b/drivers/gpu/drm/i915/i915_guc_submission.c
> @@ -475,9 +475,10 @@ static void guc_ring_doorbell(struct i915_guc_client *client)
>   	/* pointer of current doorbell cacheline */
>   	db = __get_doorbell(client);
>   
> -	/* we're not expecting the doorbell cookie to change behind our back */
> +	/* we're not expecting the doorbell cookie to change behind our back,
> +	 * we also need to treat 0 as a reserved value */
Need to fix /* & */.
Change looks good to me.
Reviewed-by: Sagar Arun Kamble <sagar.a.kamble@gmail.com>
>   	cookie = READ_ONCE(db->cookie);
> -	WARN_ON_ONCE(xchg(&db->cookie, cookie + 1) != cookie);
> +	WARN_ON_ONCE(xchg(&db->cookie, cookie + 1 ?: cookie + 2) != cookie);
>   
>   	/* XXX: doorbell was lost and need to acquire it again */
>   	GEM_BUG_ON(db->db_status != GUC_DOORBELL_ENABLED);

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC
  2017-10-19 18:36 ` [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC Michał Winiarski
                     ` (3 preceding siblings ...)
  2017-10-20 17:00   ` Chris Wilson
@ 2017-10-23 23:14   ` Daniele Ceraolo Spurio
  2017-10-25 18:15   ` Chris Wilson
  5 siblings, 0 replies; 32+ messages in thread
From: Daniele Ceraolo Spurio @ 2017-10-23 23:14 UTC (permalink / raw)
  To: Michał Winiarski, intel-gfx, Tomasz Lis

<snip>

> +
> +#define GUC_PREEMPT_FINISHED 0x1
> +#define GUC_PREEMPT_BREADCRUMB_DWORDS 0x8
> +static void inject_preempt_context(struct work_struct *work)
> +{
> +	struct guc_preempt_work *preempt_work =
> +		container_of(work, typeof(*preempt_work), work);
> +	struct intel_engine_cs *engine = preempt_work->engine;
> +	struct intel_guc *guc = &engine->i915->guc;
> +	struct i915_guc_client *client = guc->client[PREEMPT];
> +	struct intel_ring *ring = client->owner->engine[engine->id].ring;
> +	u32 ctx_desc = lower_32_bits(intel_lr_context_descriptor(client->owner,
> +								 engine));
> +	u32 *cs = ring->vaddr + ring->tail;
> +	u32 data[7];
> +
> +	if (engine->id == RCS) {
> +		cs = gen8_emit_ggtt_write_rcs(cs, GUC_PREEMPT_FINISHED,
> +				intel_hws_preempt_done_address(engine));
> +	} else {
> +		cs = gen8_emit_ggtt_write(cs, GUC_PREEMPT_FINISHED,
> +				intel_hws_preempt_done_address(engine));
> +		*cs++ = MI_NOOP;
> +		*cs++ = MI_NOOP;
> +	}
> +	*cs++ = MI_USER_INTERRUPT;
> +	*cs++ = MI_NOOP;
> +
> +	GEM_BUG_ON(!IS_ALIGNED(ring->size,
> +			       GUC_PREEMPT_BREADCRUMB_DWORDS * sizeof(u32)));
> +	GEM_BUG_ON((void*)cs - (ring->vaddr + ring->tail) !=
> +		   GUC_PREEMPT_BREADCRUMB_DWORDS * sizeof(u32));
> +
> +	ring->tail += GUC_PREEMPT_BREADCRUMB_DWORDS * sizeof(u32);
> +	ring->tail &= (ring->size - 1);
> +
> +	flush_ggtt_writes(ring->vma);
> +
> +	spin_lock_irq(&client->wq_lock);
> +	guc_wq_item_append(client, engine->guc_id, ctx_desc,
> +			   ring->tail / sizeof(u64), 0);
> +	spin_unlock_irq(&client->wq_lock);
> +
> +	data[0] = INTEL_GUC_ACTION_REQUEST_PREEMPTION;
> +	data[1] = client->stage_id;
> +	data[2] = INTEL_GUC_PREEMPT_OPTION_IMMEDIATE |

I was looking at how the GuC handles these flags and from what I've seen 
INTEL_GUC_PREEMPT_OPTION_IMMEDIATE doesn't seem to be used anywhere in 
GuC FW anymore (even if it still exist in the interface), so I believe 
it should be safe to drop it.

Daniele

> +		  INTEL_GUC_PREEMPT_OPTION_DROP_WORK_Q |
> +		  INTEL_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q;
> +	data[3] = engine->guc_id;
> +	data[4] = guc->client[SUBMIT]->priority;
> +	data[5] = guc->client[SUBMIT]->stage_id;
> +	data[6] = guc_ggtt_offset(guc->shared_data);
> +
> +	if (WARN_ON(intel_guc_send(guc, data, ARRAY_SIZE(data)))) {
> +		WRITE_ONCE(engine->execlists.preempt, false);
> +		tasklet_schedule(&engine->execlists.irq_tasklet);
> +	}
> +}
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC
  2017-10-19 18:36 ` [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC Michał Winiarski
                     ` (4 preceding siblings ...)
  2017-10-23 23:14   ` Daniele Ceraolo Spurio
@ 2017-10-25 18:15   ` Chris Wilson
  5 siblings, 0 replies; 32+ messages in thread
From: Chris Wilson @ 2017-10-25 18:15 UTC (permalink / raw)
  To: Michał Winiarski, intel-gfx

Quoting Michał Winiarski (2017-10-19 19:36:17)
> Pretty similar to what we have on execlists.
> We're reusing most of the GEM code, however, due to GuC quirks we need a
> couple of extra bits.
> Preemption is implemented as GuC action, and actions can be pretty slow.
> Because of that, we're using a mutex to serialize them. Since we're
> requesting preemption from the tasklet, the task of creating a workitem
> and wrapping it in GuC action is delegated to a worker.
> 
> To distinguish that preemption has finished, we're using additional
> piece of HWSP, and since we're not getting context switch interrupts,
> we're also adding a user interrupt.
> 
> The fact that our special preempt context has completed unfortunately
> doesn't mean that we're ready to submit new work. We also need to wait
> for GuC to finish its own processing.

Should we be concerned about the latency of a preemption switch here?
For execlists the impact on a stress test like whisper/contexts-priority
it is barely noticeable, the same cannot be said here.

Hmm, I guess I need to amend gem_exec_latency to include a measurement.
And benchmarks/ needs some TLC. Not that I really expect it to show up
at e.g. the GL client level, but one day someone may care enough to
complain; better to be prepared.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 04/14] drm/i915/guc: Initialize GuC before restarting engines
  2017-10-19 18:36 ` [PATCH 04/14] drm/i915/guc: Initialize GuC before restarting engines Michał Winiarski
@ 2017-10-25 18:44   ` Chris Wilson
  0 siblings, 0 replies; 32+ messages in thread
From: Chris Wilson @ 2017-10-25 18:44 UTC (permalink / raw)
  To: Michał Winiarski, intel-gfx; +Cc: Mika Kuoppala

Quoting Michał Winiarski (2017-10-19 19:36:09)
> Now that we're handling request resubmission the same way as regular
> submission (from the tasklet), we can move GuC initialization earlier,
> before restarting the engines. This way, we're no longer being in the
> state of flux during engine restart - we're already in user requested
> submission mode.
> 
> Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> Cc: Michel Thierry <michel.thierry@intel.com>
> Cc: Mika Kuoppala <mika.kuoppala@intel.com>
> Cc: Oscar Mateo <oscar.mateo@intel.com>
> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>

I've picked this one for dinq, any others you feel are not part of
preemption per-se and would like to push ahead of the main series?
Though it looks like preemption is robust, so maybe there won't be much
of a delay now?
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* ✗ Fi.CI.BAT: failure for Preemption with GuC, third attempt
  2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
                   ` (14 preceding siblings ...)
  2017-10-19 19:11 ` ✗ Fi.CI.BAT: failure for Preemption with GuC, third attempt Patchwork
@ 2017-10-26 21:21 ` Patchwork
  15 siblings, 0 replies; 32+ messages in thread
From: Patchwork @ 2017-10-26 21:21 UTC (permalink / raw)
  To: Michał Winiarski; +Cc: intel-gfx

== Series Details ==

Series: Preemption with GuC, third attempt
URL   : https://patchwork.freedesktop.org/series/32320/
State : failure

== Summary ==

  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CHK     include/generated/bounds.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
  CHK     scripts/mod/devicetable-offsets.h
  CHK     include/generated/compile.h
  CHK     kernel/config_data.h
  CC [M]  drivers/gpu/drm/i915/i915_guc_submission.o
drivers/gpu/drm/i915/i915_guc_submission.c: In function ‘i915_guc_submission_enable’:
drivers/gpu/drm/i915/i915_guc_submission.c:1182:1: error: version control conflict marker in file
 <<<<<<< HEAD
 ^~~~~~~
drivers/gpu/drm/i915/i915_guc_submission.c:1185:1: error: version control conflict marker in file
 =======
 ^~~~~~~
At top level:
drivers/gpu/drm/i915/i915_guc_submission.c:1122:13: error: ‘i915_guc_submission_park’ defined but not used [-Werror=unused-function]
 static void i915_guc_submission_park(struct intel_engine_cs *engine)
             ^~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
scripts/Makefile.build:313: recipe for target 'drivers/gpu/drm/i915/i915_guc_submission.o' failed
make[4]: *** [drivers/gpu/drm/i915/i915_guc_submission.o] Error 1
scripts/Makefile.build:572: recipe for target 'drivers/gpu/drm/i915' failed
make[3]: *** [drivers/gpu/drm/i915] Error 2
scripts/Makefile.build:572: recipe for target 'drivers/gpu/drm' failed
make[2]: *** [drivers/gpu/drm] Error 2
scripts/Makefile.build:572: recipe for target 'drivers/gpu' failed
make[1]: *** [drivers/gpu] Error 2
Makefile:1023: recipe for target 'drivers' failed
make: *** [drivers] Error 2

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_6111/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2017-10-26 21:21 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-19 18:36 [PATCH 00/14] Preemption with GuC, third attempt Michał Winiarski
2017-10-19 18:36 ` [PATCH 01/14] drm/i915/guc: Do not use 0 for GuC doorbell cookie Michał Winiarski
2017-10-21  6:28   ` Sagar Arun Kamble
2017-10-19 18:36 ` [PATCH 02/14] drm/i915/guc: Extract GuC stage desc pool creation into a helper Michał Winiarski
2017-10-19 18:36 ` [PATCH v2 03/14] drm/i915/guc: Allocate separate shared data object for GuC communication Michał Winiarski
2017-10-19 18:36 ` [PATCH 04/14] drm/i915/guc: Initialize GuC before restarting engines Michał Winiarski
2017-10-25 18:44   ` Chris Wilson
2017-10-19 18:36 ` [PATCH 05/14] drm/i915/guc: Add preemption action to GuC firmware interface Michał Winiarski
2017-10-19 18:36 ` [PATCH v2 06/14] drm/i915/guc: Add a second client, to be used for preemption Michał Winiarski
2017-10-19 19:36   ` Michal Wajdeczko
2017-10-19 18:36 ` [PATCH 07/14] drm/i915/guc: Split guc_wq_item_append Michał Winiarski
2017-10-19 18:36 ` [PATCH v2 08/14] drm/i915: Extract "emit write" part of emit breadcrumb functions Michał Winiarski
2017-10-19 18:36 ` [PATCH 09/14] drm/i915: Add information needed to track engine preempt state Michał Winiarski
2017-10-19 18:36 ` [PATCH 10/14] drm/i915/guc: Keep request->priority for its lifetime Michał Winiarski
2017-10-19 18:36 ` [PATCH v2 11/14] drm/i915: Rename helpers used for unwinding, use macro for can_preempt Michał Winiarski
2017-10-19 19:18   ` Chris Wilson
2017-10-19 19:20   ` Chris Wilson
2017-10-19 18:36 ` [PATCH v3 12/14] drm/i915/guc: Preemption! With GuC Michał Winiarski
2017-10-19 19:14   ` Chris Wilson
2017-10-19 19:16   ` Chris Wilson
2017-10-20  9:00   ` Chris Wilson
2017-10-20 17:00   ` Chris Wilson
2017-10-23 23:14   ` Daniele Ceraolo Spurio
2017-10-25 18:15   ` Chris Wilson
2017-10-19 18:36 ` [PATCH 13/14] drm/i915/guc: Workaround the missing user interrupt after preemption Michał Winiarski
2017-10-19 19:44   ` Chris Wilson
2017-10-20 17:22     ` Chris Wilson
2017-10-20 17:42       ` Daniele Ceraolo Spurio
2017-10-20 16:08   ` Chris Wilson
2017-10-19 18:36 ` [PATCH 14/14] HAX Enable GuC Submission for CI Michał Winiarski
2017-10-19 19:11 ` ✗ Fi.CI.BAT: failure for Preemption with GuC, third attempt Patchwork
2017-10-26 21:21 ` Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.