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 <michal.wajdeczko@intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patch.msgid.link/20260622132342.19600-2-michal.wajdeczko@intel.com
This commit is contained in:
Michal Wajdeczko
2026-06-22 15:23:37 +02:00
parent 645f1a2589
commit 632cdeecdd

View File

@@ -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))