diff mbox series

[14/21] drm/i915/guc: New reset-engine command

Message ID 20180829191814.10872-5-michal.wajdeczko@intel.com (mailing list archive)
State New, archived
Headers show
Series New GuC ABI | expand

Commit Message

Michal Wajdeczko Aug. 29, 2018, 7:18 p.m. UTC
Format of the ENGINE_RESET H2G message has been updated. Additionally,
the firmware will send a G2H ENGINE_RESET_COMPLETE message (with the
engine's guc_class in data[2]) to confirm that the reset has been
completed (but this will be handled in a other patch).

Requires GuC fw v25.161+.

Credits-to: Michel Thierry <michel.thierry@intel.com>
Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Michel Thierry <michel.thierry@intel.com>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Cc: Michal Winiarski <michal.winiarski@intel.com>
Cc: Tomasz Lis <tomasz.lis@intel.com>
---
 drivers/gpu/drm/i915/intel_guc.c | 73 ++++++++++++++++++++++++++++++++++------
 drivers/gpu/drm/i915/intel_guc.h |  6 ++++
 2 files changed, 69 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c
index a9c2f7b..64f1dca 100644
--- a/drivers/gpu/drm/i915/intel_guc.c
+++ b/drivers/gpu/drm/i915/intel_guc.c
@@ -576,27 +576,80 @@  int intel_guc_suspend(struct intel_guc *guc)
 	return intel_guc_send(guc, data, ARRAY_SIZE(data));
 }
 
+static inline void
+guc_set_class_under_reset(struct intel_guc *guc, unsigned int guc_class)
+{
+	GEM_BUG_ON(guc_class >= GUC_MAX_ENGINE_CLASSES);
+	bitmap32_set_bit(&guc->engine_class_under_reset, guc_class);
+}
+
+static inline void
+guc_clear_class_under_reset(struct intel_guc *guc, unsigned int guc_class)
+{
+	GEM_BUG_ON(guc_class >= GUC_MAX_ENGINE_CLASSES);
+	bitmap32_clear_bit(&guc->engine_class_under_reset, guc_class);
+}
+
+static inline bool
+guc_is_class_under_reset(struct intel_guc *guc, unsigned int guc_class)
+{
+	return bitmap32_test_bit(&guc->engine_class_under_reset, guc_class);
+}
+
+static int __guc_action_reset_engine(struct intel_guc *guc,
+				     u32 guc_class,
+				     u32 stage_id)
+{
+	u32 action[] = {
+		INTEL_GUC_ACTION_REQUEST_ENGINE_RESET,
+		guc_class,
+		stage_id,
+	};
+
+	return intel_guc_send(guc, action, ARRAY_SIZE(action));
+}
+
+#define GUC_ENGINE_RESET_COMPLETE_WAIT_MS 100
+
 /**
  * intel_guc_reset_engine() - ask GuC to reset an engine
  * @guc:	intel_guc structure
  * @engine:	engine to be reset
+ *
+ * Ask GuC to reset an engine. The firmware will send a separate
+ * ENGINE_RESET_COMPLETE message (with the engine's guc_class)
+ * to confirm that the reset has been completed.
  */
 int intel_guc_reset_engine(struct intel_guc *guc,
 			   struct intel_engine_cs *engine)
 {
-	u32 data[7];
+	struct intel_guc_client *client = guc->execbuf_client;
+	u32 guc_class = engine->guc_class;
+	int ret;
 
-	GEM_BUG_ON(!guc->execbuf_client);
+	GEM_BUG_ON(guc_is_class_under_reset(guc, guc_class));
+	guc_set_class_under_reset(guc, guc_class);
 
-	data[0] = INTEL_GUC_ACTION_REQUEST_ENGINE_RESET;
-	data[1] = engine->guc_id;
-	data[2] = 0;
-	data[3] = 0;
-	data[4] = 0;
-	data[5] = guc->execbuf_client->stage_id;
-	data[6] = intel_guc_ggtt_offset(guc, guc->shared_data);
+	ret = __guc_action_reset_engine(guc, guc_class, client->stage_id);
+	if (ret)
+		goto out;
 
-	return intel_guc_send(guc, data, ARRAY_SIZE(data));
+	if ((wait_for(!guc_is_class_under_reset(guc, guc_class),
+		      GUC_ENGINE_RESET_COMPLETE_WAIT_MS))) {
+		DRM_ERROR("reset_complete timed out, engine class %d\n",
+			  engine->guc_class);
+		ret = -ETIMEDOUT;
+	}
+
+out:
+	/*
+	 * Clear flag on any failure, we fall back to full reset in
+	 * case of timeout/error.
+	 */
+	if (ret)
+		guc_clear_class_under_reset(guc, guc_class);
+
+	return ret;
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index ad42faf..8688edc 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -74,6 +74,12 @@  struct intel_guc {
 	/* Cyclic counter mod pagesize	*/
 	u32 db_cacheline;
 
+	/*
+	 * Track outstanding request-engine-reset h2g commands,
+	 * accessed by set/clear/is_engine_class_under_reset
+	 */
+	u32 engine_class_under_reset;
+
 	/* GuC's FW specific registers used in MMIO send */
 	struct {
 		u32 base;