[PATCH 19/22] drm/i915/guc: Prepare uc_resume_prepare to initialize GuC/HuC state during resume

Sagar Arun Kamble sagar.a.kamble at intel.com
Tue Oct 17 08:03:42 UTC 2017


i915 maintains GuC/HuC load status and interrupt clients count when GuC
is loaded. On resume from sleep we need to update this state based on
availability of GuC.

GuC/HuC resume operation depends on whether they are loaded. This depends
on whether firmwares are available in the WOPCM region and MIA is not
reset. MIA reset status is now available through guc_mia_in_reset() and
Firmware WOPCM status is known through register GUC_WOPCM_SIZE BIT(0).
We define function guc_wopcm_locked to check firmware WOPCM status.

If MIA is not reset and WOPCM is locked then GuC is available. If either
MIA is reset or WOPCM is not locked then GuC is not loaded.

Signed-off-by: Sagar Arun Kamble <sagar.a.kamble at intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko at intel.com>
Cc: MichaƂ Winiarski <michal.winiarski at intel.com>
Cc: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem.c     |  4 ++++
 drivers/gpu/drm/i915/i915_guc_reg.h |  1 +
 drivers/gpu/drm/i915/intel_uc.c     | 42 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_uc.h     |  1 +
 4 files changed, 48 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index d384929..d5c617d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2102,6 +2102,8 @@ int i915_gem_runtime_suspend(struct drm_i915_private *dev_priv)
 
 void i915_gem_runtime_resume(struct drm_i915_private *dev_priv)
 {
+	intel_uc_resume_prepare(dev_priv);
+
 	i915_gem_init_swizzling(dev_priv);
 	i915_gem_restore_fences(dev_priv);
 
@@ -4734,6 +4736,8 @@ void i915_gem_resume(struct drm_i915_private *dev_priv)
 	WARN_ON(dev_priv->gt.awake);
 
 	mutex_lock(&dev->struct_mutex);
+	intel_uc_resume_prepare(dev_priv);
+
 	i915_gem_restore_gtt_mappings(dev_priv);
 	i915_gem_restore_fences(dev_priv);
 
diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h
index 35cf991..532296b 100644
--- a/drivers/gpu/drm/i915/i915_guc_reg.h
+++ b/drivers/gpu/drm/i915/i915_guc_reg.h
@@ -75,6 +75,7 @@
 
 /* Defines WOPCM space available to GuC firmware */
 #define GUC_WOPCM_SIZE			_MMIO(0xc050)
+#define   GUC_WOPCM_LOCKED		  BIT(0)
 /* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */
 #define   GUC_WOPCM_TOP			  (0x80 << 12)	/* 512KB */
 #define   BXT_GUC_WOPCM_RC6_RESERVED	  (0x10 << 12)	/* 64KB  */
diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c
index b80ccf1..500b38b 100644
--- a/drivers/gpu/drm/i915/intel_uc.c
+++ b/drivers/gpu/drm/i915/intel_uc.c
@@ -33,6 +33,24 @@ static inline bool guc_mia_in_reset(struct intel_guc *guc)
 	return !!(I915_READ(GUC_STATUS) & GS_MIA_IN_RESET);
 }
 
+static inline bool guc_wopcm_locked(struct intel_guc *guc)
+{
+	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+
+	return !!(I915_READ(GUC_WOPCM_SIZE) & GUC_WOPCM_LOCKED);
+}
+
+static inline bool guc_is_loaded(struct intel_guc *guc)
+{
+	/*
+	 * If GPU/GuC was not reset post last load and WOPCM is
+	 * still locked, it means GuC is still loaded and is as
+	 * good as RC6 state for GuC. This check can be used while
+	 * resuming from runtime or drm suspend to avoid loading again.
+	 */
+	return !guc_mia_in_reset(guc) && guc_wopcm_locked(guc);
+}
+
 /* Reset GuC providing us with fresh state for both GuC and HuC.
  */
 static int __intel_uc_reset_hw(struct drm_i915_private *dev_priv)
@@ -322,3 +340,27 @@ void intel_uc_reset_state(struct drm_i915_private *dev_priv)
 		huc->fw.load_status = INTEL_UC_FIRMWARE_NONE;
 	}
 }
+
+/**
+ * intel_uc_resume_prepare() - Sanitize uC state before resume from sleep.
+ * @dev_priv: i915 device private
+ *
+ * This function marks load_status as FIRMWARE_NONE and sanitizes state of
+ * other GuC tasks. This is intended to be called after suspend.
+ */
+void intel_uc_resume_prepare(struct drm_i915_private *dev_priv)
+{
+	struct intel_guc *guc = &dev_priv->guc;
+	struct intel_huc *huc = &dev_priv->huc;
+
+	if (i915_modparams.enable_guc_loading) {
+		if (!guc_is_loaded(guc)) {
+			spin_lock_irq(&dev_priv->irq_lock);
+			guc->interrupt_clients = 0;
+			spin_unlock_irq(&dev_priv->irq_lock);
+
+			guc->fw.load_status = INTEL_UC_FIRMWARE_NONE;
+			huc->fw.load_status = INTEL_UC_FIRMWARE_NONE;
+		}
+	}
+}
diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h
index e47b989..c2262a7 100644
--- a/drivers/gpu/drm/i915/intel_uc.h
+++ b/drivers/gpu/drm/i915/intel_uc.h
@@ -35,5 +35,6 @@
 int intel_uc_init_hw(struct drm_i915_private *dev_priv);
 void intel_uc_fini_hw(struct drm_i915_private *dev_priv);
 void intel_uc_reset_state(struct drm_i915_private *dev_priv);
+void intel_uc_resume_prepare(struct drm_i915_private *dev_priv);
 
 #endif
-- 
1.9.1



More information about the Intel-gfx-trybot mailing list