[v12,09/17] drm/i915/guc/slpc: Reset SLPC on engine reset with flag TDR_OCCURRED
diff mbox

Message ID 1522398722-12161-10-git-send-email-sagar.a.kamble@intel.com
State New
Headers show

Commit Message

sagar.a.kamble@intel.com March 30, 2018, 8:31 a.m. UTC
On engine reset, SLPC needs to be notified for it to clear metrics/stats.
This is done by sending GUC_SLPC_EVENT_RESET with a flag
GUC_SLPC_RESET_FLAG_TDR_OCCURRED.

v2: Full GPU reset in i915 triggers reload of GuC and SLPC reset happens
    along that path. Hence only handling engine reset.

Signed-off-by: Sagar Arun Kamble <sagar.a.kamble@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Radoslaw Szwichtenberg <radoslaw.szwichtenberg@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com>
Cc: Jeff McGee <jeff.mcgee@intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c       |  3 +++
 drivers/gpu/drm/i915/intel_guc_slpc.c | 36 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_guc_slpc.h |  1 +
 drivers/gpu/drm/i915/intel_uc.c       |  5 +++++
 drivers/gpu/drm/i915/intel_uc.h       |  1 +
 5 files changed, 46 insertions(+)

Patch
diff mbox

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index cc7dd85..726391c 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -3020,6 +3020,9 @@  void i915_handle_error(struct drm_i915_private *dev_priv,
 			wake_up_bit(&dev_priv->gpu_error.flags,
 				    I915_RESET_ENGINE + engine->id);
 		}
+
+		if (!engine_mask)
+			intel_uc_handle_engine_reset(dev_priv);
 	}
 
 	if (!engine_mask)
diff --git a/drivers/gpu/drm/i915/intel_guc_slpc.c b/drivers/gpu/drm/i915/intel_guc_slpc.c
index 7f75d218..bdafbaa 100644
--- a/drivers/gpu/drm/i915/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/intel_guc_slpc.c
@@ -390,6 +390,20 @@  static bool slpc_stopped(struct intel_guc_slpc *slpc)
 	return (data.global_state == SLPC_GLOBAL_STATE_NOT_RUNNING);
 }
 
+static void host2guc_slpc_tdr_reset(struct intel_guc_slpc *slpc)
+{
+	struct intel_guc *guc = slpc_to_guc(slpc);
+	u32 shared_data_gtt_offset = intel_guc_ggtt_offset(guc, slpc->vma);
+	struct slpc_event_input data = {0};
+
+	data.header.value = SLPC_EVENT(SLPC_EVENT_RESET, 3);
+	data.args[0] = shared_data_gtt_offset;
+	data.args[1] = 0;
+	data.args[2] = SLPC_RESET_FLAG_TDR_OCCURRED;
+
+	slpc_send(slpc, &data, 5);
+}
+
 /**
  * intel_guc_slpc_init() - Initialize the SLPC shared data structure.
  * @slpc: pointer to intel_guc_slpc.
@@ -471,6 +485,28 @@  int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
 }
 
 /**
+ * intel_guc_slpc_handle_engine_reset() - Notify SLPC about engine reset.
+ * @slpc: pointer to intel_guc_slpc.
+ *
+ * On engine reset, SLPC needs to be notified for it to clear metrics/stats.
+ * This function notifies by invoking SLPC_EVENT_RESET with a flag
+ * SLPC_RESET_FLAG_TDR_OCCURRED.
+ */
+void intel_guc_slpc_handle_engine_reset(struct intel_guc_slpc *slpc)
+{
+	mutex_lock(&slpc->lock);
+
+	host2guc_slpc_tdr_reset(slpc);
+
+	/* Check whether SLPC is running */
+	if (wait_for(slpc_running(slpc), 5))
+		DRM_ERROR("SLPC not enabled! State = %s\n",
+			  slpc_get_state(slpc));
+
+	mutex_unlock(&slpc->lock);
+}
+
+/**
  * intel_guc_slpc_disable() - Stop SLPC tasks.
  * @slpc: pointer to intel_guc_slpc.
  *
diff --git a/drivers/gpu/drm/i915/intel_guc_slpc.h b/drivers/gpu/drm/i915/intel_guc_slpc.h
index 87dac07..75f0b5d 100644
--- a/drivers/gpu/drm/i915/intel_guc_slpc.h
+++ b/drivers/gpu/drm/i915/intel_guc_slpc.h
@@ -16,6 +16,7 @@  struct intel_guc_slpc {
 
 int intel_guc_slpc_init(struct intel_guc_slpc *slpc);
 int intel_guc_slpc_enable(struct intel_guc_slpc *slpc);
+void intel_guc_slpc_handle_engine_reset(struct intel_guc_slpc *slpc);
 void intel_guc_slpc_disable(struct intel_guc_slpc *slpc);
 void intel_guc_slpc_fini(struct intel_guc_slpc *slpc);
 
diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c
index ece6687..c050444 100644
--- a/drivers/gpu/drm/i915/intel_uc.c
+++ b/drivers/gpu/drm/i915/intel_uc.c
@@ -475,6 +475,11 @@  int intel_uc_init_hw(struct drm_i915_private *dev_priv)
 	return ret;
 }
 
+void intel_uc_handle_engine_reset(struct drm_i915_private *dev_priv)
+{
+	intel_guc_slpc_handle_engine_reset(&dev_priv->guc.slpc);
+}
+
 void intel_uc_fini_hw(struct drm_i915_private *dev_priv)
 {
 	struct intel_guc *guc = &dev_priv->guc;
diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h
index 76139d3..1d67ad3 100644
--- a/drivers/gpu/drm/i915/intel_uc.h
+++ b/drivers/gpu/drm/i915/intel_uc.h
@@ -35,6 +35,7 @@  int intel_uc_init_misc(struct drm_i915_private *dev_priv);
 void intel_uc_fini_misc(struct drm_i915_private *dev_priv);
 void intel_uc_sanitize(struct drm_i915_private *dev_priv);
 int intel_uc_init_hw(struct drm_i915_private *dev_priv);
+void intel_uc_handle_engine_reset(struct drm_i915_private *dev_priv);
 void intel_uc_fini_hw(struct drm_i915_private *dev_priv);
 int intel_uc_init(struct drm_i915_private *dev_priv);
 void intel_uc_fini(struct drm_i915_private *dev_priv);