drm/i915/guc: Simplify intel_guc_init_hw()
authorArkadiusz Hiler <arkadiusz.hiler@intel.com>
Tue, 14 Mar 2017 14:28:11 +0000 (15:28 +0100)
committerJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Wed, 15 Mar 2017 12:26:30 +0000 (14:26 +0200)
Current version of intel_guc_init_hw() does a lot:
 - cares about submission
 - loads huc
 - implement WA

This change offloads some of the logic to intel_uc_init_hw(), which now
cares about the above.

v2: rename guc_hw_reset and fix typo in define name (M. Wajdeczko)
v3: rename once again
v4: remove spurious comments and add some style (J. Lahtinen)
v5: flow changes, got rid of dead checks (M. Wajdeczko)
v6: rebase
v7: rebase & onion teardown (J. Lahtinen)

Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
Cc: Michal Winiarski <michal.winiarski@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Arkadiusz Hiler <arkadiusz.hiler@intel.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/intel_guc_loader.c
drivers/gpu/drm/i915/intel_uc.c
drivers/gpu/drm/i915/intel_uc.h

index 5762c9bdf406afe08bfc859273e73de3d8c8ebef..d87983ba536f9ba8d23a37cfc260104b347d1386 100644 (file)
@@ -4541,7 +4541,7 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
        intel_mocs_init_l3cc_table(dev_priv);
 
        /* We can't enable contexts until all firmware is loaded */
-       ret = intel_guc_init_hw(&dev_priv->guc);
+       ret = intel_uc_init_hw(dev_priv);
        if (ret)
                goto out;
 
index e732266fd610c5425de96a82fa93c5ce8483b337..0a29c1b79c2f1f10d6522f95e3c4b0a8756db0a6 100644 (file)
@@ -344,24 +344,6 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
        return ret;
 }
 
