From 632cdeecdd30337e3a9293d9de52ad9fbaf5f229 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 22 Jun 2026 15:23:37 +0200 Subject: [PATCH] drm/xe/mmio: Verify MMIO is available We shouldn't access device registers after the device was unplugged or the MMIO bar (GTTMMADR) was unmapped. Instead of relying on the NPD splat due to zeroed tile->mmio.regs, which might be unreliable anyway as not all xe_mmio structs are using that directly, add an explicit check during all xe_mmio read/write operations to test if xe->mmio.regs are still mapped and safely abort with WARN if not. Signed-off-by: Michal Wajdeczko Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patch.msgid.link/20260622132342.19600-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_mmio.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c index 78adb303b663..7e0cefcd16bd 100644 --- a/drivers/gpu/drm/xe/xe_mmio.c +++ b/drivers/gpu/drm/xe/xe_mmio.c @@ -17,6 +17,7 @@ #include "xe_device.h" #include "xe_gt_sriov_vf.h" #include "xe_sriov.h" +#include "xe_tile_printk.h" #include "xe_trace.h" #include "xe_wa.h" @@ -128,6 +129,11 @@ void xe_mmio_init(struct xe_mmio *mmio, struct xe_tile *tile, void __iomem *ptr, mmio->tile = tile; } +static bool mmio_available(struct xe_mmio *mmio) +{ + return !xe_tile_WARN_ON_ONCE(mmio->tile, !mmio->tile->xe->mmio.regs); +} + static void mmio_flush_pending_writes(struct xe_mmio *mmio) { #define DUMMY_REG_OFFSET 0x130030 @@ -146,6 +152,9 @@ u8 xe_mmio_read8(struct xe_mmio *mmio, struct xe_reg reg) u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr); u8 val; + if (!mmio_available(mmio)) + return 0; + mmio_flush_pending_writes(mmio); val = readb(mmio->regs + addr); @@ -158,6 +167,9 @@ void xe_mmio_write8(struct xe_mmio *mmio, struct xe_reg reg, u8 val) { u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr); + if (!mmio_available(mmio)) + return; + trace_xe_reg_rw(mmio, true, addr, val, sizeof(val)); writeb(val, mmio->regs + addr); @@ -168,6 +180,9 @@ u16 xe_mmio_read16(struct xe_mmio *mmio, struct xe_reg reg) u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr); u16 val; + if (!mmio_available(mmio)) + return 0; + mmio_flush_pending_writes(mmio); val = readw(mmio->regs + addr); @@ -180,6 +195,9 @@ void xe_mmio_write32(struct xe_mmio *mmio, struct xe_reg reg, u32 val) { u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr); + if (!mmio_available(mmio)) + return; + trace_xe_reg_rw(mmio, true, addr, val, sizeof(val)); if (!reg.vf && IS_SRIOV_VF(mmio->tile->xe)) @@ -194,6 +212,9 @@ u32 xe_mmio_read32(struct xe_mmio *mmio, struct xe_reg reg) u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr); u32 val; + if (!mmio_available(mmio)) + return 0; + mmio_flush_pending_writes(mmio); if (!reg.vf && IS_SRIOV_VF(mmio->tile->xe))