* [RFC PATCH 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume
@ 2026-08-19 18:53 Denis Pisarev
2026-08-19 18:53 ` [RFC PATCH 1/1] drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is unresponsive Denis Pisarev
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Denis Pisarev @ 2026-08-19 18:53 UTC (permalink / raw)
To: amd-gfx
Cc: alexander.deucher, christian.koenig, mario.limonciello,
ionut_n2001, dri-devel, linux-kernel, Denis Pisarev
Hi,
This RFC follows up on bugzilla 219492 ("failed to write reg 28b4 wait
reg 28c6" after hibernation) and on the resume_gpu_stable proposal
rejected in January:
https://lore.kernel.org/amd-gfx/20260106125929.25214-6-sunlightlinux@gmail.com/
The rejection argued that (a) kiq sched.ready is managed correctly -
set false in suspend, set true again only after ring tests pass on
resume - and (b) the proposed flag would have disabled the KIQ flush
path permanently. Both points are correct, and this RFC takes a
different route: nothing is disabled proactively; the driver reacts to
observed failures.
MEASURED FAILURE MODE (Cezanne iGPU, Ryzen 7 PRO 5850U, 7.1.8, KDE
Wayland, no ROCm):
- S4 resume -> "failed to write reg 28b4/28c6" + "1a6f4/1a706" pairs
begin in the same second as the thaw and continue at 80-140/hour
for 9+ hours until reboot. kiq sched.ready is true throughout (the
ring test at resume passed).
- Two user-visible consequences: each failed flush burns the ~5 s KIQ
retry window (desktop-wide sluggishness), and the invalidation is
then silently dropped (stale TLBs - correctness).
TRIGGER ISOLATION (single-variable tests, one hibernate cycle each):
- stock (GFXOFF allowed across S4): ~70-140 errors / 30 min of use
- GFXOFF held off across S4: 0 errors (30 min)
- GFXOFF re-enabled 40 min after the clean
resume: 0 errors (15 min;
gating resumption not independently verified)
So the wedge forms in the S4 resume window while GFXOFF is allowed,
and is consistent with the existing semaphore workaround comment in
gmc_v9_0.c about losing invalidate-acknowledge state across
power-gating cycles. A boot-time amdgpu.pg_mask=0 does not even
initialize on this part (probe -ETIMEDOUT), so runtime debugfs
control was used.
THE PATCH (1/1):
- amdgpu_gmc_fw_reg_write_reg_wait() returns -ETIME on failure and
counts consecutive failures
- gmc_v9_0_flush_gpu_tlb() uses its existing MMIO path as fallback
when the KIQ submit fails (invalidations no longer dropped), and
after 3 consecutive failures skips the KIQ path entirely until the
counter resets - so wedged systems stop paying 5 s per flush
- counter resets on every success and in gmc_v9_0_hw_fini(); each
suspend/resume cycle re-arms KIQ. No proactive disabling anywhere.
- gmc_v10/v11/v12 call sites unchanged and compile-safe (int return
used as statement); extending the fallback to them is trivial once
the approach is agreed.
This mirrors what the sibling PASID path already does (KIQ submit,
-ETIME on timeout, MMIO variant as fallback), applied to the per-VMID
path.
OPEN QUESTIONS:
1. Root cause in the S4 window: RLC/ME not processing KIQ invalidates
while GFXOFF is allowed? Happy to run tracing (amdgpu.vm_debug,
VM_INVALIDATE ack registers) on the affected hardware on request.
2. Should the latch be per-xcc-inst?
3. Should amdgpu_gmc_flush_gpu_tlb_pasid()'s KIQ branch share the
latch?
Patch 1/1 follows. Comments very welcome - especially on whether the
failure-driven fallback is the right shape vs. fixing the S4 resume
ordering directly.
Denis Pisarev
Denis Pisarev (1):
drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is
unresponsive
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 15 +++++++++++----
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 4 +++-
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 18 ++++++++++++++----
4 files changed, 30 insertions(+), 9 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH 1/1] drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is unresponsive
2026-08-19 18:53 [RFC PATCH 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Denis Pisarev
@ 2026-08-19 18:53 ` Denis Pisarev
2026-08-20 10:57 ` [RFC PATCH v2 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Denis Pisarev
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Denis Pisarev @ 2026-08-19 18:53 UTC (permalink / raw)
To: amd-gfx
Cc: alexander.deucher, christian.koenig, mario.limonciello,
ionut_n2001, dri-devel, linux-kernel, Denis Pisarev
After resume from S4 (hibernation) on gmc_v9 parts with GFXOFF
(observed on Cezanne / Ryzen 7 PRO 5850U, kernel 7.1.8), KIQ-based TLB
flushes start failing at the moment of the thaw and keep failing for
hours of normal desktop use:
amdgpu 0000:07:00.0: failed to write reg 28b4 wait reg 28c6
amdgpu 0000:07:00.0: failed to write reg 1a6f4 wait reg 1a706
(80-140 errors/hour measured over 9+ hours; bugzilla 219492)
Two problems follow from the current code:
1. Every failed flush burns the full retry window
(MAX_KIQ_REG_TRY * MAX_KIQ_REG_BAILOUT_INTERVAL = ~5 s) before
erroring out, which makes the whole desktop sluggish.
2. The invalidation is then silently dropped - stale TLB entries are
left in place - because gmc_v9_0_flush_gpu_tlb() returns as soon as
amdgpu_gmc_fw_reg_write_reg_wait() finishes, whether it succeeded
or not.
The KIQ ring is marked ready during resume after its ring test passes,
but on affected systems the ring subsequently stops completing
invalidation commands. sched.ready therefore does not reflect the
state of the hardware in this failure mode, and there is no path back
to the direct MMIO invalidation that already exists in
gmc_v9_0_flush_gpu_tlb() for the pre-KIQ stage.
Make the failure observable and self-healing:
- amdgpu_gmc_fw_reg_write_reg_wait() returns 0/-ETIME and counts
consecutive failures in adev->gmc.kiq_flush_failures
(dev_err_ratelimited instead of dev_err, since affected systems
print this 80-140x/hour for hours)
- gmc_v9_0_flush_gpu_tlb() falls back to its existing MMIO path when
the KIQ submit fails, so the invalidation is no longer dropped
- after AMDGPU_KIQ_FLUSH_MAX_FAIL (3) consecutive failures the KIQ
path is skipped entirely until the counter is reset, so wedged
systems stop paying the 5 s retry window per flush
- the counter is reset on every success and in gmc_v9_0_hw_fini(),
i.e. every suspend/resume cycle re-arms the KIQ path; nothing is
disabled proactively
gmc_v10/v11/v12 call sites are unchanged (statement calls compile
fine against the new int return; behavior identical). They can get
the same fallback once this approach is agreed for gmc_v9.
The sibling PASID path (amdgpu_gmc_flush_gpu_tlb_pasid) already has
an -ETIME/MMIO split; this brings the per-VMID path in line with it.
RFC questions for maintainers:
- Is a per-xcd-inst latch preferred over the global gmc one? (single
inst on the affected hardware here)
- Should the latch also gate the KIQ branch of
amdgpu_gmc_flush_gpu_tlb_pasid()? (no failures observed on that
path on the affected system)
- Root cause: with GFXOFF disabled across the S4 cycle (debugfs
amdgpu_gfxoff), zero errors occur across resume and 30 min of use
vs ~70-140 in the control arm. The wedge forms in the S4 resume
window while GFXOFF is allowed, consistent with the existing
semaphore workaround comment about losing invalidate acknowledge
state across power-gating cycles in this file.
Tested on Cezanne (Ryzen 7 PRO 5850U, Manjaro 7.1.8): S4 resume with
GFXOFF enabled reproduces the failure storm on stock; hibernate loop
testing of this patch pending maintainer feedback on the approach.
Signed-off-by: Denis Pisarev <pisarevden@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 15 +++++++++++----
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 4 +++-
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 18 ++++++++++++++----
4 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 7b09410d6..cd5d9e56e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -360,6 +360,8 @@ enum amdgpu_kiq_irq {
#define MAX_KIQ_REG_WAIT 5000 /* in usecs, 5ms */
#define MAX_KIQ_REG_BAILOUT_INTERVAL 5 /* in msecs, 5ms */
#define MAX_KIQ_REG_TRY 1000
+/* consecutive KIQ TLB flush failures before falling back to MMIO */
+#define AMDGPU_KIQ_FLUSH_MAX_FAIL 3
/*
* BIOS.
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index 5d6149ba7..000a1d107 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -874,7 +874,7 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
return r;
}
-void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
+int amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
uint32_t reg0, uint32_t reg1,
uint32_t ref, uint32_t mask,
uint32_t xcc_inst)
@@ -888,7 +888,7 @@ void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
if (adev->mes.ring[MES_PIPE_INST(xcc_inst, 0)].sched.ready) {
amdgpu_mes_reg_write_reg_wait(adev, reg0, reg1,
ref, mask, xcc_inst);
- return;
+ return 0;
}
spin_lock_irqsave(&kiq->ring_lock, flags);
@@ -919,13 +919,20 @@ void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
if (cnt > MAX_KIQ_REG_TRY)
goto failed_kiq;
- return;
+ atomic_set(&adev->gmc.kiq_flush_failures, 0);
+ return 0;
failed_undo:
amdgpu_ring_undo(ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
failed_kiq:
- dev_err(adev->dev, "failed to write reg %x wait reg %x\n", reg0, reg1);
+ if (atomic_inc_return(&adev->gmc.kiq_flush_failures) ==
+ AMDGPU_KIQ_FLUSH_MAX_FAIL)
+ dev_warn(adev->dev,
+ "KIQ reg access keeps failing, falling back to MMIO\n");
+ dev_err_ratelimited(adev->dev,
+ "failed to write reg %x wait reg %x\n", reg0, reg1);
+ return -ETIME;
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
index ddb0d500e..3e5c152ad 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
@@ -366,6 +366,8 @@ struct amdgpu_gmc {
bool flush_tlb_needs_extra_type_0;
bool flush_tlb_needs_extra_type_2;
bool flush_pasid_uses_kiq;
+ /* consecutive KIQ TLB flush failures; MMIO fallback when latched */
+ atomic_t kiq_flush_failures;
bool override_pte;
};
@@ -447,7 +449,7 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
uint32_t flush_type, bool all_hub,
uint32_t inst);
-void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
+int amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
uint32_t reg0, uint32_t reg1,
uint32_t ref, uint32_t mask,
uint32_t xcc_inst);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 8a5c44810..a262df837 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -798,13 +798,18 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
* properly under bare metal
*/
if (adev->gfx.kiq[inst].ring.sched.ready &&
- (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) {
+ (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) &&
+ atomic_read(&adev->gmc.kiq_flush_failures) <
+ AMDGPU_KIQ_FLUSH_MAX_FAIL) {
uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
- amdgpu_gmc_fw_reg_write_reg_wait(adev, req, ack, inv_req,
- 1 << vmid, inst);
- return;
+ if (!amdgpu_gmc_fw_reg_write_reg_wait(adev, req, ack, inv_req,
+ 1 << vmid, inst))
+ return;
+ /* KIQ submit failed - fall through to the MMIO path below
+ * so the invalidation is not silently dropped
+ */
}
/* This path is needed before KIQ/MES/GFXOFF are set up */
@@ -2238,6 +2243,11 @@ static int gmc_v9_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
+ /* KIQ is re-initialized on the next resume; give it a clean
+ * start for the MMIO fallback latch
+ */
+ atomic_set(&adev->gmc.kiq_flush_failures, 0);
+
gmc_v9_0_gart_disable(adev);
if (amdgpu_sriov_vf(adev)) {
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH v2 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume
2026-08-19 18:53 [RFC PATCH 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Denis Pisarev
2026-08-19 18:53 ` [RFC PATCH 1/1] drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is unresponsive Denis Pisarev
@ 2026-08-20 10:57 ` Denis Pisarev
2026-08-20 10:57 ` [RFC PATCH v2 1/1] drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is unresponsive Denis Pisarev
2026-08-20 21:10 ` [RFC PATCH 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Alex Deucher
` (2 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Denis Pisarev @ 2026-08-20 10:57 UTC (permalink / raw)
To: amd-gfx
Cc: alexander.deucher, christian.koenig, mario.limonciello,
ionut_n2001, dri-devel, linux-kernel, Denis Pisarev
Hi,
v2 of this RFC, addressing the automated sashiko-bot review of v1.
The failure data and trigger isolation are unchanged from v1
(bugzilla 219492):
- S4 resume on Cezanne (gmc_v9, GFXOFF) -> KIQ TLB flush reg failures
at 80-140/hour for 9+ hours, sched.ready true throughout; each
failure burns the ~5 s retry window and the invalidation is dropped
- GFXOFF held off across S4: 0 errors (vs ~70-140/30 min stock);
re-enabled 40 min after a clean resume: 0 errors in 15 min
- so the wedge forms in the S4 resume window while GFXOFF is allowed
Changes since v1 (all from the bot review, all reasonable):
1. [Critical] the runtime MMIO fallback now holds the GC block awake
with amdgpu_gfx_off_ctrl(adev, false) across the direct register
access - the unguarded v1 could touch power-gated registers.
Because that call may sleep, the fallback is restricted to process
context.
2. [High] failure counter moved from a global in amdgpu_gmc to the
per-instance struct amdgpu_kiq - no cross-talk between XCCs.
3. [High] SR-IOV VFs never take the runtime MMIO fallback (they lack
privileges for direct GMC invalidation register writes).
4. [Medium] gmc_v9_0_flush_gpu_tlb_mmio() (extracted helper) takes
invalidate_lock with irqsave since the path is now
runtime-reachable.
5. [High, pre-existing] the MES branch now propagates
amdgpu_mes_reg_write_reg_wait()'s error instead of hardcoding
success.
6. [Medium] threshold warning no longer claims a fallback that
gmc_v10/v11/v12 do not implement.
Open question kept from v1: a KIQ command that timed out remains
queued in the ring; if the ring recovers late, a duplicate
(idempotent) invalidation could race a CPU MMIO flush. Input on
whether the req/ack handshake needs protection for that case is
welcome. Alternative direction also still open: fix the S4 resume
ordering itself (RLC/ME vs GFXOFF) instead of a runtime fallback -
happy to run tracing on the affected hardware.
Patch 1/1 follows.
Denis Pisarev
Denis Pisarev (1):
drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is
unresponsive
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 18 ++--
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 2 +-
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 111 ++++++++++++++++++------
5 files changed, 102 insertions(+), 33 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH v2 1/1] drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is unresponsive
2026-08-20 10:57 ` [RFC PATCH v2 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Denis Pisarev
@ 2026-08-20 10:57 ` Denis Pisarev
0 siblings, 0 replies; 9+ messages in thread
From: Denis Pisarev @ 2026-08-20 10:57 UTC (permalink / raw)
To: amd-gfx
Cc: alexander.deucher, christian.koenig, mario.limonciello,
ionut_n2001, dri-devel, linux-kernel, Denis Pisarev
After resume from S4 (hibernation) on gmc_v9 parts with GFXOFF
(observed on Cezanne / Ryzen 7 PRO 5850U, kernel 7.1.8), KIQ-based TLB
flushes start failing at the moment of the thaw and keep failing for
hours of normal desktop use:
amdgpu 0000:07:00.0: failed to write reg 28b4 wait reg 28c6
amdgpu 0000:07:00.0: failed to write reg 1a6f4 wait reg 1a706
(80-140 errors/hour measured over 9+ hours; bugzilla 219492). The KIQ
ring stays sched.ready throughout, so readiness does not reflect the
state of the hardware in this failure mode.
Two problems follow from the current code: every failed flush burns
the full ~5 s KIQ retry window before erroring out (desktop-wide
sluggishness), and the invalidation is then silently dropped (stale
TLBs - correctness).
Make the failure observable and self-healing:
- amdgpu_gmc_fw_reg_write_reg_wait() returns 0/-ETIME, propagates MES
errors, and counts consecutive failures per KIQ instance
- gmc_v9_0_flush_gpu_tlb() falls back to a new
gmc_v9_0_flush_gpu_tlb_mmio() helper (the former pre-KIQ MMIO code,
now with irqsave locking since it is reachable at runtime) when the
KIQ submit fails, so the invalidation is no longer dropped
- after AMDGPU_KIQ_FLUSH_MAX_FAIL (3) consecutive failures the KIQ
path is skipped entirely until the counter resets, so wedged systems
stop paying the 5 s retry window per flush
- the MMIO fallback is restricted to process context on bare metal:
amdgpu_gfx_off_ctrl() is used to hold the GC block awake across the
direct register access (it may sleep), and SR-IOV VFs keep
proxying through KIQ as before
- the counter resets on every success and in gmc_v9_0_hw_fini(); every
suspend/resume cycle re-arms the KIQ path; nothing is disabled
proactively
Changes since v1 (addressing the sashiko-bot review):
- hold GFXOFF off around runtime MMIO access (was: unguarded - could
hit power-gated registers)
- per-KIQ-instance failure counter instead of a global one (multi-XCC
cross-talk)
- invalidate_lock is now taken irqsave (the path is runtime-reachable)
- VFs and interrupt context never take the runtime MMIO fallback
- MES path errors are propagated instead of hardcoded success
- reworded the threshold warning to not promise a fallback that
gmc_v10/v11/v12 do not implement
Known limitation / open question: a KIQ command that already timed out
stays queued in the ring; if the ring recovers late it could emit a
duplicate invalidation concurrently with a CPU MMIO flush. The command
is semantically an idempotent invalidate, but reviewer input on
whether the req/ack handshake needs protection here is welcome.
gmc_v10/v11/v12 call sites are unchanged and compile-safe (int return
used as statement). They can get the same fallback once the approach
is agreed for gmc_v9.
The sibling PASID path (amdgpu_gmc_flush_gpu_tlb_pasid) already has an
-ETIME/MMIO split; this brings the per-VMID path in line with it.
Root-cause note: with GFXOFF held off across the S4 cycle (debugfs
amdgpu_gfxoff), zero errors occur across resume and 30 min of use vs
~70-140 in the control arm; the wedge forms in the S4 resume window
while GFXOFF is allowed, consistent with the existing semaphore
workaround comment in gmc_v9_0.c.
Signed-off-by: Denis Pisarev <pisarevden@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 18 ++--
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 2 +-
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 111 ++++++++++++++++++------
5 files changed, 102 insertions(+), 33 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 7b09410d6..cd5d9e56e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -360,6 +360,8 @@ enum amdgpu_kiq_irq {
#define MAX_KIQ_REG_WAIT 5000 /* in usecs, 5ms */
#define MAX_KIQ_REG_BAILOUT_INTERVAL 5 /* in msecs, 5ms */
#define MAX_KIQ_REG_TRY 1000
+/* consecutive KIQ TLB flush failures before falling back to MMIO */
+#define AMDGPU_KIQ_FLUSH_MAX_FAIL 3
/*
* BIOS.
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index 54c1eb9c4..e2aceb99c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -167,6 +167,8 @@ struct amdgpu_kiq {
struct amdgpu_irq_src irq;
const struct kiq_pm4_funcs *pmf;
void *mqd_backup;
+ /* consecutive TLB flush reg access failures on this instance */
+ atomic_t flush_failures;
};
/*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index 5d6149ba7..49d3d6651 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -874,7 +874,7 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
return r;
}
-void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
+int amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
uint32_t reg0, uint32_t reg1,
uint32_t ref, uint32_t mask,
uint32_t xcc_inst)
@@ -886,9 +886,8 @@ void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
uint32_t seq;
if (adev->mes.ring[MES_PIPE_INST(xcc_inst, 0)].sched.ready) {
- amdgpu_mes_reg_write_reg_wait(adev, reg0, reg1,
- ref, mask, xcc_inst);
- return;
+ return amdgpu_mes_reg_write_reg_wait(adev, reg0, reg1,
+ ref, mask, xcc_inst);
}
spin_lock_irqsave(&kiq->ring_lock, flags);
@@ -919,13 +918,20 @@ void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
if (cnt > MAX_KIQ_REG_TRY)
goto failed_kiq;
- return;
+ atomic_set(&adev->gfx.kiq[xcc_inst].flush_failures, 0);
+ return 0;
failed_undo:
amdgpu_ring_undo(ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
failed_kiq:
- dev_err(adev->dev, "failed to write reg %x wait reg %x\n", reg0, reg1);
+ if (atomic_inc_return(&adev->gfx.kiq[xcc_inst].flush_failures) ==
+ AMDGPU_KIQ_FLUSH_MAX_FAIL)
+ dev_warn(adev->dev,
+ "KIQ reg access keeps failing, MMIO fallback recommended\n");
+ dev_err_ratelimited(adev->dev,
+ "failed to write reg %x wait reg %x\n", reg0, reg1);
+ return -ETIME;
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
index ddb0d500e..303e0ee98 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
@@ -447,7 +447,7 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
uint32_t flush_type, bool all_hub,
uint32_t inst);
-void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
+int amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
uint32_t reg0, uint32_t reg1,
uint32_t ref, uint32_t mask,
uint32_t xcc_inst);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 8a5c44810..11fc9085e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -764,27 +764,28 @@ static bool gmc_v9_0_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
*/
/**
- * gmc_v9_0_flush_gpu_tlb - tlb flush with certain type
+ * gmc_v9_0_flush_gpu_tlb_mmio - tlb flush via direct MMIO
*
* @adev: amdgpu_device pointer
+ * @hub: vmhub to flush
* @vmid: vm instance to flush
* @vmhub: which hub to flush
- * @flush_type: the flush type
+ * @inv_req: invalidation request payload
*
- * Flush the TLB for the requested page table using certain type.
+ * Direct CPU access to the invalidation engine. Callers must ensure
+ * the target block cannot power gate across the access (GFXOFF needs
+ * to be held off at runtime) and must hold no other locks.
*/
-static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
- uint32_t vmhub, uint32_t flush_type)
+static void gmc_v9_0_flush_gpu_tlb_mmio(struct amdgpu_device *adev,
+ struct amdgpu_vmhub *hub,
+ uint32_t vmid, uint32_t vmhub,
+ u32 inv_req)
{
bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(adev, vmhub);
- u32 j, inv_req, tmp, sem, req, ack, inst;
const unsigned int eng = 17;
- struct amdgpu_vmhub *hub;
-
- BUG_ON(vmhub >= AMDGPU_MAX_VMHUBS);
+ unsigned long flags;
+ u32 j, tmp, sem, req, ack, inst;
- hub = &adev->vmhub[vmhub];
- inv_req = gmc_v9_0_get_invalidate_req(vmid, flush_type);
sem = hub->vm_inv_eng0_sem + hub->eng_distance * eng;
req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
@@ -794,21 +795,8 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
else
inst = vmhub;
- /* This is necessary for SRIOV as well as for GFXOFF to function
- * properly under bare metal
- */
- if (adev->gfx.kiq[inst].ring.sched.ready &&
- (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) {
- uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
- uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
-
- amdgpu_gmc_fw_reg_write_reg_wait(adev, req, ack, inv_req,
- 1 << vmid, inst);
- return;
- }
-
/* This path is needed before KIQ/MES/GFXOFF are set up */
- spin_lock(&adev->gmc.invalidate_lock);
+ spin_lock_irqsave(&adev->gmc.invalidate_lock, flags);
/*
* It may lose gpuvm invalidate acknowldege state across power-gating
@@ -870,7 +858,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
WREG32_SOC15_IP_NO_KIQ(GC, sem, 0, GET_INST(GC, inst));
}
- spin_unlock(&adev->gmc.invalidate_lock);
+ spin_unlock_irqrestore(&adev->gmc.invalidate_lock, flags);
if (j < adev->usec_timeout)
return;
@@ -878,6 +866,70 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
DRM_ERROR("Timeout waiting for VM flush ACK!\n");
}
+/**
+ * gmc_v9_0_flush_gpu_tlb - tlb flush with certain type
+ *
+ * @adev: amdgpu_device pointer
+ * @vmid: vm instance to flush
+ * @vmhub: which hub to flush
+ * @flush_type: the flush type
+ *
+ * Flush the TLB for the requested page table using certain type.
+ */
+static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
+ uint32_t vmhub, uint32_t flush_type)
+{
+ u32 inv_req;
+ const unsigned int eng = 17;
+ struct amdgpu_vmhub *hub;
+ u32 inst;
+
+ BUG_ON(vmhub >= AMDGPU_MAX_VMHUBS);
+
+ hub = &adev->vmhub[vmhub];
+ inv_req = gmc_v9_0_get_invalidate_req(vmid, flush_type);
+
+ if (vmhub >= AMDGPU_MMHUB0(0))
+ inst = 0;
+ else
+ inst = vmhub;
+
+ /* This is necessary for SRIOV as well as for GFXOFF to function
+ * properly under bare metal
+ */
+ if (adev->gfx.kiq[inst].ring.sched.ready &&
+ (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) {
+ uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
+ uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
+
+ if (atomic_read(&adev->gfx.kiq[inst].flush_failures) <
+ AMDGPU_KIQ_FLUSH_MAX_FAIL) {
+ if (!amdgpu_gmc_fw_reg_write_reg_wait(adev, req, ack,
+ inv_req,
+ 1 << vmid, inst))
+ return;
+ /* KIQ submit failed; error already logged */
+ }
+
+ /*
+ * MMIO fallback: invalidation must not be silently dropped
+ * when KIQ is unresponsive. Direct register access is only
+ * safe in process context (amdgpu_gfx_off_ctrl may sleep)
+ * and on bare metal; SR-IOV VFs must keep proxying through
+ * KIQ.
+ */
+ if (in_interrupt() || amdgpu_sriov_vf(adev))
+ return;
+
+ amdgpu_gfx_off_ctrl(adev, false);
+ gmc_v9_0_flush_gpu_tlb_mmio(adev, hub, vmid, vmhub, inv_req);
+ amdgpu_gfx_off_ctrl(adev, true);
+ return;
+ }
+
+ gmc_v9_0_flush_gpu_tlb_mmio(adev, hub, vmid, vmhub, inv_req);
+}
+
/**
* gmc_v9_0_flush_gpu_tlb_pasid - tlb flush via pasid
*
@@ -2237,6 +2289,13 @@ static void gmc_v9_0_gart_disable(struct amdgpu_device *adev)
static int gmc_v9_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
+ int i;
+
+ /* KIQ instances are re-initialized on the next resume; re-arm
+ * the MMIO fallback logic
+ */
+ for (i = 0; i < AMDGPU_MAX_GC_INSTANCES; i++)
+ atomic_set(&adev->gfx.kiq[i].flush_failures, 0);
gmc_v9_0_gart_disable(adev);
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume
2026-08-19 18:53 [RFC PATCH 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Denis Pisarev
2026-08-19 18:53 ` [RFC PATCH 1/1] drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is unresponsive Denis Pisarev
2026-08-20 10:57 ` [RFC PATCH v2 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Denis Pisarev
@ 2026-08-20 21:10 ` Alex Deucher
2026-08-24 15:35 ` [RFC PATCH v3 " Denis Pisarev
2026-08-24 18:31 ` [RFC PATCH " Christian König
4 siblings, 0 replies; 9+ messages in thread
From: Alex Deucher @ 2026-08-20 21:10 UTC (permalink / raw)
To: Denis Pisarev
Cc: amd-gfx, alexander.deucher, christian.koenig, mario.limonciello,
ionut_n2001, dri-devel, linux-kernel
On Wed, Aug 19, 2026 at 3:30 PM Denis Pisarev <pisarevden@gmail.com> wrote:
>
> Hi,
>
> This RFC follows up on bugzilla 219492 ("failed to write reg 28b4 wait
> reg 28c6" after hibernation) and on the resume_gpu_stable proposal
> rejected in January:
>
> https://lore.kernel.org/amd-gfx/20260106125929.25214-6-sunlightlinux@gmail.com/
>
> The rejection argued that (a) kiq sched.ready is managed correctly -
> set false in suspend, set true again only after ring tests pass on
> resume - and (b) the proposed flag would have disabled the KIQ flush
> path permanently. Both points are correct, and this RFC takes a
> different route: nothing is disabled proactively; the driver reacts to
> observed failures.
>
> MEASURED FAILURE MODE (Cezanne iGPU, Ryzen 7 PRO 5850U, 7.1.8, KDE
> Wayland, no ROCm):
>
> - S4 resume -> "failed to write reg 28b4/28c6" + "1a6f4/1a706" pairs
> begin in the same second as the thaw and continue at 80-140/hour
> for 9+ hours until reboot. kiq sched.ready is true throughout (the
> ring test at resume passed).
> - Two user-visible consequences: each failed flush burns the ~5 s KIQ
> retry window (desktop-wide sluggishness), and the invalidation is
> then silently dropped (stale TLBs - correctness).
>
> TRIGGER ISOLATION (single-variable tests, one hibernate cycle each):
>
> - stock (GFXOFF allowed across S4): ~70-140 errors / 30 min of use
> - GFXOFF held off across S4: 0 errors (30 min)
> - GFXOFF re-enabled 40 min after the clean
> resume: 0 errors (15 min;
> gating resumption not independently verified)
>
> So the wedge forms in the S4 resume window while GFXOFF is allowed,
> and is consistent with the existing semaphore workaround comment in
> gmc_v9_0.c about losing invalidate-acknowledge state across
> power-gating cycles. A boot-time amdgpu.pg_mask=0 does not even
> initialize on this part (probe -ETIMEDOUT), so runtime debugfs
> control was used.
>
> THE PATCH (1/1):
>
> - amdgpu_gmc_fw_reg_write_reg_wait() returns -ETIME on failure and
> counts consecutive failures
> - gmc_v9_0_flush_gpu_tlb() uses its existing MMIO path as fallback
> when the KIQ submit fails (invalidations no longer dropped), and
> after 3 consecutive failures skips the KIQ path entirely until the
> counter resets - so wedged systems stop paying 5 s per flush
> - counter resets on every success and in gmc_v9_0_hw_fini(); each
> suspend/resume cycle re-arms KIQ. No proactive disabling anywhere.
> - gmc_v10/v11/v12 call sites unchanged and compile-safe (int return
> used as statement); extending the fallback to them is trivial once
> the approach is agreed.
I think it would be better to get KIQ and MES out of the TLB path. If
they get hung, we have bigger problems. Can you give this branch a
spin?
https://gitlab.freedesktop.org/agd5f/linux/-/commits/tlb_inv_rework?ref_type=heads
It switches over to using SDMA and only falls back to MMIO if SDMA is
not available. If you use MMIO, you need to disallow gfxoff before
you touch the registers over MMIO otherwise you'll hang GFX.
Alex
>
> This mirrors what the sibling PASID path already does (KIQ submit,
> -ETIME on timeout, MMIO variant as fallback), applied to the per-VMID
> path.
>
> OPEN QUESTIONS:
>
> 1. Root cause in the S4 window: RLC/ME not processing KIQ invalidates
> while GFXOFF is allowed? Happy to run tracing (amdgpu.vm_debug,
> VM_INVALIDATE ack registers) on the affected hardware on request.
> 2. Should the latch be per-xcc-inst?
> 3. Should amdgpu_gmc_flush_gpu_tlb_pasid()'s KIQ branch share the
> latch?
>
> Patch 1/1 follows. Comments very welcome - especially on whether the
> failure-driven fallback is the right shape vs. fixing the S4 resume
> ordering directly.
>
> Denis Pisarev
>
> Denis Pisarev (1):
> drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is
> unresponsive
>
> drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++
> drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 15 +++++++++++----
> drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 4 +++-
> drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 18 ++++++++++++++----
> 4 files changed, 30 insertions(+), 9 deletions(-)
>
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH v3 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume
2026-08-19 18:53 [RFC PATCH 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Denis Pisarev
` (2 preceding siblings ...)
2026-08-20 21:10 ` [RFC PATCH 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Alex Deucher
@ 2026-08-24 15:35 ` Denis Pisarev
2026-08-24 15:35 ` [RFC PATCH v3 1/1] drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is unresponsive Denis Pisarev
2026-08-24 18:31 ` [RFC PATCH v3 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Alex Deucher
2026-08-24 18:31 ` [RFC PATCH " Christian König
4 siblings, 2 replies; 9+ messages in thread
From: Denis Pisarev @ 2026-08-24 15:35 UTC (permalink / raw)
To: amd-gfx
Cc: alexander.deucher, christian.koenig, mario.limonciello,
ionut_n2001, dri-devel, linux-kernel, Denis Pisarev
Hi,
v3 addresses the two findings from the sashiko-bot review of v2.
Failure data and trigger isolation are unchanged (bugzilla 219492):
S4 resume on Cezanne (gmc_v9, GFXOFF) wedges KIQ TLB flushes at
80-140/hour for 9+ hours with sched.ready true throughout; holding
GFXOFF off across the S4 cycle produces zero errors.
1. [High] "VFs and interrupt contexts silently drop TLB flushes once
the threshold is reached" - correct, and fixed. In v3 the latch
only reroutes bare metal process context to MMIO. VFs and IRQ
contexts keep submitting to KIQ exactly as before this patch, with
per-failure logging, because they have no MMIO alternative; there
is no longer any code path that drops a flush without attempting
and logging.
2. [High] "KIQ and MMIO race on the same invalidation engine if KIQ
recovers" - this remains the documented open question; no code
change in v3. Our analysis: once latched, this path submits no new
KIQ commands, so the exposure is limited to already-queued stale
commands and the recovery transition window. The engine serializes
requests internally, so the realistic worst case is a lost flush
request caught by the existing ACK timeout ("Timeout waiting for VM
flush ACK!"), not silent state corruption. If maintainers consider
a fence necessary (or a dedicated invalidate engine for the MMIO
path), guidance on the preferred mechanism would be welcome.
Full patch history: v1 (initial fallback+counter), v2 (GFXOFF hold,
per-instance counter, irqsave, VF/IRQ restrictions, MES error
propagation) - all from bot review; v3 (this one) fixes the VF/IRQ
drop regression the bot found in v2.
Also still open from the cover letters: the alternative direction of
fixing the S4 resume ordering itself (RLC/ME vs GFXOFF) instead of a
runtime fallback. Happy to run tracing on the affected hardware.
Patch 1/1 follows.
Denis Pisarev
Denis Pisarev (1):
drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is
unresponsive
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 18 ++--
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 2 +-
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 123 +++++++++++++++++++-----
5 files changed, 114 insertions(+), 33 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH v3 1/1] drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is unresponsive
2026-08-24 15:35 ` [RFC PATCH v3 " Denis Pisarev
@ 2026-08-24 15:35 ` Denis Pisarev
2026-08-24 18:31 ` [RFC PATCH v3 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Alex Deucher
1 sibling, 0 replies; 9+ messages in thread
From: Denis Pisarev @ 2026-08-24 15:35 UTC (permalink / raw)
To: amd-gfx
Cc: alexander.deucher, christian.koenig, mario.limonciello,
ionut_n2001, dri-devel, linux-kernel, Denis Pisarev
After resume from S4 (hibernation) on gmc_v9 parts with GFXOFF
(observed on Cezanne / Ryzen 7 PRO 5850U, kernel 7.1.8), KIQ-based TLB
flushes start failing at the moment of the thaw and keep failing for
hours of normal desktop use:
amdgpu 0000:07:00.0: failed to write reg 28b4 wait reg 28c6
amdgpu 0000:07:00.0: failed to write reg 1a6f4 wait reg 1a706
(80-140 errors/hour measured over 9+ hours; bugzilla 219492). The KIQ
ring stays sched.ready throughout, so readiness does not reflect the
state of the hardware in this failure mode.
Two problems follow from the current code: every failed flush burns
the full ~5 s KIQ retry window before erroring out (desktop-wide
sluggishness), and the invalidation is then silently dropped (stale
TLBs - correctness).
Make the failure observable and self-healing:
- amdgpu_gmc_fw_reg_write_reg_wait() returns 0/-ETIME, propagates MES
errors, and counts consecutive failures per KIQ instance
- gmc_v9_0_flush_gpu_tlb() falls back to gmc_v9_0_flush_gpu_tlb_mmio()
(the former pre-KIQ MMIO code, extracted into a helper with irqsave
locking since it is reachable at runtime) when the KIQ submit fails,
so the invalidation is no longer dropped
- after AMDGPU_KIQ_FLUSH_MAX_FAIL (3) consecutive failures the KIQ
path is skipped entirely for bare metal process context, so wedged
systems stop paying the 5 s retry window per flush
- the MMIO fallback holds the GC block awake with
amdgpu_gfx_off_ctrl() across the direct register access (it may
sleep, hence process context only) and is restricted to bare metal;
SR-IOV VFs and interrupt contexts never take it - they keep
attempting KIQ exactly as before this patch, with failures logged,
because they have no MMIO alternative
- the counter resets on every success and in gmc_v9_0_hw_fini(); every
suspend/resume cycle re-arms the KIQ path; nothing is disabled
proactively
Known limitation / open question: a KIQ command that already timed out
stays queued in the ring; if the ring recovers late it could emit a
duplicate invalidation concurrently with a CPU MMIO flush. The
invalidation engine serializes requests internally, so the expected
worst case is a lost flush request caught by the existing ACK timeout
("Timeout waiting for VM flush ACK!") rather than silent corruption;
once latched this path submits no new KIQ commands, bounding the
window. Reviewer input on whether a fence (or a dedicated invalidate
engine for the MMIO path) is required would be welcome.
Changes since v2 (sashiko-bot review):
- VFs and IRQ contexts are no longer silently dropped once the latch
is set: they keep submitting to KIQ with per-failure logging,
matching pre-patch behavior exactly; the latch now only reroutes
bare metal process context to MMIO
Changes since v1 (sashiko-bot review):
- hold GFXOFF off around runtime MMIO access (was: unguarded)
- per-KIQ-instance failure counter instead of a global one
- invalidate_lock taken irqsave in the extracted MMIO helper
- MES path errors propagated instead of hardcoded success
- threshold warning no longer promises a fallback gmc_v10/v11/v12 do
not implement
gmc_v10/v11/v12 call sites are unchanged and compile-safe (int return
used as statement). The sibling PASID path
(amdgpu_gmc_flush_gpu_tlb_pasid) already has an -ETIME/MMIO split;
this brings the per-VMID path in line with it.
Root-cause note: with GFXOFF held off across the S4 cycle (debugfs
amdgpu_gfxoff), zero errors occur across resume and 30 min of use vs
~70-140 in the control arm; the wedge forms in the S4 resume window
while GFXOFF is allowed, consistent with the existing semaphore
workaround comment in gmc_v9_0.c.
Signed-off-by: Denis Pisarev <pisarevden@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 18 ++--
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 2 +-
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 123 +++++++++++++++++++-----
5 files changed, 114 insertions(+), 33 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 7b09410d6..cd5d9e56e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -360,6 +360,8 @@ enum amdgpu_kiq_irq {
#define MAX_KIQ_REG_WAIT 5000 /* in usecs, 5ms */
#define MAX_KIQ_REG_BAILOUT_INTERVAL 5 /* in msecs, 5ms */
#define MAX_KIQ_REG_TRY 1000
+/* consecutive KIQ TLB flush failures before falling back to MMIO */
+#define AMDGPU_KIQ_FLUSH_MAX_FAIL 3
/*
* BIOS.
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index 54c1eb9c4..e2aceb99c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -167,6 +167,8 @@ struct amdgpu_kiq {
struct amdgpu_irq_src irq;
const struct kiq_pm4_funcs *pmf;
void *mqd_backup;
+ /* consecutive TLB flush reg access failures on this instance */
+ atomic_t flush_failures;
};
/*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index 5d6149ba7..49d3d6651 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -874,7 +874,7 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
return r;
}
-void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
+int amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
uint32_t reg0, uint32_t reg1,
uint32_t ref, uint32_t mask,
uint32_t xcc_inst)
@@ -886,9 +886,8 @@ void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
uint32_t seq;
if (adev->mes.ring[MES_PIPE_INST(xcc_inst, 0)].sched.ready) {
- amdgpu_mes_reg_write_reg_wait(adev, reg0, reg1,
- ref, mask, xcc_inst);
- return;
+ return amdgpu_mes_reg_write_reg_wait(adev, reg0, reg1,
+ ref, mask, xcc_inst);
}
spin_lock_irqsave(&kiq->ring_lock, flags);
@@ -919,13 +918,20 @@ void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
if (cnt > MAX_KIQ_REG_TRY)
goto failed_kiq;
- return;
+ atomic_set(&adev->gfx.kiq[xcc_inst].flush_failures, 0);
+ return 0;
failed_undo:
amdgpu_ring_undo(ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
failed_kiq:
- dev_err(adev->dev, "failed to write reg %x wait reg %x\n", reg0, reg1);
+ if (atomic_inc_return(&adev->gfx.kiq[xcc_inst].flush_failures) ==
+ AMDGPU_KIQ_FLUSH_MAX_FAIL)
+ dev_warn(adev->dev,
+ "KIQ reg access keeps failing, MMIO fallback recommended\n");
+ dev_err_ratelimited(adev->dev,
+ "failed to write reg %x wait reg %x\n", reg0, reg1);
+ return -ETIME;
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
index ddb0d500e..303e0ee98 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
@@ -447,7 +447,7 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
uint32_t flush_type, bool all_hub,
uint32_t inst);
-void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
+int amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
uint32_t reg0, uint32_t reg1,
uint32_t ref, uint32_t mask,
uint32_t xcc_inst);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 8a5c44810..3f04a25b1 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -764,27 +764,28 @@ static bool gmc_v9_0_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
*/
/**
- * gmc_v9_0_flush_gpu_tlb - tlb flush with certain type
+ * gmc_v9_0_flush_gpu_tlb_mmio - tlb flush via direct MMIO
*
* @adev: amdgpu_device pointer
+ * @hub: vmhub to flush
* @vmid: vm instance to flush
* @vmhub: which hub to flush
- * @flush_type: the flush type
+ * @inv_req: invalidation request payload
*
- * Flush the TLB for the requested page table using certain type.
+ * Direct CPU access to the invalidation engine. Callers must ensure
+ * the target block cannot power gate across the access (GFXOFF needs
+ * to be held off at runtime) and must hold no other locks.
*/
-static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
- uint32_t vmhub, uint32_t flush_type)
+static void gmc_v9_0_flush_gpu_tlb_mmio(struct amdgpu_device *adev,
+ struct amdgpu_vmhub *hub,
+ uint32_t vmid, uint32_t vmhub,
+ u32 inv_req)
{
bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(adev, vmhub);
- u32 j, inv_req, tmp, sem, req, ack, inst;
const unsigned int eng = 17;
- struct amdgpu_vmhub *hub;
-
- BUG_ON(vmhub >= AMDGPU_MAX_VMHUBS);
+ unsigned long flags;
+ u32 j, tmp, sem, req, ack, inst;
- hub = &adev->vmhub[vmhub];
- inv_req = gmc_v9_0_get_invalidate_req(vmid, flush_type);
sem = hub->vm_inv_eng0_sem + hub->eng_distance * eng;
req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
@@ -794,21 +795,8 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
else
inst = vmhub;
- /* This is necessary for SRIOV as well as for GFXOFF to function
- * properly under bare metal
- */
- if (adev->gfx.kiq[inst].ring.sched.ready &&
- (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) {
- uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
- uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
-
- amdgpu_gmc_fw_reg_write_reg_wait(adev, req, ack, inv_req,
- 1 << vmid, inst);
- return;
- }
-
/* This path is needed before KIQ/MES/GFXOFF are set up */
- spin_lock(&adev->gmc.invalidate_lock);
+ spin_lock_irqsave(&adev->gmc.invalidate_lock, flags);
/*
* It may lose gpuvm invalidate acknowldege state across power-gating
@@ -870,7 +858,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
WREG32_SOC15_IP_NO_KIQ(GC, sem, 0, GET_INST(GC, inst));
}
- spin_unlock(&adev->gmc.invalidate_lock);
+ spin_unlock_irqrestore(&adev->gmc.invalidate_lock, flags);
if (j < adev->usec_timeout)
return;
@@ -878,6 +866,82 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
DRM_ERROR("Timeout waiting for VM flush ACK!\n");
}
+/**
+ * gmc_v9_0_flush_gpu_tlb - tlb flush with certain type
+ *
+ * @adev: amdgpu_device pointer
+ * @vmid: vm instance to flush
+ * @vmhub: which hub to flush
+ * @flush_type: the flush type
+ *
+ * Flush the TLB for the requested page table using certain type.
+ */
+static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
+ uint32_t vmhub, uint32_t flush_type)
+{
+ u32 inv_req, inst;
+ const unsigned int eng = 17;
+ struct amdgpu_vmhub *hub;
+ bool latched, can_mmio;
+
+ BUG_ON(vmhub >= AMDGPU_MAX_VMHUBS);
+
+ hub = &adev->vmhub[vmhub];
+ inv_req = gmc_v9_0_get_invalidate_req(vmid, flush_type);
+
+ if (vmhub >= AMDGPU_MMHUB0(0))
+ inst = 0;
+ else
+ inst = vmhub;
+
+ latched = atomic_read(&adev->gfx.kiq[inst].flush_failures) >=
+ AMDGPU_KIQ_FLUSH_MAX_FAIL;
+ /* Direct register access requires process context (holding
+ * GFXOFF off may sleep) and bare metal (VFs lack the
+ * privileges for direct GMC invalidation writes)
+ */
+ can_mmio = !in_interrupt() && !amdgpu_sriov_vf(adev);
+
+ /* This is necessary for SRIOV as well as for GFXOFF to function
+ * properly under bare metal
+ */
+ if (adev->gfx.kiq[inst].ring.sched.ready &&
+ (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) {
+ uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
+ uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
+
+ /* Once latched, KIQ is only attempted by callers that have
+ * no MMIO alternative (IRQ context, VFs); bare metal
+ * process context goes straight to the MMIO fallback
+ */
+ if (!latched || !can_mmio) {
+ if (!amdgpu_gmc_fw_reg_write_reg_wait(adev, req, ack,
+ inv_req,
+ 1 << vmid, inst))
+ return;
+ /* KIQ submit failed; error already logged above */
+ }
+
+ /*
+ * MMIO fallback: the invalidation must not be silently
+ * dropped when KIQ is unresponsive.
+ */
+ if (can_mmio) {
+ amdgpu_gfx_off_ctrl(adev, false);
+ gmc_v9_0_flush_gpu_tlb_mmio(adev, hub, vmid, vmhub,
+ inv_req);
+ amdgpu_gfx_off_ctrl(adev, true);
+ }
+ /* IRQ context / VF: flush dropped as before this patch;
+ * the failure was logged in
+ * amdgpu_gmc_fw_reg_write_reg_wait()
+ */
+ return;
+ }
+
+ gmc_v9_0_flush_gpu_tlb_mmio(adev, hub, vmid, vmhub, inv_req);
+}
+
/**
* gmc_v9_0_flush_gpu_tlb_pasid - tlb flush via pasid
*
@@ -2237,6 +2301,13 @@ static void gmc_v9_0_gart_disable(struct amdgpu_device *adev)
static int gmc_v9_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
+ int i;
+
+ /* KIQ instances are re-initialized on the next resume; re-arm
+ * the MMIO fallback logic
+ */
+ for (i = 0; i < AMDGPU_MAX_GC_INSTANCES; i++)
+ atomic_set(&adev->gfx.kiq[i].flush_failures, 0);
gmc_v9_0_gart_disable(adev);
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH v3 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume
2026-08-24 15:35 ` [RFC PATCH v3 " Denis Pisarev
2026-08-24 15:35 ` [RFC PATCH v3 1/1] drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is unresponsive Denis Pisarev
@ 2026-08-24 18:31 ` Alex Deucher
1 sibling, 0 replies; 9+ messages in thread
From: Alex Deucher @ 2026-08-24 18:31 UTC (permalink / raw)
To: Denis Pisarev
Cc: amd-gfx, alexander.deucher, christian.koenig, mario.limonciello,
ionut_n2001, dri-devel, linux-kernel
On Mon, Aug 24, 2026 at 12:30 PM Denis Pisarev <pisarevden@gmail.com> wrote:
>
> Hi,
>
> v3 addresses the two findings from the sashiko-bot review of v2.
> Failure data and trigger isolation are unchanged (bugzilla 219492):
> S4 resume on Cezanne (gmc_v9, GFXOFF) wedges KIQ TLB flushes at
> 80-140/hour for 9+ hours with sched.ready true throughout; holding
> GFXOFF off across the S4 cycle produces zero errors.
>
> 1. [High] "VFs and interrupt contexts silently drop TLB flushes once
> the threshold is reached" - correct, and fixed. In v3 the latch
> only reroutes bare metal process context to MMIO. VFs and IRQ
> contexts keep submitting to KIQ exactly as before this patch, with
> per-failure logging, because they have no MMIO alternative; there
> is no longer any code path that drops a flush without attempting
> and logging.
>
> 2. [High] "KIQ and MMIO race on the same invalidation engine if KIQ
> recovers" - this remains the documented open question; no code
> change in v3. Our analysis: once latched, this path submits no new
> KIQ commands, so the exposure is limited to already-queued stale
> commands and the recovery transition window. The engine serializes
> requests internally, so the realistic worst case is a lost flush
> request caught by the existing ACK timeout ("Timeout waiting for VM
> flush ACK!"), not silent state corruption. If maintainers consider
> a fence necessary (or a dedicated invalidate engine for the MMIO
> path), guidance on the preferred mechanism would be welcome.
>
> Full patch history: v1 (initial fallback+counter), v2 (GFXOFF hold,
> per-instance counter, irqsave, VF/IRQ restrictions, MES error
> propagation) - all from bot review; v3 (this one) fixes the VF/IRQ
> drop regression the bot found in v2.
>
> Also still open from the cover letters: the alternative direction of
> fixing the S4 resume ordering itself (RLC/ME vs GFXOFF) instead of a
> runtime fallback. Happy to run tracing on the affected hardware.
>
If that's a problem, that should be fixed. That said, did you have
any success with the branch I proposed?
Alex
> Patch 1/1 follows.
>
> Denis Pisarev
>
> Denis Pisarev (1):
> drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is
> unresponsive
>
> drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 2 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 18 ++--
> drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 2 +-
> drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 123 +++++++++++++++++++-----
> 5 files changed, 114 insertions(+), 33 deletions(-)
>
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume
2026-08-19 18:53 [RFC PATCH 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Denis Pisarev
` (3 preceding siblings ...)
2026-08-24 15:35 ` [RFC PATCH v3 " Denis Pisarev
@ 2026-08-24 18:31 ` Christian König
4 siblings, 0 replies; 9+ messages in thread
From: Christian König @ 2026-08-24 18:31 UTC (permalink / raw)
To: Denis Pisarev, amd-gfx
Cc: alexander.deucher, mario.limonciello, ionut_n2001, dri-devel,
linux-kernel
On 8/19/26 20:53, Denis Pisarev wrote:
> Hi,
>
> This RFC follows up on bugzilla 219492 ("failed to write reg 28b4 wait
> reg 28c6" after hibernation) and on the resume_gpu_stable proposal
> rejected in January:
>
> https://lore.kernel.org/amd-gfx/20260106125929.25214-6-sunlightlinux@gmail.com/
>
> The rejection argued that (a) kiq sched.ready is managed correctly -
> set false in suspend, set true again only after ring tests pass on
> resume - and (b) the proposed flag would have disabled the KIQ flush
> path permanently. Both points are correct, and this RFC takes a
> different route: nothing is disabled proactively; the driver reacts to
> observed failures.
>
> MEASURED FAILURE MODE (Cezanne iGPU, Ryzen 7 PRO 5850U, 7.1.8, KDE
> Wayland, no ROCm):
>
> - S4 resume -> "failed to write reg 28b4/28c6" + "1a6f4/1a706" pairs
> begin in the same second as the thaw and continue at 80-140/hour
> for 9+ hours until reboot. kiq sched.ready is true throughout (the
> ring test at resume passed).
> - Two user-visible consequences: each failed flush burns the ~5 s KIQ
> retry window (desktop-wide sluggishness), and the invalidation is
> then silently dropped (stale TLBs - correctness).
>
> TRIGGER ISOLATION (single-variable tests, one hibernate cycle each):
>
> - stock (GFXOFF allowed across S4): ~70-140 errors / 30 min of use
> - GFXOFF held off across S4: 0 errors (30 min)
> - GFXOFF re-enabled 40 min after the clean
> resume: 0 errors (15 min;
> gating resumption not independently verified)
>
> So the wedge forms in the S4 resume window while GFXOFF is allowed,
> and is consistent with the existing semaphore workaround comment in
> gmc_v9_0.c about losing invalidate-acknowledge state across
> power-gating cycles. A boot-time amdgpu.pg_mask=0 does not even
> initialize on this part (probe -ETIMEDOUT), so runtime debugfs
> control was used.
>
> THE PATCH (1/1):
>
> - amdgpu_gmc_fw_reg_write_reg_wait() returns -ETIME on failure and
> counts consecutive failures
> - gmc_v9_0_flush_gpu_tlb() uses its existing MMIO path as fallback
> when the KIQ submit fails (invalidations no longer dropped), and
> after 3 consecutive failures skips the KIQ path entirely until the
> counter resets - so wedged systems stop paying 5 s per flush
> - counter resets on every success and in gmc_v9_0_hw_fini(); each
> suspend/resume cycle re-arms KIQ. No proactive disabling anywhere.
> - gmc_v10/v11/v12 call sites unchanged and compile-safe (int return
> used as statement); extending the fallback to them is trivial once
> the approach is agreed.
>
> This mirrors what the sibling PASID path already does (KIQ submit,
> -ETIME on timeout, MMIO variant as fallback), applied to the per-VMID
> path.
>
> OPEN QUESTIONS:
>
> 1. Root cause in the S4 window: RLC/ME not processing KIQ invalidates
> while GFXOFF is allowed? Happy to run tracing (amdgpu.vm_debug,
> VM_INVALIDATE ack registers) on the affected hardware on request.
> 2. Should the latch be per-xcc-inst?
> 3. Should amdgpu_gmc_flush_gpu_tlb_pasid()'s KIQ branch share the
> latch?
That still doesn't make any sense at all.
First of all GFXOFF completely turns of the CP/ME/KIQ, so sending *anything* to the KIQ including the ring test would fail.
Then second fallback is simply not an acceptable option, it is a *must* have to have a working KIQ.
Regards,
Christian.
>
> Patch 1/1 follows. Comments very welcome - especially on whether the
> failure-driven fallback is the right shape vs. fixing the S4 resume
> ordering directly.
>
> Denis Pisarev
>
> Denis Pisarev (1):
> drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is
> unresponsive
>
> drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++
> drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 15 +++++++++++----
> drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 4 +++-
> drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 18 ++++++++++++++----
> 4 files changed, 30 insertions(+), 9 deletions(-)
>
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-08-24 18:31 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-19 18:53 [RFC PATCH 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Denis Pisarev
2026-08-19 18:53 ` [RFC PATCH 1/1] drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is unresponsive Denis Pisarev
2026-08-20 10:57 ` [RFC PATCH v2 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Denis Pisarev
2026-08-20 10:57 ` [RFC PATCH v2 1/1] drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is unresponsive Denis Pisarev
2026-08-20 21:10 ` [RFC PATCH 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Alex Deucher
2026-08-24 15:35 ` [RFC PATCH v3 " Denis Pisarev
2026-08-24 15:35 ` [RFC PATCH v3 1/1] drm/amdgpu: fall back to MMIO TLB invalidation when KIQ is unresponsive Denis Pisarev
2026-08-24 18:31 ` [RFC PATCH v3 0/1] drm/amdgpu: MMIO TLB invalidation fallback when KIQ is wedged after S4 resume Alex Deucher
2026-08-24 18:31 ` [RFC PATCH " Christian König
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®