@@ -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)
@@ -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.
*
@@ -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);
@@ -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;
@@ -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);
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(+)