]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/xe/memirq: Update interrupt handler logic
authorMichal Wajdeczko <michal.wajdeczko@intel.com>
Mon, 11 May 2026 17:28:37 +0000 (19:28 +0200)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Mon, 18 May 2026 13:22:11 +0000 (09:22 -0400)
To workaround some corner case hardware limitations, new programming
note for the memory based interrupt handler suggests to assume that
some status bytes, like GT_MI_USER_INTERRUPT and GUC_INTR_GUC2HOST,
are always set. Update our interrupt handler to follow the new rules.

Bspec: 53672
Fixes: a6581ebe7685 ("drm/xe/vf: Introduce Memory Based Interrupts Handler")
Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: MichaƂ Winiarski <michal.winiarski@intel.com>
Link: https://patch.msgid.link/20260511172838.2299-2-michal.wajdeczko@intel.com
(cherry picked from commit 284f4cae4579eed9dd4406f18a6c1becc69f8931)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/xe/xe_memirq.c

index 811e07136efbfff8b39c8f88a5f8b1dc0e7f331c..579af47edc61f1020cbdb7fd9fd2cf204328e3e5 100644 (file)
@@ -427,13 +427,25 @@ static bool memirq_received(struct xe_memirq *memirq, struct iosys_map *vector,
        return __memirq_received(memirq, vector, offset, name, true);
 }
 
+static void memirq_assume_received(struct xe_memirq *memirq, const char *source,
+                                  u16 offset, const char *status)
+{
+       memirq_debug(memirq, "ASSUME %s %s(%u)\n", source, status, offset);
+}
+
 static void memirq_dispatch_engine(struct xe_memirq *memirq, struct iosys_map *status,
                                   struct xe_hw_engine *hwe)
 {
        memirq_debug(memirq, "STATUS %s %*ph\n", hwe->name, 16, status->vaddr);
 
-       if (memirq_received(memirq, status, ilog2(GT_MI_USER_INTERRUPT), hwe->name))
-               xe_hw_engine_handle_irq(hwe, GT_MI_USER_INTERRUPT);
+       /*
+        * The programming note says to assume that GT_MI_USER_INTERRUPT is always
+        * set. Check and clear related status byte just for a debug.
+        */
+       if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_MEMIRQ) &&
+           !memirq_received(memirq, status, ilog2(GT_MI_USER_INTERRUPT), hwe->name))
+               memirq_assume_received(memirq, hwe->name, ilog2(GT_MI_USER_INTERRUPT), "USER");
+       xe_hw_engine_handle_irq(hwe, GT_MI_USER_INTERRUPT);
 }
 
 static void memirq_dispatch_guc(struct xe_memirq *memirq, struct iosys_map *status,
@@ -443,8 +455,14 @@ static void memirq_dispatch_guc(struct xe_memirq *memirq, struct iosys_map *stat
 
        memirq_debug(memirq, "STATUS %s %*ph\n", name, 16, status->vaddr);
 
-       if (memirq_received(memirq, status, ilog2(GUC_INTR_GUC2HOST), name))
-               xe_guc_irq_handler(guc, GUC_INTR_GUC2HOST);
+       /*
+        * The programming note says to assume that GUC_INTR_GUC2HOST is always
+        * set. Check and clear related status byte just for a debug.
+        */
+       if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_MEMIRQ) &&
+           !memirq_received(memirq, status, ilog2(GUC_INTR_GUC2HOST), name))
+               memirq_assume_received(memirq, name, ilog2(GUC_INTR_GUC2HOST), "GUC2HOST");
+       xe_guc_irq_handler(guc, GUC_INTR_GUC2HOST);
 
        /*
         * This is a software interrupt that must be cleared after it's consumed