Takashi Iwai e71951
From 6acbea89efbdc6aef56bc6f364d4d8b72a5fc145 Mon Sep 17 00:00:00 2001
Takashi Iwai e71951
From: Michel Thierry <michel.thierry@intel.com>
Takashi Iwai e71951
Date: Tue, 31 Oct 2017 15:53:09 -0700
Takashi Iwai e71951
Subject: [PATCH] drm/i915/guc: Add support for reset engine using GuC commands
Takashi Iwai e71951
Git-commit: 6acbea89efbdc6aef56bc6f364d4d8b72a5fc145
Takashi Iwai e71951
Patch-mainline: v4.16-rc1
Takashi Iwai e71951
References: FATE#322643 bsc#1055900
Takashi Iwai e71951
Takashi Iwai e71951
This patch adds per engine reset and recovery (TDR) support when GuC is
Takashi Iwai e71951
used to submit workloads to GPU.
Takashi Iwai e71951
Takashi Iwai e71951
In the case of i915 directly submission to ELSP, driver manages hang
Takashi Iwai e71951
detection, recovery and resubmission. With GuC submission these tasks
Takashi Iwai e71951
are shared between driver and GuC. i915 is still responsible for detecting
Takashi Iwai e71951
a hang, and when it does it only requests GuC to reset that Engine. GuC
Takashi Iwai e71951
internally manages acquiring forcewake and idling the engine before
Takashi Iwai e71951
resetting it.
Takashi Iwai e71951
Takashi Iwai e71951
Once the reset is successful, i915 takes over again and handles the
Takashi Iwai e71951
resubmission. The scheduler in i915 knows which requests are pending so
Takashi Iwai e71951
after resetting a engine, pending workloads/requests are resubmitted
Takashi Iwai e71951
again.
Takashi Iwai e71951
Takashi Iwai e71951
V2: s/i915_guc_request_engine_reset/i915_guc_reset_engine/ to match the
Takashi Iwai e71951
non-guc function names.
Takashi Iwai e71951
Takashi Iwai e71951
V3: Removed debug message about engine restarting from which request,
Takashi Iwai e71951
since the new baseline do it regardless of submission mode. (Chris)
Takashi Iwai e71951
Takashi Iwai e71951
V4: Rebase.
Takashi Iwai e71951
Takashi Iwai e71951
V5: Do not pass unnecessary reporting flags to the fw (Jeff);
Takashi Iwai e71951
tasklet_schedule(&execlists->irq_tasklet) handles the resubmit; rebase.
Takashi Iwai e71951
Takashi Iwai e71951
V6: Rename the existing reset engine function and share a similar
Takashi Iwai e71951
interface between guc and non-guc paths (Chris).
Takashi Iwai e71951
Takashi Iwai e71951
Signed-off-by: Michel Thierry <michel.thierry@intel.com>
Takashi Iwai e71951
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Takashi Iwai e71951
Link: https://patchwork.freedesktop.org/patch/msgid/20171031225309.10888-1-michel.thierry@intel.com
Takashi Iwai e71951
Reviewed-by: Jeff McGee <jeff.mcgee@intel.com>
Takashi Iwai e71951
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Takashi Iwai e71951
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai e71951
Takashi Iwai e71951
---
Takashi Iwai e71951
 drivers/gpu/drm/i915/i915_drv.c       |   14 ++++++++++++--
Takashi Iwai e71951
 drivers/gpu/drm/i915/i915_drv.h       |    2 ++
Takashi Iwai e71951
 drivers/gpu/drm/i915/intel_guc.c      |   24 ++++++++++++++++++++++++
Takashi Iwai e71951
 drivers/gpu/drm/i915/intel_guc_fwif.h |    1 +
Takashi Iwai e71951
 drivers/gpu/drm/i915/intel_uncore.c   |    5 -----
Takashi Iwai e71951
 5 files changed, 39 insertions(+), 7 deletions(-)
Takashi Iwai e71951
Takashi Iwai e71951
--- a/drivers/gpu/drm/i915/i915_drv.c
Takashi Iwai e71951
+++ b/drivers/gpu/drm/i915/i915_drv.c
Takashi Iwai e71951
@@ -1950,6 +1950,12 @@ error:
Takashi Iwai e71951
 	goto finish;
Takashi Iwai e71951
 }
Takashi Iwai e71951
 
Takashi Iwai e71951
+static inline int intel_gt_reset_engine(struct drm_i915_private *dev_priv,
Takashi Iwai e71951
+					struct intel_engine_cs *engine)
Takashi Iwai e71951
+{
Takashi Iwai e71951
+	return intel_gpu_reset(dev_priv, intel_engine_flag(engine));
Takashi Iwai e71951
+}
Takashi Iwai e71951
+
Takashi Iwai e71951
 /**
Takashi Iwai e71951
  * i915_reset_engine - reset GPU engine to recover from a hang
Takashi Iwai e71951
  * @engine: engine to reset
Takashi Iwai e71951
@@ -1984,10 +1990,14 @@ int i915_reset_engine(struct intel_engin
Takashi Iwai e71951
 		goto out;
Takashi Iwai e71951
 	}
Takashi Iwai e71951
 
Takashi Iwai e71951
-	ret = intel_gpu_reset(engine->i915, intel_engine_flag(engine));
Takashi Iwai e71951
+	if (!engine->i915->guc.execbuf_client)
Takashi Iwai e71951
+		ret = intel_gt_reset_engine(engine->i915, engine);
Takashi Iwai e71951
+	else
Takashi Iwai e71951
+		ret = intel_guc_reset_engine(&engine->i915->guc, engine);
Takashi Iwai e71951
 	if (ret) {
Takashi Iwai e71951
 		/* If we fail here, we expect to fallback to a global reset */
Takashi Iwai e71951
-		DRM_DEBUG_DRIVER("Failed to reset %s, ret=%d\n",
Takashi Iwai e71951
+		DRM_DEBUG_DRIVER("%sFailed to reset %s, ret=%d\n",
Takashi Iwai e71951
+				 engine->i915->guc.execbuf_client ? "GuC " : "",
Takashi Iwai e71951
 				 engine->name, ret);
Takashi Iwai e71951
 		goto out;
Takashi Iwai e71951
 	}
Takashi Iwai e71951
--- a/drivers/gpu/drm/i915/i915_drv.h
Takashi Iwai e71951
+++ b/drivers/gpu/drm/i915/i915_drv.h
Takashi Iwai e71951
@@ -3282,6 +3282,8 @@ extern int i915_reset_engine(struct inte
Takashi Iwai e71951
 
Takashi Iwai e71951
 extern bool intel_has_reset_engine(struct drm_i915_private *dev_priv);
Takashi Iwai e71951
 extern int intel_reset_guc(struct drm_i915_private *dev_priv);
Takashi Iwai e71951
+extern int intel_guc_reset_engine(struct intel_guc *guc,
Takashi Iwai e71951
+				  struct intel_engine_cs *engine);
Takashi Iwai e71951
 extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine);
Takashi Iwai e71951
 extern void intel_hangcheck_init(struct drm_i915_private *dev_priv);
Takashi Iwai e71951
 extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
Takashi Iwai e71951
--- a/drivers/gpu/drm/i915/intel_guc.c
Takashi Iwai e71951
+++ b/drivers/gpu/drm/i915/intel_guc.c
Takashi Iwai e71951
@@ -24,6 +24,7 @@
Takashi Iwai e71951
 
Takashi Iwai e71951
 #include "intel_guc.h"
Takashi Iwai e71951
 #include "i915_drv.h"
Takashi Iwai e71951
+#include "i915_guc_submission.h"
Takashi Iwai e71951
 
Takashi Iwai e71951
 static void gen8_guc_raise_irq(struct intel_guc *guc)
