* [PATCH 0/2] drm/v3d: Idle AXI transactions before cutting the clock on suspend
@ 2026-07-18 13:44 Maíra Canal
2026-07-18 13:44 ` [PATCH 1/2] drm/v3d: Reach the GMP through the hub registers on V3D 7.x Maíra Canal
2026-07-18 13:44 ` [PATCH 2/2] drm/v3d: Idle AXI transactions before disabling the clock on suspend Maíra Canal
0 siblings, 2 replies; 4+ messages in thread
From: Maíra Canal @ 2026-07-18 13:44 UTC (permalink / raw)
To: Melissa Wen, Iago Toral Quiroga, Florian Fainelli
Cc: kernel-dev, dri-devel, stable, Maíra Canal
This series fixes a GPU hang seen on the first job submitted after a
runtime PM resume [1][2]. v3d_power_suspend() disables the GPU clock
without first quiescing the memory interface (AXI), so if the core still
has outstanding transactions in flight the hardware freezes
mid-transaction. That corrupted state survives the power cycle and surfaces
on resume as a GPU hang with an L2T "pte invalid" MMU fault.
The driver already implements the hardware's safe-powerdown sequence
(v3d_idle_axi(), plus v3d_idle_gca() on pre-4.1 HW), but the runtime PM
support added later never invoked it on powerdown.
Patch 1 fixes the GMP register access used by that sequence: on V3D 7.x
the GMP moved out of the per-core block into the hub register region, so
v3d_idle_axi() was touching the wrong registers. It comes first so the
sequence is correct on 7.x before patch 2 starts relying on it.
Patch 2 runs the safe-powerdown sequence in v3d_power_suspend(), while the
core is still powered, letting outstanding reads/writes drain before the
clock is disabled.
[1] https://github.com/raspberrypi/linux/issues/7443
[2] https://github.com/raspberrypi/linux/issues/7488
Best regards,
- Maíra
---
Maíra Canal (2):
drm/v3d: Reach the GMP through the hub registers on V3D 7.x
drm/v3d: Idle AXI transactions before disabling the clock on suspend
drivers/gpu/drm/v3d/v3d_drv.h | 2 ++
drivers/gpu/drm/v3d/v3d_gem.c | 16 ++++++++++++++--
drivers/gpu/drm/v3d/v3d_power.c | 7 +++++++
3 files changed, 23 insertions(+), 2 deletions(-)
---
base-commit: b0a652436b892eb9a036a031b33099dca036faaa
change-id: 20260717-v3d-pm-axi-transactions-acb8f01f1683
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 1/2] drm/v3d: Reach the GMP through the hub registers on V3D 7.x 2026-07-18 13:44 [PATCH 0/2] drm/v3d: Idle AXI transactions before cutting the clock on suspend Maíra Canal @ 2026-07-18 13:44 ` Maíra Canal 2026-07-18 13:44 ` [PATCH 2/2] drm/v3d: Idle AXI transactions before disabling the clock on suspend Maíra Canal 1 sibling, 0 replies; 4+ messages in thread From: Maíra Canal @ 2026-07-18 13:44 UTC (permalink / raw) To: Melissa Wen, Iago Toral Quiroga, Florian Fainelli Cc: kernel-dev, dri-devel, stable, Maíra Canal v3d_idle_axi() drains the GPU's memory interface for a safe powerdown by using the V3D_GMP_CFG register. It reached both registers with the macros V3D_CORE_READ and V3D_CORE_WRITE. On V3D 7.x the GMP is no longer a per-core block; it lives in the hub register region. Reaching it through the per-core register block addresses the wrong region. Select the hub accessors (V3D_{READ,WRITE}) for the GMP on V3D 7.x and keep the per-core path for earlier generations. Cc: stable@vger.kernel.org Fixes: 0ad5bc1ce463 ("drm/v3d: fix up register addresses for V3D 7.x") Signed-off-by: Maíra Canal <mcanal@igalia.com> --- drivers/gpu/drm/v3d/v3d_gem.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 18c941f15e2e..41dc3617fb44 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -39,6 +39,18 @@ v3d_init_core(struct v3d_dev *v3d, int core) static void v3d_idle_axi(struct v3d_dev *v3d, int core) { + if (v3d->ver >= V3D_GEN_71) { + V3D_WRITE(V3D_GMP_CFG(v3d->ver), V3D_GMP_CFG_STOP_REQ); + + if (wait_for((V3D_READ(V3D_GMP_STATUS(v3d->ver)) & + (V3D_GMP_STATUS_RD_COUNT_MASK | + V3D_GMP_STATUS_WR_COUNT_MASK | + V3D_GMP_STATUS_CFG_BUSY)) == 0, 100)) { + drm_err(&v3d->drm, "Failed to wait for safe GMP shutdown\n"); + } + return; + } + V3D_CORE_WRITE(core, V3D_GMP_CFG(v3d->ver), V3D_GMP_CFG_STOP_REQ); if (wait_for((V3D_CORE_READ(core, V3D_GMP_STATUS(v3d->ver)) & -- 2.55.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] drm/v3d: Idle AXI transactions before disabling the clock on suspend 2026-07-18 13:44 [PATCH 0/2] drm/v3d: Idle AXI transactions before cutting the clock on suspend Maíra Canal 2026-07-18 13:44 ` [PATCH 1/2] drm/v3d: Reach the GMP through the hub registers on V3D 7.x Maíra Canal @ 2026-07-18 13:44 ` Maíra Canal 2026-07-18 13:59 ` sashiko-bot 1 sibling, 1 reply; 4+ messages in thread From: Maíra Canal @ 2026-07-18 13:44 UTC (permalink / raw) To: Melissa Wen, Iago Toral Quiroga, Florian Fainelli Cc: kernel-dev, dri-devel, stable, Maíra Canal Currently, v3d_power_suspend() removes the GPU clock without first quiescing the GPU's memory interface (AXI). If the clock is cut while the core still has outstanding AXI transactions in flight, the hardware is frozen mid-transaction. That corrupted state survives the power cycle, and the first job submitted after the next resume will cause a GPU hang accompanied by an L2T "pte invalid" MMU fault. The hardware already provides a safe-powerdown sequence for this: request the GMP to stop and wait for outstanding reads/writes to drain (v3d_idle_axi()), plus the GCA safe shutdown on pre-4.1 HW (v3d_idle_gca()). The driver implements both, but the runtime PM support added later never invoked them when powering the GPU down. Perform the safe-powerdown sequence in v3d_power_suspend() before disabling the clock, while the core is still powered. Cc: stable@vger.kernel.org Link: https://github.com/raspberrypi/linux/issues/7443 Link: https://github.com/raspberrypi/linux/issues/7488 Fixes: 458f2a712ab4 ("drm/v3d: Introduce Runtime Power Management") Signed-off-by: Maíra Canal <mcanal@igalia.com> --- drivers/gpu/drm/v3d/v3d_drv.h | 2 ++ drivers/gpu/drm/v3d/v3d_gem.c | 4 ++-- drivers/gpu/drm/v3d/v3d_power.c | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index 1b88b3dff757..f28b19237c0b 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -618,6 +618,8 @@ extern bool super_pages; void v3d_init_hw_state(struct v3d_dev *v3d); int v3d_gem_init(struct drm_device *dev); void v3d_gem_destroy(struct drm_device *dev); +void v3d_idle_axi(struct v3d_dev *v3d, int core); +void v3d_idle_gca(struct v3d_dev *v3d); void v3d_reset_sms(struct v3d_dev *v3d); void v3d_reset(struct v3d_dev *v3d); void v3d_invalidate_caches(struct v3d_dev *v3d); diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 41dc3617fb44..bc88ebdcdbea 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -36,7 +36,7 @@ v3d_init_core(struct v3d_dev *v3d, int core) V3D_CORE_WRITE(core, V3D_CTL_L2TFLEND, ~0); } -static void +void v3d_idle_axi(struct v3d_dev *v3d, int core) { if (v3d->ver >= V3D_GEN_71) { @@ -61,7 +61,7 @@ v3d_idle_axi(struct v3d_dev *v3d, int core) } } -static void +void v3d_idle_gca(struct v3d_dev *v3d) { if (v3d->ver >= V3D_GEN_41) diff --git a/drivers/gpu/drm/v3d/v3d_power.c b/drivers/gpu/drm/v3d/v3d_power.c index ade8e932fb9c..f608e6d5516a 100644 --- a/drivers/gpu/drm/v3d/v3d_power.c +++ b/drivers/gpu/drm/v3d/v3d_power.c @@ -56,8 +56,15 @@ int v3d_power_suspend(struct device *dev) v3d_clean_caches(v3d); + /* Wait until V3D has no active or pending AXI transactions. */ + v3d_idle_axi(v3d, 0); + v3d_idle_gca(v3d); + ret = v3d_suspend_sms(v3d); if (ret) { + /* Staying active: undo the GMP STOP_REQ from v3d_idle_axi(). */ + V3D_WRITE(V3D_GMP_CFG(v3d->ver), + V3D_READ(V3D_GMP_CFG(v3d->ver)) & ~V3D_GMP_CFG_STOP_REQ); v3d_irq_enable(v3d); return ret; } -- 2.55.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] drm/v3d: Idle AXI transactions before disabling the clock on suspend 2026-07-18 13:44 ` [PATCH 2/2] drm/v3d: Idle AXI transactions before disabling the clock on suspend Maíra Canal @ 2026-07-18 13:59 ` sashiko-bot 0 siblings, 0 replies; 4+ messages in thread From: sashiko-bot @ 2026-07-18 13:59 UTC (permalink / raw) To: Maíra Canal; +Cc: dri-devel Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] Hardware quiescence timeouts are ignored, allowing the driver to cut the clock while transactions are still in flight. - [High] Direct assignment to the V3D_GMP_CFG register in v3d_idle_axi() clobbers existing bits, breaking the newly introduced read-modify-write undo logic. -- --- Patch [2]: [PATCH 2/2] drm/v3d: Idle AXI transactions before disabling the clock on suspend --- commit 586b3ea31f7f24c40a5d3a66c4418d7273686a72 Author: Maíra Canal <mcanal@igalia.com> drm/v3d: Idle AXI transactions before disabling the clock on suspend Currently, v3d_power_suspend() removes the GPU clock without first quiescing the GPU's memory interface (AXI). If the clock is cut while the core still has outstanding AXI transactions in flight, the hardware is frozen mid-transaction. That corrupted state survives the power cycle, and the first job submitted after the next resume will cause a GPU hang. Link: https://github.com/raspberrypi/linux/issues/7443 Link: https://github.com/raspberrypi/linux/issues/7488 > diff --git a/drivers/gpu/drm/v3d/v3d_power.c b/drivers/gpu/drm/v3d/v3d_power.c > index ade8e932fb9c5..f608e6d5516a1 100644 > --- a/drivers/gpu/drm/v3d/v3d_power.c > +++ b/drivers/gpu/drm/v3d/v3d_power.c > @@ -56,8 +56,15 @@ int v3d_power_suspend(struct device *dev) > > v3d_clean_caches(v3d); > > + /* Wait until V3D has no active or pending AXI transactions. */ > + v3d_idle_axi(v3d, 0); > + v3d_idle_gca(v3d); > + [Severity: High] If v3d_idle_axi() times out, it logs an error but returns void: v3d_idle_axi() { ... if (wait_for(... == 0, 100)) { drm_err(&v3d->drm, "Failed to wait for safe GMP shutdown\n"); } } Does this allow the suspend operation to blindly proceed and disable the clock while AXI transactions are still in flight? > ret = v3d_suspend_sms(v3d); > if (ret) { > + /* Staying active: undo the GMP STOP_REQ from v3d_idle_axi(). */ > + V3D_WRITE(V3D_GMP_CFG(v3d->ver), > + V3D_READ(V3D_GMP_CFG(v3d->ver)) & ~V3D_GMP_CFG_STOP_REQ); [Severity: High] Since v3d_idle_axi() uses direct assignment to set V3D_GMP_CFG_STOP_REQ: v3d_idle_axi() { ... V3D_WRITE(V3D_GMP_CFG(v3d->ver), V3D_GMP_CFG_STOP_REQ); } Does this clobber other bits in the register, making the read-modify-write undo logic here write 0 and fail to restore the hardware's original configuration? > v3d_irq_enable(v3d); > return ret; > } -- Sashiko AI review · https://sashiko.dev/#/patchset/20260718-v3d-pm-axi-transactions-v1-0-4ecd7729ed70@igalia.com?part=2 ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-18 13:59 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-18 13:44 [PATCH 0/2] drm/v3d: Idle AXI transactions before cutting the clock on suspend Maíra Canal 2026-07-18 13:44 ` [PATCH 1/2] drm/v3d: Reach the GMP through the hub registers on V3D 7.x Maíra Canal 2026-07-18 13:44 ` [PATCH 2/2] drm/v3d: Idle AXI transactions before disabling the clock on suspend Maíra Canal 2026-07-18 13:59 ` sashiko-bot
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.