@@ -5523,8 +5523,10 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
intel_init_gt_powersave(dev_priv);
ret = intel_uc_init(dev_priv);
- if (ret)
+ if (ret) {
+ GEM_BUG_ON(ret == -EIO);
goto err_pm;
+ }
ret = i915_gem_init_hw(dev_priv);
if (ret)
@@ -5577,7 +5579,8 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
mutex_lock(&dev_priv->drm.struct_mutex);
intel_uc_fini_hw(dev_priv);
err_uc_init:
- intel_uc_fini(dev_priv);
+ if (ret != -EIO)
+ intel_uc_fini(dev_priv);
err_pm:
if (ret != -EIO) {
intel_cleanup_gt_powersave(dev_priv);
@@ -5592,11 +5595,6 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
mutex_unlock(&dev_priv->drm.struct_mutex);
err_uc_misc:
- intel_uc_fini_misc(dev_priv);
-
- if (ret != -EIO)
- i915_gem_cleanup_userptr(dev_priv);
-
if (ret == -EIO) {
/*
* Allow engine initialisation to fail by marking the GPU as
@@ -5609,6 +5607,9 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
i915_gem_set_wedged(dev_priv);
}
ret = 0;
+ } else {
+ intel_uc_fini_misc(dev_priv);
+ i915_gem_cleanup_userptr(dev_priv);
}
i915_gem_drain_freed_objects(dev_priv);
@@ -121,6 +121,11 @@ static inline void intel_guc_to_host_event_handler(struct intel_guc *guc)
guc->handler(guc);
}
+static inline bool intel_guc_is_loaded(const struct intel_guc *guc)
+{
+ return intel_uc_fw_is_loaded(&guc->fw);
+}
+
/* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */
#define GUC_GGTT_TOP 0xFEE00000
@@ -424,11 +424,13 @@ int intel_uc_init_hw(struct drm_i915_private *i915)
* Note that there is no fallback as either user explicitly asked for
* the GuC or driver default option was to run with the GuC enabled.
*/
- if (GEM_WARN_ON(ret == -EIO))
- ret = -EINVAL;
-
dev_err(i915->drm.dev, "GuC initialization failed %d\n", ret);
- return ret;
+
+ /* Mark GuC firmware as failed to avoid redundant clean-up */
+ guc->fw.load_status = INTEL_UC_FIRMWARE_FAIL;
+
+ /* We want to disable GPU submission but keep KMS alive */
+ return -EIO;
}
void intel_uc_fini_hw(struct drm_i915_private *i915)
@@ -440,6 +442,9 @@ void intel_uc_fini_hw(struct drm_i915_private *i915)
GEM_BUG_ON(!HAS_GUC(i915));
+ if (!intel_guc_is_loaded(guc))
+ return;
+
if (USES_GUC_SUBMISSION(i915))
intel_guc_submission_disable(guc);
@@ -115,9 +115,14 @@ static inline bool intel_uc_fw_is_selected(struct intel_uc_fw *uc_fw)
return uc_fw->path != NULL;
}
+static inline bool intel_uc_fw_is_loaded(const struct intel_uc_fw *uc_fw)
+{
+ return uc_fw->load_status == INTEL_UC_FIRMWARE_SUCCESS;
+}
+
static inline void intel_uc_fw_sanitize(struct intel_uc_fw *uc_fw)
{
- if (uc_fw->load_status == INTEL_UC_FIRMWARE_SUCCESS)
+ if (intel_uc_fw_is_loaded(uc_fw))
uc_fw->load_status = INTEL_UC_FIRMWARE_PENDING;
}
@@ -131,7 +136,7 @@ static inline void intel_uc_fw_sanitize(struct intel_uc_fw *uc_fw)
*/
static inline u32 intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw)
{
- if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
+ if (!intel_uc_fw_is_loaded(uc_fw))
return 0;
return uc_fw->header_size + uc_fw->ucode_size;