Takashi Iwai e71951
 {
Takashi Iwai e71951
@@ -282,6 +283,29 @@ int intel_guc_suspend(struct drm_i915_pr
Takashi Iwai e71951
 
Takashi Iwai e71951
 	return intel_guc_send(guc, data, ARRAY_SIZE(data));
Takashi Iwai e71951
 }
Takashi Iwai e71951
+
Takashi Iwai e71951
+/**
Takashi Iwai e71951
+ * intel_guc_reset_engine() - ask GuC to reset an engine
Takashi Iwai e71951
+ * @guc:	intel_guc structure
Takashi Iwai e71951
+ * @engine:	engine to be reset
Takashi Iwai e71951
+ */
Takashi Iwai e71951
+int intel_guc_reset_engine(struct intel_guc *guc,
Takashi Iwai e71951
+			   struct intel_engine_cs *engine)
Takashi Iwai e71951
+{
Takashi Iwai e71951
+	u32 data[7];
Takashi Iwai e71951
+
Takashi Iwai e71951
+	GEM_BUG_ON(!guc->execbuf_client);
Takashi Iwai e71951
+
Takashi Iwai e71951
+	data[0] = INTEL_GUC_ACTION_REQUEST_ENGINE_RESET;
Takashi Iwai e71951
+	data[1] = engine->guc_id;
Takashi Iwai e71951
+	data[2] = 0;
Takashi Iwai e71951
+	data[3] = 0;
Takashi Iwai e71951
+	data[4] = 0;
Takashi Iwai e71951
+	data[5] = guc->execbuf_client->stage_id;
Takashi Iwai e71951
+	data[6] = guc_ggtt_offset(guc->shared_data);
Takashi Iwai e71951
+
Takashi Iwai e71951
+	return intel_guc_send(guc, data, ARRAY_SIZE(data));
Takashi Iwai e71951
+}
Takashi Iwai e71951
 
Takashi Iwai e71951
 /**
Takashi Iwai e71951
  * intel_guc_resume() - notify GuC resuming from suspend state
Takashi Iwai e71951
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
Takashi Iwai e71951
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
Takashi Iwai e71951
@@ -574,6 +574,7 @@ struct guc_shared_ctx_data {
Takashi Iwai e71951
 enum intel_guc_action {
Takashi Iwai e71951
 	INTEL_GUC_ACTION_DEFAULT = 0x0,
Takashi Iwai e71951
 	INTEL_GUC_ACTION_REQUEST_PREEMPTION = 0x2,
Takashi Iwai e71951
+	INTEL_GUC_ACTION_REQUEST_ENGINE_RESET = 0x3,
Takashi Iwai e71951
 	INTEL_GUC_ACTION_SAMPLE_FORCEWAKE = 0x6,
Takashi Iwai e71951
 	INTEL_GUC_ACTION_ALLOCATE_DOORBELL = 0x10,
Takashi Iwai e71951
 	INTEL_GUC_ACTION_DEALLOCATE_DOORBELL = 0x20,
Takashi Iwai e71951
--- a/drivers/gpu/drm/i915/intel_uncore.c
Takashi Iwai e71951
+++ b/drivers/gpu/drm/i915/intel_uncore.c
Takashi Iwai e71951
@@ -1805,14 +1805,9 @@ bool intel_has_gpu_reset(struct drm_i915
Takashi Iwai e71951
 	return intel_get_gpu_reset(dev_priv) != NULL;
Takashi Iwai e71951
 }
Takashi Iwai e71951
 
Takashi Iwai e71951
-/*
Takashi Iwai e71951
- * When GuC submission is enabled, GuC manages ELSP and can initiate the
Takashi Iwai e71951
- * engine reset too. For now, fall back to full GPU reset if it is enabled.
Takashi Iwai e71951
- */
Takashi Iwai e71951
 bool intel_has_reset_engine(struct drm_i915_private *dev_priv)
Takashi Iwai e71951
 {
Takashi Iwai e71951
 	return (dev_priv->info.has_reset_engine &&
Takashi Iwai e71951
-		!dev_priv->guc.execbuf_client &&
Takashi Iwai e71951
 		i915_modparams.reset >= 2);
Takashi Iwai e71951
 }
Takashi Iwai e71951