]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/xe/guc: Return an error code if the GuC load fails
authorJohn Harrison <John.C.Harrison@Intel.com>
Tue, 9 Sep 2025 22:41:31 +0000 (15:41 -0700)
committerJohn Harrison <John.C.Harrison@Intel.com>
Tue, 16 Sep 2025 19:11:08 +0000 (12:11 -0700)
Due to multiple explosion issues in the early days of the Xe driver,
the GuC load was hacked to never return a failure. That prevented
kernel panics and such initially, but now all it achieves is creating
more confusing errors when the driver tries to submit commands to a
GuC it already knows is not there. So fix that up.

As a stop-gap and to help with debug of load failures due to invalid
GuC init params, a wedge call had been added to the inner GuC load
function. The reason being that it leaves the GuC log accessible via
debugfs. However, for an end user, simply aborting the module load is
much cleaner than wedging and trying to continue. The wedge blocks
user submissions but it seems that various bits of the driver itself
still try to submit to a dead GuC and lots of subsequent errors occur.
And with regards to developers debugging why their particular code
change is being rejected by the GuC, it is trivial to either add the
wedge back in and hack the return code to zero again or to just do a
GuC log dump to dmesg.

v2: Add support for error injection testing and drop the now redundant
wedge call.

CC: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
Reviewed-by: Matt Atwood <matthew.s.atwood@intel.com>
Link: https://lore.kernel.org/r/20250909224132.536320-1-John.C.Harrison@Intel.com
drivers/gpu/drm/xe/xe_guc.c

index 171b49817adf1f5c16e8b94773bb172348e9f8c7..00789844ea4d03496aa884b22f6a4cfd89d0acd7 100644 (file)
@@ -1055,7 +1055,7 @@ static s32 guc_pc_get_cur_freq(struct xe_guc_pc *guc_pc)
 #endif
 #define GUC_LOAD_TIME_WARN_MS      200
 
-static void guc_wait_ucode(struct xe_guc *guc)
+static int guc_wait_ucode(struct xe_guc *guc)
 {
        struct xe_gt *gt = guc_to_gt(guc);
        struct xe_mmio *mmio = &gt->mmio;
@@ -1162,7 +1162,7 @@ static void guc_wait_ucode(struct xe_guc *guc)
                        break;
                }
 
-               xe_device_declare_wedged(gt_to_xe(gt));
+               return -EPROTO;
        } else if (delta_ms > GUC_LOAD_TIME_WARN_MS) {
                xe_gt_warn(gt, "excessive init time: %lldms! [status = 0x%08X, timeouts = %d]\n",
                           delta_ms, status, count);
@@ -1174,7 +1174,10 @@ static void guc_wait_ucode(struct xe_guc *guc)
                          delta_ms, xe_guc_pc_get_act_freq(guc_pc), guc_pc_get_cur_freq(guc_pc),
                          before_freq, status, count);
        }
+
+       return 0;
 }
+ALLOW_ERROR_INJECTION(guc_wait_ucode, ERRNO);
 
 static int __xe_guc_upload(struct xe_guc *guc)
 {
@@ -1206,14 +1209,16 @@ static int __xe_guc_upload(struct xe_guc *guc)
                goto out;
 
        /* Wait for authentication */
-       guc_wait_ucode(guc);
+       ret = guc_wait_ucode(guc);
+       if (ret)
+               goto out;
 
        xe_uc_fw_change_status(&guc->fw, XE_UC_FIRMWARE_RUNNING);
        return 0;
 
 out:
        xe_uc_fw_change_status(&guc->fw, XE_UC_FIRMWARE_LOAD_FAIL);
-       return 0        /* FIXME: ret, don't want to stop load currently */;
+       return ret;
 }
 
 static int vf_guc_min_load_for_hwconfig(struct xe_guc *guc)