]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/xe/vf: Start CTs before resfix VF post migration recovery
authorMatthew Brost <matthew.brost@intel.com>
Wed, 8 Oct 2025 21:45:22 +0000 (14:45 -0700)
committerMatthew Brost <matthew.brost@intel.com>
Thu, 9 Oct 2025 10:22:48 +0000 (03:22 -0700)
Before RESFIX_DONE, all CTs stuck in the H2G queue need to be squashed,
as they may contain actions which contain invalid GGTT references or are
unnecessary after HW change.

Starting the CTs clears all H2Gs in the queue. Any lost H2Gs are
resubmitted by the GuC submission state machine.

v3:
 - Don't mess with head / tail values (Michal)
v4:
 - Don't mess with broke (Michal)
 - Add CTB_H2G_BUFFER_OFFSET (Michal)
v5:
 - Adjust commit message (Tomasz)

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Link: https://lore.kernel.org/r/20251008214532.3442967-25-matthew.brost@intel.com
drivers/gpu/drm/xe/xe_gt_sriov_vf.c
drivers/gpu/drm/xe/xe_guc_ct.c
drivers/gpu/drm/xe/xe_guc_ct.h

index 34fb8699b7a2a26e53e0def63a3e6ef9197c1e7a..321178b6022a66504e568f2d228b1ee69bdcaba1 100644 (file)
@@ -1134,6 +1134,11 @@ static int vf_post_migration_fixups(struct xe_gt *gt)
        return 0;
 }
 
+static void vf_post_migration_rearm(struct xe_gt *gt)
+{
+       xe_guc_ct_restart(&gt->uc.guc.ct);
+}
+
 static void vf_post_migration_kickstart(struct xe_gt *gt)
 {
        xe_guc_submit_unpause(&gt->uc.guc);
@@ -1185,6 +1190,8 @@ static void vf_post_migration_recovery(struct xe_gt *gt)
        if (err)
                goto fail;
 
+       vf_post_migration_rearm(gt);
+
        err = vf_post_migration_notify_resfix_done(gt);
        if (err && err != -EAGAIN)
                goto fail;
index 503cf5cb5d33eee0b81397ba498c6459126e72a9..3472e4ea2609b6553c753c5b7a6038c67d64141b 100644 (file)
@@ -502,7 +502,7 @@ static void ct_exit_safe_mode(struct xe_guc_ct *ct)
                xe_gt_dbg(ct_to_gt(ct), "GuC CT safe-mode disabled\n");
 }
 
-int xe_guc_ct_enable(struct xe_guc_ct *ct)
+static int __xe_guc_ct_start(struct xe_guc_ct *ct, bool needs_register)
 {
        struct xe_device *xe = ct_to_xe(ct);
        struct xe_gt *gt = ct_to_gt(ct);
@@ -510,21 +510,29 @@ int xe_guc_ct_enable(struct xe_guc_ct *ct)
 
        xe_gt_assert(gt, !xe_guc_ct_enabled(ct));
 
-       xe_map_memset(xe, &ct->bo->vmap, 0, 0, xe_bo_size(ct->bo));
-       guc_ct_ctb_h2g_init(xe, &ct->ctbs.h2g, &ct->bo->vmap);
-       guc_ct_ctb_g2h_init(xe, &ct->ctbs.g2h, &ct->bo->vmap);
+       if (needs_register) {
+               xe_map_memset(xe, &ct->bo->vmap, 0, 0, xe_bo_size(ct->bo));
+               guc_ct_ctb_h2g_init(xe, &ct->ctbs.h2g, &ct->bo->vmap);
+               guc_ct_ctb_g2h_init(xe, &ct->ctbs.g2h, &ct->bo->vmap);
 
-       err = guc_ct_ctb_h2g_register(ct);
-       if (err)
-               goto err_out;
+               err = guc_ct_ctb_h2g_register(ct);
+               if (err)
+                       goto err_out;
 
-       err = guc_ct_ctb_g2h_register(ct);
-       if (err)
-               goto err_out;
+               err = guc_ct_ctb_g2h_register(ct);
+               if (err)
+                       goto err_out;
 
-       err = guc_ct_control_toggle(ct, true);
-       if (err)
-               goto err_out;
+               err = guc_ct_control_toggle(ct, true);
+               if (err)
+                       goto err_out;
+       } else {
+               ct->ctbs.h2g.info.broken = false;
+               ct->ctbs.g2h.info.broken = false;
+               /* Skip everything in H2G buffer */
+               xe_map_memset(xe, &ct->bo->vmap, CTB_H2G_BUFFER_OFFSET, 0,
+                             CTB_H2G_BUFFER_SIZE);
+       }
 
        guc_ct_change_state(ct, XE_GUC_CT_STATE_ENABLED);
 
@@ -556,6 +564,32 @@ err_out:
        return err;
 }
 
+/**
+ * xe_guc_ct_restart() - Restart GuC CT
+ * @ct: the &xe_guc_ct
+ *
+ * Restart GuC CT to an empty state without issuing a CT register MMIO command.
+ *
+ * Return: 0 on success, or a negative errno on failure.
+ */
+int xe_guc_ct_restart(struct xe_guc_ct *ct)
+{
+       return __xe_guc_ct_start(ct, false);
+}
+
+/**
+ * xe_guc_ct_enable() - Enable GuC CT
+ * @ct: the &xe_guc_ct
+ *
+ * Enable GuC CT to an empty state and issue a CT register MMIO command.
+ *
+ * Return: 0 on success, or a negative errno on failure.
+ */
+int xe_guc_ct_enable(struct xe_guc_ct *ct)
+{
+       return __xe_guc_ct_start(ct, true);
+}
+
 static void stop_g2h_handler(struct xe_guc_ct *ct)
 {
        cancel_work_sync(&ct->g2h_worker);
index f8370fa4727f872bda6939b8efe1072b9aba37f8..ca1ce2b3c3548d2ff0a2913c5935bb37e15ca9d1 100644 (file)
@@ -15,6 +15,7 @@ int xe_guc_ct_init_noalloc(struct xe_guc_ct *ct);
 int xe_guc_ct_init(struct xe_guc_ct *ct);
 int xe_guc_ct_init_post_hwconfig(struct xe_guc_ct *ct);
 int xe_guc_ct_enable(struct xe_guc_ct *ct);
+int xe_guc_ct_restart(struct xe_guc_ct *ct);
 void xe_guc_ct_disable(struct xe_guc_ct *ct);
 void xe_guc_ct_stop(struct xe_guc_ct *ct);
 void xe_guc_ct_flush_and_stop(struct xe_guc_ct *ct);