-static int guc_hw_reset(struct drm_i915_private *dev_priv)
-{
-       int ret;
-       u32 guc_status;
-
-       ret = intel_guc_reset(dev_priv);
-       if (ret) {
-               DRM_ERROR("GuC reset failed, ret = %d\n", ret);
-               return ret;
-       }
-
-       guc_status = I915_READ(GUC_STATUS);
-       WARN(!(guc_status & GS_MIA_IN_RESET),
-            "GuC status: 0x%x, MIA core expected to be in reset\n", guc_status);
-
-       return ret;
-}
-
 /**
  * intel_guc_init_hw() - finish preparing the GuC for activity
  * @guc: intel_guc structure
@@ -379,41 +361,22 @@ int intel_guc_init_hw(struct intel_guc *guc)
 {
        struct drm_i915_private *dev_priv = guc_to_i915(guc);
        const char *fw_path = guc->fw.path;
-       int retries, ret, err;
+       int ret;
 
        DRM_DEBUG_DRIVER("GuC fw status: path %s, fetch %s, load %s\n",
                fw_path,
                intel_uc_fw_status_repr(guc->fw.fetch_status),
                intel_uc_fw_status_repr(guc->fw.load_status));
 
-       /* Loading forbidden, or no firmware to load? */
-       if (!i915.enable_guc_loading) {
-               err = 0;
-               goto fail;
-       } else if (fw_path == NULL) {
-               /* Device is known to have no uCode (e.g. no GuC) */
-               err = -ENXIO;
-               goto fail;
+       if (!fw_path) {
+               return -ENXIO;
        } else if (*fw_path == '\0') {
-               /* Device has a GuC but we don't know what f/w to load? */
                WARN(1, "No GuC firmware known for this platform!\n");
-               err = -ENODEV;
-               goto fail;
+               return -ENODEV;
        }
 
-       /* Fetch failed, or already fetched but failed to load? */
-       if (guc->fw.fetch_status != INTEL_UC_FIRMWARE_SUCCESS) {
-               err = -EIO;
-               goto fail;
-       } else if (guc->fw.load_status == INTEL_UC_FIRMWARE_FAIL) {
-               err = -ENOEXEC;
-               goto fail;
-       }
-
-       gen9_reset_guc_interrupts(dev_priv);
-
-       /* We need to notify the guc whenever we change the GGTT */
-       i915_ggtt_enable_guc(dev_priv);
+       if (guc->fw.fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
+               return -EIO;
 
        guc->fw.load_status = INTEL_UC_FIRMWARE_PENDING;
 
@@ -421,102 +384,19 @@ int intel_guc_init_hw(struct intel_guc *guc)
                intel_uc_fw_status_repr(guc->fw.fetch_status),
                intel_uc_fw_status_repr(guc->fw.load_status));
 
-       err = i915_guc_submission_init(dev_priv);
-       if (err)
-               goto fail;
+       ret = guc_ucode_xfer(dev_priv);
 
-       /*
-        * WaEnableuKernelHeaderValidFix:skl,bxt
-        * For BXT, this is only upto B0 but below WA is required for later
-        * steppings also so this is extended as well.
-        */
-       /* WaEnableGuCBootHashCheckNotSet:skl,bxt */
-       for (retries = 3; ; ) {
-               /*
-                * Always reset the GuC just before (re)loading, so
-                * that the state and timing are fairly predictable
-                */
-               err = guc_hw_reset(dev_priv);
-               if (err)
-                       goto fail;
-
-               intel_huc_init_hw(&dev_priv->huc);
-               err = guc_ucode_xfer(dev_priv);
-               if (!err)
-                       break;
-
-               if (--retries == 0)
-                       goto fail;
-
-               DRM_INFO("GuC fw load failed: %d; will reset and "
-                        "retry %d more time(s)\n", err, retries);
-       }
+       if (ret)
+               return -EAGAIN;
 
        guc->fw.load_status = INTEL_UC_FIRMWARE_SUCCESS;
 
-       intel_guc_auth_huc(dev_priv);
-
-       if (i915.enable_guc_submission) {
-               if (i915.guc_log_level >= 0)
-                       gen9_enable_guc_interrupts(dev_priv);
-
-               err = i915_guc_submission_enable(dev_priv);
-               if (err)
-                       goto fail;
-       }
-
        DRM_INFO("GuC %s (firmware %s [version %u.%u])\n",
                 i915.enable_guc_submission ? "submission enabled" : "loaded",
                 guc->fw.path,
                 guc->fw.major_ver_found, guc->fw.minor_ver_found);
 
        return 0;
-
-fail:
-       if (guc->fw.load_status == INTEL_UC_FIRMWARE_PENDING)
-               guc->fw.load_status = INTEL_UC_FIRMWARE_FAIL;
-
-       i915_guc_submission_disable(dev_priv);
-       i915_guc_submission_fini(dev_priv);
-       i915_ggtt_disable_guc(dev_priv);
-
-       /*
-        * We've failed to load the firmware :(
-        *
-        * Decide whether to disable GuC submission and fall back to
-        * execlist mode, and whether to hide the error by returning
-        * zero or to return -EIO, which the caller will treat as a
-        * nonfatal error (i.e. it doesn't prevent driver load, but
-        * marks the GPU as wedged until reset).
-        */
-       if (i915.enable_guc_loading > 1) {
-               ret = -EIO;
-       } else if (i915.enable_guc_submission > 1) {
-               ret = -EIO;
-       } else {
-               ret = 0;
-       }
-
-       if (err == 0 && !HAS_GUC_UCODE(dev_priv))
-               ;       /* Don't mention the GuC! */
-       else if (err == 0)
-               DRM_INFO("GuC firmware load skipped\n");
-       else if (ret != -EIO)
-               DRM_NOTE("GuC firmware load failed: %d\n", err);
-       else
-               DRM_WARN("GuC firmware load failed: %d\n", err);
-
-       if (i915.enable_guc_submission) {
-               if (fw_path == NULL)
-                       DRM_INFO("GuC submission without firmware not supported\n");
-               if (ret == 0)
-                       DRM_NOTE("Falling back from GuC submission to execlist mode\n");
-               else
-                       DRM_ERROR("GuC init failed: %d\n", ret);
-       }
-       i915.enable_guc_submission = 0;
-
-       return ret;
 }
 
 
index f0a69d4388bb21db8c8ec4e0b574d92436cf5bec..69f21cc5c166dd47a89fdd462415ee371e9a5917 100644 (file)
 #include "intel_uc.h"
 #include <linux/firmware.h>
 
