[PATCH] drm/imagination: suspend the GPU for system sleep, not just runtime PM
From: Ryan Brue
Date: Wed Sep 09 2026 - 16:01:31 EST
pvr_pm_ops has only RUNTIME_PM_OPS, so the GPU gets no callback for system
suspend at all. That is fine only while the GPU happens to be
runtime-suspended when the system suspends -- then its own runtime PM has
already disabled the firmware and powered the domain off. If it is
runtime-ACTIVE, genpd powers the domain down during the system suspend
without the driver ever being told, so on resume the driver still believes
its firmware is running. The first firmware operation then never completes:
pvr_mmu_flush_exec -> timeout -> pvr_power_reset -> drm_dev_unplug
and pvr_power_reset() deadlocks, because drm_dev_unplug() waits in
synchronize_srcu() for every drm_dev_enter() section to exit while being
called from inside a DRM ioctl that holds one. The result is an unkillable
D-state process and a GPU that stays dead until reboot.
On mt8173 (amazon-suez) this is deterministic:
echo on > /sys/devices/platform/soc/13000000.gpu/power/control
echo mem > /sys/power/state # wakes on an RTC alarm
vulkaninfo --summary # hangs in D state, every time
and with an autosuspend delay of 50 ms it is also what makes the failure
look intermittent in normal use -- it depends purely on whether the GPU was
idle at the instant of suspend.
pvr_power_device_suspend() already disables the firmware and calls the
platform power_off, and pvr_power_device_resume() is its exact inverse, so
force them for system sleep. The vendor driver arrives at the same rule by
a different route: it holds a wakelock while the MFG domain is powered
("prevent suspend when gpu active") so the system can never suspend with
the GPU on.
The reset-path deadlock itself (drm_dev_unplug() waiting on an SRCU section
held by the ioctl that called pvr_power_reset()) is a separate problem and
is not addressed here; this change only stops the system-sleep path from
triggering it.
Fixes: 727538a4bbff ("drm/imagination: Implement power management")
Assisted-by: LLM
Signed-off-by: Ryan Brue <ryanbrue.dev@xxxxxxxxx>
---
drivers/gpu/drm/imagination/pvr_drv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c
index 5c965ef0274f..23d353141589 100644
--- a/drivers/gpu/drm/imagination/pvr_drv.c
+++ b/drivers/gpu/drm/imagination/pvr_drv.c
@@ -1517,6 +1517,7 @@ MODULE_DEVICE_TABLE(of, dt_match);
static const struct dev_pm_ops pvr_pm_ops = {
RUNTIME_PM_OPS(pvr_power_device_suspend, pvr_power_device_resume, pvr_power_device_idle)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static struct platform_driver pvr_driver = {
---
base-commit: df2908090cda368b01ff43709f51890076c56157
change-id: 20260909-rbrue-suez-upstreaming-pvr-suspend-gpu-system-sleep-bfb9dfd7007b
Best regards,
--
Ryan Brue <ryanbrue.dev@xxxxxxxxx>