drm/i915/uc: Abort early on uc_init failure
authorDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Tue, 18 Feb 2020 22:33:25 +0000 (14:33 -0800)
committerChris Wilson <chris@chris-wilson.co.uk>
Thu, 20 Feb 2020 17:48:07 +0000 (17:48 +0000)
Now that we can differentiate wants vs uses GuC/HuC, intel_uc_init is
restricted to running only if we have successfully fetched the required
blob(s) and are committed to using the microcontroller(s).
The only remaining thing that can go wrong in uc_init is the allocation
of GuC/HuC related objects; if we get such a failure better to bail out
immediately instead of wedging later, like we do for e.g.
intel_engines_init, since without objects we can't use the HW, including
not being able to attempt the firmware load.

While at it, remove the unneeded fw_cleanup call (this is handled
outside of gt_init) and add a probe failure injection point for testing.
Also, update the logs for <g/h>uc_init failures to probe_failure() since
they will cause the driver load to fail.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Fernando Pacheco <fernando.pacheco@intel.com>
Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Reviewed-by: Andi Shyti <andi.shyti@intel.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20200218223327.11058-8-daniele.ceraolospurio@intel.com
drivers/gpu/drm/i915/gt/intel_gt.c
drivers/gpu/drm/i915/gt/uc/intel_guc.c
drivers/gpu/drm/i915/gt/uc/intel_huc.c
drivers/gpu/drm/i915/gt/uc/intel_uc.c
drivers/gpu/drm/i915/gt/uc/intel_uc.h

index f1f1b306e0af0f2962d0f5f489b3b7304182ec58..cd64f81a3e604e4cec1ea76d137d3c602668f629 100644 (file)
@@ -592,7 +592,9 @@ int intel_gt_init(struct intel_gt *gt)
        if (err)
                goto err_engines;
 
-       intel_uc_init(&gt->uc);
+       err = intel_uc_init(&gt->uc);
+       if (err)
+               goto err_engines;
 
        err = intel_gt_resume(gt);
        if (err)
index f96d1bdf4bf29d2e55e756c23492279163963a84..97b9c71a6fd4d326a45ceb2f4e7fac0116c755a5 100644 (file)
@@ -376,7 +376,7 @@ err_fw:
        intel_uc_fw_fini(&guc->fw);
 err_fetch:
        intel_uc_fw_cleanup_fetch(&guc->fw);
-       DRM_DEV_DEBUG_DRIVER(gt->i915->drm.dev, "failed with %d\n", ret);
+       i915_probe_error(gt->i915, "failed with %d\n", ret);
        return ret;
 }
 
index 32a069841c14b34ceb1b9cbeffc51b1d1debb0e6..5f448d0e360b66013643d17b5dc646f0e3e3cf15 100644 (file)
@@ -127,7 +127,7 @@ out_fini:
        intel_uc_fw_fini(&huc->fw);
 out:
        intel_uc_fw_cleanup_fetch(&huc->fw);
-       DRM_DEV_DEBUG_DRIVER(i915->drm.dev, "failed with %d\n", err);
+       i915_probe_error(i915, "failed with %d\n", err);
        return err;
 }
 
index f81b4d40bc909b7b9b27c177437d108143b7cd1f..1c74518c2459229a3afb5627b01ad9d23cf9ac74 100644 (file)
@@ -273,7 +273,7 @@ static void __uc_cleanup_firmwares(struct intel_uc *uc)
        intel_uc_fw_cleanup_fetch(&uc->guc.fw);
 }
 
-static void __uc_init(struct intel_uc *uc)
+static int __uc_init(struct intel_uc *uc)
 {
        struct intel_guc *guc = &uc->guc;
        struct intel_huc *huc = &uc->huc;
@@ -282,19 +282,29 @@ static void __uc_init(struct intel_uc *uc)
        GEM_BUG_ON(!intel_uc_wants_guc(uc));
 
        if (!intel_uc_uses_guc(uc))
-               return;
+               return 0;
+
+       if (i915_inject_probe_failure(uc_to_gt(uc)->i915))
+               return -ENOMEM;
 
        /* XXX: GuC submission is unavailable for now */
        GEM_BUG_ON(intel_uc_uses_guc_submission(uc));
 
        ret = intel_guc_init(guc);
-       if (ret) {
-               intel_uc_fw_cleanup_fetch(&huc->fw);
-               return;
+       if (ret)
+               return ret;
+
+       if (intel_uc_uses_huc(uc)) {
+               ret = intel_huc_init(huc);
+               if (ret)
+                       goto out_guc;
        }
 
-       if (intel_uc_uses_huc(uc))
-               intel_huc_init(huc);
+       return 0;
+
+out_guc:
+       intel_guc_fini(guc);
+       return ret;
 }
 
 static void __uc_fini(struct intel_uc *uc)
index c1f39bdc115a9a122519634a5440e0c6573c9803..5ae7b50b7dc1dfc0dbcd027c5d78b8ae1706bf3b 100644 (file)
@@ -17,7 +17,7 @@ struct intel_uc_ops {
        int (*sanitize)(struct intel_uc *uc);
        void (*init_fw)(struct intel_uc *uc);
        void (*fini_fw)(struct intel_uc *uc);
-       void (*init)(struct intel_uc *uc);
+       int (*init)(struct intel_uc *uc);
        void (*fini)(struct intel_uc *uc);
        int (*init_hw)(struct intel_uc *uc);
        void (*fini_hw)(struct intel_uc *uc);
@@ -90,7 +90,7 @@ static inline _TYPE intel_uc_##_NAME(struct intel_uc *uc) \
 intel_uc_ops_function(sanitize, sanitize, int, 0);
 intel_uc_ops_function(fetch_firmwares, init_fw, void, );
 intel_uc_ops_function(cleanup_firmwares, fini_fw, void, );
-intel_uc_ops_function(init, init, void, );
+intel_uc_ops_function(init, init, int, 0);
 intel_uc_ops_function(fini, fini, void, );
 intel_uc_ops_function(init_hw, init_hw, int, 0);
 intel_uc_ops_function(fini_hw, fini_hw, void, );