+/* Reset GuC providing us with fresh state for both GuC and HuC.
+ */
+static int __intel_uc_reset_hw(struct drm_i915_private *dev_priv)
+{
+       int ret;
+       u32 guc_status;
+
+       ret = intel_guc_reset(dev_priv);
+       if (ret) {
+               DRM_ERROR("GuC reset failed, ret = %d\n", ret);
+               return ret;
+       }
+
+       guc_status = I915_READ(GUC_STATUS);
+       WARN(!(guc_status & GS_MIA_IN_RESET),
+            "GuC status: 0x%x, MIA core expected to be in reset\n",
+            guc_status);
+
+       return ret;
+}
+
 void intel_uc_sanitize_options(struct drm_i915_private *dev_priv)
 {
        if (!HAS_GUC(dev_priv)) {
@@ -63,6 +84,96 @@ void intel_uc_init_fw(struct drm_i915_private *dev_priv)
        intel_guc_init_fw(&dev_priv->guc);
 }
 
+int intel_uc_init_hw(struct drm_i915_private *dev_priv)
+{
+       int ret, attempts;
+
+       /* GuC not enabled, nothing to do */
+       if (!i915.enable_guc_loading)
+               return 0;
+
+       gen9_reset_guc_interrupts(dev_priv);
+
+       /* We need to notify the guc whenever we change the GGTT */
+       i915_ggtt_enable_guc(dev_priv);
+
+       if (i915.enable_guc_submission) {
+               ret = i915_guc_submission_init(dev_priv);
+               if (ret)
+                       goto err;
+       }
+
+       /* WaEnableuKernelHeaderValidFix:skl */
+       /* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
+       if (IS_GEN9(dev_priv))
+               attempts = 3;
+       else
+               attempts = 1;
+
+       while (attempts--) {
+               /*
+                * Always reset the GuC just before (re)loading, so
+                * that the state and timing are fairly predictable
+                */
+               ret = __intel_uc_reset_hw(dev_priv);
+               if (ret)
+                       goto err_submission;
+
+               intel_huc_init_hw(&dev_priv->huc);
+               ret = intel_guc_init_hw(&dev_priv->guc);
+               if (ret == 0 || ret != -EAGAIN)
+                       break;
+
+               DRM_DEBUG_DRIVER("GuC fw load failed: %d; will reset and "
+                                "retry %d more time(s)\n", ret, attempts);
+       }
+
+       /* Did we succeded or run out of retries? */
+       if (ret)
+               goto err_submission;
+
+       intel_guc_auth_huc(dev_priv);
+       if (i915.enable_guc_submission) {
+               if (i915.guc_log_level >= 0)
+                       gen9_enable_guc_interrupts(dev_priv);
+
+               ret = i915_guc_submission_enable(dev_priv);
+               if (ret)
+                       goto err_submission;
+       }
+
+       return 0;
+
+       /*
+        * We've failed to load the firmware :(
+        *
+        * Decide whether to disable GuC submission and fall back to
+        * execlist mode, and whether to hide the error by returning
+        * zero or to return -EIO, which the caller will treat as a
+        * nonfatal error (i.e. it doesn't prevent driver load, but
+        * marks the GPU as wedged until reset).
+        */
+err_submission:
+       if (i915.enable_guc_submission)
+               i915_guc_submission_fini(dev_priv);
+
+err:
+       i915_ggtt_disable_guc(dev_priv);
+
+       DRM_ERROR("GuC init failed\n");
+       if (i915.enable_guc_loading > 1 || i915.enable_guc_submission > 1)
+               ret = -EIO;
+       else
+               ret = 0;
+
+       if (i915.enable_guc_submission) {
+               i915.enable_guc_submission = 0;
+               DRM_NOTE("Falling back from GuC submission to execlist mode\n");
+       }
+
+       return ret;
+}
+
 /*
  * Read GuC command/status register (SOFT_SCRATCH_0)
  * Return true if it contains a response rather than a command
index c5179efe2db90c6abfa1da3546a3d4263eba3658..794e6eaaadde9d88a060313373a55748975d3b74 100644 (file)
@@ -187,6 +187,7 @@ struct intel_huc {
 void intel_uc_sanitize_options(struct drm_i915_private *dev_priv);
 void intel_uc_init_early(struct drm_i915_private *dev_priv);
 void intel_uc_init_fw(struct drm_i915_private *dev_priv);
+int intel_uc_init_hw(struct drm_i915_private *dev_priv);
 void intel_uc_prepare_fw(struct drm_i915_private *dev_priv,
                         struct intel_uc_fw *uc_fw);
 int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len);