[PATCH 13/21] drm/i915/guc: Update uC suspend/resume function separating Host/GuC tasks

Sagar Arun Kamble sagar.a.kamble at intel.com
Thu Oct 12 04:30:06 UTC 2017


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

Host needs to disable submission to GuC and any 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, communication with GuC
(intel_guc_send/notify). GGTT invalidate update will have to be done in
conjunction with GTT related suspend/resume tasks.

Currently during runtime suspend/resume, GuC submission disable/enable
leads to hang in RPM as RPM reference needs to be acquired while
allocating/freeing client vma that is part of submission now.
Hence uc_runtime_suspend/resume differs from uc_suspend/resume w.r.t
GuC submission enabling/disabling.

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.

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 |  11 ---
 drivers/gpu/drm/i915/intel_uc.c  | 143 ++++++++++++++++++++++++++++++++++++---
 2 files changed, 135 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c
index 48b71f5..462a354 100644
--- a/drivers/gpu/drm/i915/intel_guc.c
+++ b/drivers/gpu/drm/i915/intel_guc.c
@@ -178,11 +178,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;
-
-	gen9_disable_guc_interrupts(i915);
-
 	ctx = i915->kernel_context;
 
 	data[0] = INTEL_GUC_ACTION_ENTER_S_STATE;
@@ -205,12 +200,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;
-
-	if (i915_modparams.guc_log_level >= 0)
-		gen9_enable_guc_interrupts(i915);
-
 	ctx = i915->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 54fd324..092bdea 100644
--- a/drivers/gpu/drm/i915/intel_uc.c
+++ b/drivers/gpu/drm/i915/intel_uc.c
@@ -284,36 +284,163 @@ void intel_uc_fini_hw(struct drm_i915_private *dev_priv)
 		i915_ggtt_disable_guc(dev_priv);
 }
 
+/**
+ * intel_uc_suspend() - Suspend uC operation.
+ * @dev_priv: i915 device private
+ *
+ * This function disables GuC submission, invokes GuC OS suspension,
+ * disables GuC interrupts and disable communication with GuC.
+ *
+ * Return:	non-zero code on error
+ */
 int intel_uc_suspend(struct drm_i915_private *dev_priv)
 {
-	int ret;
+	struct intel_guc *guc = &dev_priv->guc;
+	int ret = 0;
+
+	if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS)
+		goto out;
+
+	i915_guc_submission_disable(dev_priv);
 
-	ret = intel_guc_suspend(&dev_priv->guc);
+	ret = intel_guc_suspend(guc);
 	if (ret)
-		DRM_ERROR("Failed to suspend GuC\n");
+		goto out_suspend;
+
+	gen9_disable_guc_interrupts(dev_priv);
+	guc_disable_communication(guc);
+
+	goto out;
+
+out_suspend:
+	i915_guc_submission_enable(dev_priv);
+out:
+	if (ret)
+		DRM_ERROR("uC Suspend failed (%d)\n", ret);
 
 	return ret;
 }
 
+/**
+ * intel_uc_resume() - Resume uC operation.
+ * @dev_priv: i915 device private
+ *
+ * This function enables communication with GuC, enables GuC interrupts,
+ * invokes GuC OS resumption and enables GuC submission.
+ */
 void intel_uc_resume(struct drm_i915_private *dev_priv)
 {
-	intel_guc_resume(&dev_priv->guc);
+	struct intel_guc *guc = &dev_priv->guc;
+	int ret;
+
+	if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS)
+		return;
+
+	ret = guc_enable_communication(guc);
+	if (ret) {
+		DRM_DEBUG_DRIVER("GuC communication enable failed (%d)\n", ret);
+		return;
+	}
+
+	if (i915_modparams.guc_log_level >= 0)
+		gen9_enable_guc_interrupts(dev_priv);
+
+	ret = intel_guc_resume(guc);
+	if (ret)
+		DRM_ERROR("GuC resume failed (%d)."
+			  "GuC functions may not work\n", ret);
+
+	i915_guc_submission_enable(dev_priv);
+
+	DRM_DEBUG_DRIVER("GuC submission %s\n",
+			 i915_guc_submission_enabled(guc) ?
+			 "enabled" : "disabled");
 }
 
+/**
+ * intel_uc_runtime_suspend() - Suspend uC operation.
+ * @dev_priv: i915 device private
+ *
+ * This function is largely similar to intel_uc_suspend except for
+ * GuC submission disabling. This function invokes GuC OS suspension,
+ * disables GuC interrupts and disable communication with GuC.
+ *
+ * Return:	non-zero code on error
+ */
 int intel_uc_runtime_suspend(struct drm_i915_private *dev_priv)
 {
-	int ret;
+	struct intel_guc *guc = &dev_priv->guc;
+	int ret = 0;
+
+	if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS)
+		goto out;
+
+	/*
+	 * TODO: Note that currently GuC submission is not being disabled
+	 * prior to GuC suspend. It is recommended to release all
+	 * doorbells at this point. Disabling GuC submission here will
+	 * lead to GuC execbufclient vma allocation/free along wit
+	 * doorbell release that in turn involves RPM get/put hence this
+	 * path will hang. Once we update guc_submission_disable to only
+	 * destroy doorbell and not free/unmap client vmas, GuC will be
+	 * properly suspended. Post that we can possibly unify
+	 * uc_suspend/resume and uc_runtime_suspend/resume.
+	 */
+	ret = intel_guc_suspend(guc);
+	if (ret)
+		goto out;
 
-	ret = intel_guc_suspend(&dev_priv->guc);
+	gen9_disable_guc_interrupts(dev_priv);
+	guc_disable_communication(guc);
+
+	goto out;
+
+out:
 	if (ret)
-		DRM_ERROR("Failed to suspend GuC\n");
+		DRM_ERROR("uC Suspend failed (%d)\n", ret);
 
 	return ret;
 }
 
+/**
+ * intel_uc_runtime_resume() - Resume uC operation.
+ * @dev_priv: i915 device private
+ *
+ * This function is largely similar to intel_uc_resume except for
+ * GuC submission enabling. This function enables communication with
+ * GuC, enables GuC interrupts, invokes GuC OS resumption.
+ */
 void intel_uc_runtime_resume(struct drm_i915_private *dev_priv)
 {
-	intel_guc_resume(&dev_priv->guc);
+	struct intel_guc *guc = &dev_priv->guc;
+	int ret;
+
+	if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS)
+		return;
+
+	ret = guc_enable_communication(guc);
+	if (ret) {
+		DRM_DEBUG_DRIVER("GuC communication enable failed (%d)\n", ret);
+		return;
+	}
+
+	if (i915_modparams.guc_log_level >= 0)
+		gen9_enable_guc_interrupts(dev_priv);
+
+	ret = intel_guc_resume(guc);
+	if (ret)
+		DRM_ERROR("GuC resume failed (%d)."
+			  "GuC functions may not work\n", ret);
+
+	/*
+	 * TODO: Note that currently GuC submission is not being disabled
+	 * prior to GuC suspend. Hence we skip enabling here. It is
+	 * recommended to release all doorbells during suspend and acquire
+	 * here. Once we update guc_submission_disable to only destroy
+	 * doorbell and not free/unmap client vmas, we will acquire
+	 * doorbell here without alloc/free of client vmas. Post that we
+	 * can possibly unify uc_suspend/resume and uc_runtime_suspend/resume.
+	 */
 }
 
 /**
-- 
1.9.1



More information about the Intel-gfx-trybot mailing list