Commit 6cd5a72c authored by Arkadiusz Hiler's avatar Arkadiusz Hiler Committed by Joonas Lahtinen

drm/i915/guc: Simplify intel_guc_init_hw()

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: default avatarArkadiusz Hiler <arkadiusz.hiler@intel.com>
Reviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
parent d2be9f2f
...@@ -4541,7 +4541,7 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv) ...@@ -4541,7 +4541,7 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
intel_mocs_init_l3cc_table(dev_priv); intel_mocs_init_l3cc_table(dev_priv);
/* We can't enable contexts until all firmware is loaded */ /* 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) if (ret)
goto out; goto out;
......
...@@ -344,24 +344,6 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) ...@@ -344,24 +344,6 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
return ret; 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 * intel_guc_init_hw() - finish preparing the GuC for activity
* @guc: intel_guc structure * @guc: intel_guc structure
...@@ -379,41 +361,22 @@ int intel_guc_init_hw(struct intel_guc *guc) ...@@ -379,41 +361,22 @@ int intel_guc_init_hw(struct intel_guc *guc)
{ {
struct drm_i915_private *dev_priv = guc_to_i915(guc); struct drm_i915_private *dev_priv = guc_to_i915(guc);
const char *fw_path = guc->fw.path; 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", DRM_DEBUG_DRIVER("GuC fw status: path %s, fetch %s, load %s\n",
fw_path, fw_path,
intel_uc_fw_status_repr(guc->fw.fetch_status), intel_uc_fw_status_repr(guc->fw.fetch_status),
intel_uc_fw_status_repr(guc->fw.load_status)); intel_uc_fw_status_repr(guc->fw.load_status));
/* Loading forbidden, or no firmware to load? */ if (!fw_path) {
if (!i915.enable_guc_loading) { return -ENXIO;
err = 0;
goto fail;
} else if (fw_path == NULL) {
/* Device is known to have no uCode (e.g. no GuC) */
err = -ENXIO;
goto fail;
} else if (*fw_path == '\0') { } 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"); WARN(1, "No GuC firmware known for this platform!\n");
err = -ENODEV; return -ENODEV;
goto fail;
} }
/* Fetch failed, or already fetched but failed to load? */ if (guc->fw.fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
if (guc->fw.fetch_status != INTEL_UC_FIRMWARE_SUCCESS) { return -EIO;
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);
guc->fw.load_status = INTEL_UC_FIRMWARE_PENDING; guc->fw.load_status = INTEL_UC_FIRMWARE_PENDING;
...@@ -421,102 +384,19 @@ int intel_guc_init_hw(struct intel_guc *guc) ...@@ -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.fetch_status),
intel_uc_fw_status_repr(guc->fw.load_status)); intel_uc_fw_status_repr(guc->fw.load_status));
err = i915_guc_submission_init(dev_priv); ret = guc_ucode_xfer(dev_priv);
if (err)
goto fail;
/* if (ret)
* WaEnableuKernelHeaderValidFix:skl,bxt return -EAGAIN;
* 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);
}
guc->fw.load_status = INTEL_UC_FIRMWARE_SUCCESS; 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", DRM_INFO("GuC %s (firmware %s [version %u.%u])\n",
i915.enable_guc_submission ? "submission enabled" : "loaded", i915.enable_guc_submission ? "submission enabled" : "loaded",
guc->fw.path, guc->fw.path,
guc->fw.major_ver_found, guc->fw.minor_ver_found); guc->fw.major_ver_found, guc->fw.minor_ver_found);
return 0; 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;
} }
......
...@@ -26,6 +26,27 @@ ...@@ -26,6 +26,27 @@
#include "intel_uc.h" #include "intel_uc.h"
#include <linux/firmware.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) void intel_uc_sanitize_options(struct drm_i915_private *dev_priv)
{ {
if (!HAS_GUC(dev_priv)) { if (!HAS_GUC(dev_priv)) {
...@@ -63,6 +84,96 @@ void intel_uc_init_fw(struct drm_i915_private *dev_priv) ...@@ -63,6 +84,96 @@ void intel_uc_init_fw(struct drm_i915_private *dev_priv)
intel_guc_init_fw(&dev_priv->guc); 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) * Read GuC command/status register (SOFT_SCRATCH_0)
* Return true if it contains a response rather than a command * Return true if it contains a response rather than a command
......
...@@ -187,6 +187,7 @@ struct intel_huc { ...@@ -187,6 +187,7 @@ struct intel_huc {
void intel_uc_sanitize_options(struct drm_i915_private *dev_priv); 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_early(struct drm_i915_private *dev_priv);
void intel_uc_init_fw(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, void intel_uc_prepare_fw(struct drm_i915_private *dev_priv,
struct intel_uc_fw *uc_fw); struct intel_uc_fw *uc_fw);
int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len); int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment