mirror of https://gitee.com/openkylin/linux.git
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: 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>
This commit is contained in:
parent
d2be9f2f41
commit
6cd5a72c35
|
@ -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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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 @@
|
||||||
#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)
|
||||||
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 {
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue