[PATCH v14 17/25] drm/i915/guc: Update uC suspend/resume function separating Host/GuC tasks

Sagar Arun Kamble sagar.a.kamble at intel.com
Tue Oct 17 10:37:06 UTC 2017


Suspending GuC involves tasks controlled by GuC OS and some controlled by
Host OS.

Host needs to destroy all doorbells and disabling other GuC functions.
Then, GuC's task is initiated by Host sending action to GuC to enter sleep
state. On this action, GuC preempts engines to idle context and then saves
internal state to a buffer. It also disables internal interrupts/timers to
avoid any wake-ups.
After this, Host should disable GuC interrupts. Interrupts need to be
restored during resume.

uc_runtime_resume differs from uc_resume w.r.t GuC load handling.

v2: Rebase w.r.t removal of GuC code restructuring.

v3: Removed GuC specific helpers as tasks other than send H2G for
sleep/resume are to be done from uc generic functions. (Michal Wajdeczko)

v4: Simplified/Unified the error messaging in uc_runtime_suspend/resume.
(Michal Wajdeczko). Rebase w.r.t i915_modparams change.
Added documentation to intel_uc_runtime_suspend/resume.

v5: Removed enable_guc_loading based check from intel_uc_runtime_suspend
and intel_uc_runtime_resume and pulled FW load_status based checks from
intel_guc_suspend/resume into these functions. (Michal Wajdeczko)

v6: Adjusted intel_uc_runtime_resume with prototype change to not return
value.

v7: Rebase.

v8: Updated commit description and added submission enable/disable in
GuC suspend/resume paths. Removed GGTT invalidate update functions.

v9: Updated uc_runtime_suspend/resume.

v10: Rebase. Updated kerneldoc. Flag error if GuC not loaded. Updated
error messages in suspend/resume. Error handling done for all steps.
GuC interrupts enable/disable updated with client support.
(Michal Wajdeczko)

v11: Removed GuC submission disabling. Rebase. (Sagar)

Signed-off-by: Sagar Arun Kamble <sagar.a.kamble at intel.com>
Cc: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Michal Wajdeczko <michal.wajdeczko at intel.com>
Cc: MichaƂ Winiarski <michal.winiarski at intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
Reviewed-by: Michal Wajdeczko <michal.wajdeczko at intel.com> #6
---
 drivers/gpu/drm/i915/intel_guc.c | 10 -----
 drivers/gpu/drm/i915/intel_uc.c  | 83 +++++++++++++++++++++++++++++++---------
 2 files changed, 64 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c
index 21c93ff..0e9b2e6 100644
--- a/drivers/gpu/drm/i915/intel_guc.c
+++ b/drivers/gpu/drm/i915/intel_guc.c
@@ -290,11 +290,6 @@ int intel_guc_suspend(struct intel_guc *guc)
 	struct i915_gem_context *ctx;
 	u32 data[3];
 
-	if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS)
-		return 0;
-
-	intel_suspend_guc_interrupts(guc);
-
 	ctx = dev_priv->kernel_context;
 
 	data[0] = INTEL_GUC_ACTION_ENTER_S_STATE;
@@ -332,11 +327,6 @@ int intel_guc_resume(struct intel_guc *guc)
 	struct i915_gem_context *ctx;
 	u32 data[3];
 
-	if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS)
-		return 0;
-
-	intel_restore_guc_interrupts(guc);
-
 	ctx = dev_priv->kernel_context;
 
 	data[0] = INTEL_GUC_ACTION_EXIT_S_STATE;
diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c
index d91f8c23..e8333c5 100644
--- a/drivers/gpu/drm/i915/intel_uc.c
+++ b/drivers/gpu/drm/i915/intel_uc.c
@@ -297,21 +297,35 @@ void intel_uc_fini_hw(struct drm_i915_private *dev_priv)
  * intel_uc_suspend() - Suspend uC operation.
  * @dev_priv: i915 device private
  *
- * This function invokes GuC OS suspension.
+ * This function will destroy doorbells (TODO: not done currently)
+ * invoke GuC OS suspension and suspend GuC interrupts.
  *
  * Return:	non-zero code on error
  */
 int intel_uc_suspend(struct drm_i915_private *dev_priv)
 {
+	struct intel_guc *guc = &dev_priv->guc;
 	int ret;
 
 	if (!i915_modparams.enable_guc_loading)
 		return 0;
 
-	ret = intel_guc_suspend(&dev_priv->guc);
-	if (ret)
-		DRM_ERROR("Failed to suspend GuC\n");
+	if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) {
+		DRM_ERROR("GuC not loaded. Suspend skipped\n");
+		return 0;
+	}
+
+	/* TODO: It is recommended to release all doorbells at this point. */
 
+	ret = intel_guc_suspend(guc);
+	if (ret) {
+		DRM_ERROR("Failed to suspend uC, aborting suspend (%d)\n", ret);
+		goto out;
+	}
+
+	intel_suspend_guc_interrupts(guc);
+
+out:
 	return ret;
 }
 
@@ -319,48 +333,79 @@ int intel_uc_suspend(struct drm_i915_private *dev_priv)
  * intel_uc_resume() - Resume uC operation.
  * @dev_priv: i915 device private
  *
- * This function invokes GuC OS resumption.
+ * This function will restore GuC interrupts, invoke GuC OS resumption
+ * and acquire needed doorbells again (TODO: not done currently)
+ *
  */
 void intel_uc_resume(struct drm_i915_private *dev_priv)
 {
+	struct intel_guc *guc = &dev_priv->guc;
+	int ret;
+
 	if (!i915_modparams.enable_guc_loading)
 		return;
 
-	intel_guc_resume(&dev_priv->guc);
+	if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) {
+		DRM_ERROR("GuC not loaded. Resume skipped\n");
+		return;
+	}
+
+	intel_restore_guc_interrupts(guc);
+
+	ret = intel_guc_resume(guc);
+	if (ret) {
+		DRM_ERROR("GuC resume failed (%d)\n", ret);
+		intel_suspend_guc_interrupts(guc);
+	}
+
+	/* TODO: Need to restore doorbells for all GuC clients. */
 }
 
 /**
  * intel_uc_runtime_suspend() - Suspend uC operation.
  * @dev_priv: i915 device private
  *
- * This function invokes GuC OS suspension.
+ * This function does similar suspend tasks as uc_suspend.
  *
  * Return:	non-zero code on error
  */
 int intel_uc_runtime_suspend(struct drm_i915_private *dev_priv)
 {
-	int ret;
-
-	if (!i915_modparams.enable_guc_loading)
-		return 0;
-
-	ret = intel_guc_suspend(&dev_priv->guc);
-	if (ret)
-		DRM_ERROR("Failed to suspend GuC\n");
-
-	return ret;
+	return intel_uc_suspend(dev_priv);
 }
 
 /**
  * intel_uc_runtime_resume() - Resume uC operation.
  * @dev_priv: i915 device private
  *
- * This function invokes GuC OS resumption.
+ * This function does similar resume tasks as uc_resume except
+ * GuC load handling in case it gets unloaded during suspend.
+ * TODO: Along drm resume path GuC gets loaded through uc_init_hw and
+ * we need to add support to load GuC here.
  */
 void intel_uc_runtime_resume(struct drm_i915_private *dev_priv)
 {
+	struct intel_guc *guc = &dev_priv->guc;
+	int ret;
+
 	if (!i915_modparams.enable_guc_loading)
 		return;
 
-	intel_guc_resume(&dev_priv->guc);
+	/* TODO: Need to handle case when GuC is not loaded. */
+
+	if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) {
+		DRM_ERROR("GuC not loaded. Resume skipped\n");
+		return;
+	}
+
+	intel_restore_guc_interrupts(guc);
+
+	ret = intel_guc_resume(guc);
+	if (ret) {
+		DRM_ERROR("GuC resume failed (%d)\n", ret);
+
+		intel_suspend_guc_interrupts(guc);
+	}
+
+	/* TODO: Need to restore doorbells for all GuC clients. */
 }
-- 
1.9.1



More information about the Intel-gfx-trybot mailing list