summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_guc_loader.c
diff options
context:
space:
mode:
authorDave Gordon <david.s.gordon@intel.com>2016-04-04 18:50:57 +0100
committerTvrtko Ursulin <tvrtko.ursulin@intel.com>2016-04-05 13:29:24 +0100
commitd761701c55a99598477f3cb25c03d939a7711e74 (patch)
treecc4fdbe703c4099f1e5c10fb1af262f09ab6a0b3 /drivers/gpu/drm/i915/intel_guc_loader.c
parent6b332fa20f671265638d1d62496f9607c5f6e92f (diff)
downloadlinux-next-d761701c55a99598477f3cb25c03d939a7711e74.tar.gz
drm/i915/guc: always reset GuC before loading firmware
After a suspend-resume cycle, the resumed kernel has no idea what the booted kernel may have done to the GuC before replacing itself with the resumed image. In particular, it may have already loaded the GuC with firmware, which will then cause this kernel's attempt to (re)load the firmware to fail (GuC program memory is write-once!). The symptoms (GuC firmware reload fails after hibernation) are further described in the Bugzilla reference below. So let's *always* reset the GuC just before (re)loading the firmware; the hardware should then be in a well-known state, and we may even avoid some of the issues arising from unpredictable timing. Also added some more fields & values to the definition of the GUC_STATUS register, which is the key diagnostic indicator if the GuC load fails. Signed-off-by: Dave Gordon <david.s.gordon@intel.com> Reviewed-by: Arun Siluvery <arun.siluvery@linux.intel.com> Cc: Alex Dai <yu.dai@intel.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94390 Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_guc_loader.c')
-rw-r--r--drivers/gpu/drm/i915/intel_guc_loader.c40
1 files changed, 19 insertions, 21 deletions
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
index d84c5608f068..876e5da44c4e 100644
--- a/drivers/gpu/drm/i915/intel_guc_loader.c
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -387,7 +387,7 @@ int intel_guc_ucode_load(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
- int err = 0;
+ int retries, err = 0;
if (!i915.enable_guc_submission)
return 0;
@@ -441,29 +441,26 @@ int intel_guc_ucode_load(struct drm_device *dev)
* steppings also so this is extended as well.
*/
/* WaEnableGuCBootHashCheckNotSet:skl,bxt */
- err = guc_ucode_xfer(dev_priv);
- if (err) {
- int retries = 3;
-
- DRM_ERROR("GuC fw load failed, err=%d, attempting reset and retry\n", err);
-
- while (retries--) {
- err = i915_reset_guc(dev_priv);
- if (err)
- break;
-
- err = guc_ucode_xfer(dev_priv);
- if (!err) {
- DRM_DEBUG_DRIVER("GuC fw reload succeeded after reset\n");
- break;
- }
- DRM_DEBUG_DRIVER("GuC fw reload retries left: %d\n", retries);
- }
-
+ for (retries = 3; ; ) {
+ /*
+ * Always reset the GuC just before (re)loading, so
+ * that the state and timing are fairly predictable
+ */
+ err = i915_reset_guc(dev_priv);
if (err) {
- DRM_ERROR("GuC fw reload attempt failed, ret=%d\n", err);
+ DRM_ERROR("GuC reset failed, err %d\n", err);
goto fail;
}
+
+ err = guc_ucode_xfer(dev_priv);
+ if (!err)
+ break;
+
+ if (--retries == 0)
+ goto fail;
+
+ DRM_INFO("GuC fw load failed, err %d; will reset and "
+ "retry %d more time(s)\n", err, retries);
}
guc_fw->guc_fw_load_status = GUC_FIRMWARE_SUCCESS;
@@ -485,6 +482,7 @@ int intel_guc_ucode_load(struct drm_device *dev)
return 0;
fail:
+ DRM_ERROR("GuC firmware load failed, err %d\n", err);
if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_PENDING)
guc_fw->guc_fw_load_status = GUC_FIRMWARE_FAIL;