[PATCH v6 08/16] drm/panfrost: Fix PM refcnt and autosuspend issues at device probe/remove

From: Adrián Larumbe

Date: Wed Aug 26 2026 - 17:21:20 EST


During device probe(), failure to do a PM get() will leave the usage_count
set to 0, which is the value assigned at device creation time. That means
when the autosuspend delay expires, runtime suspend callback won't be
invoked, so the device will remain powered on forever.

On top of that, failure to call PM put() during device unplug means
Panfrost device's PM usage_count increases monotonically for every new
module reload.

The combined outcome of both of the above was that devfreq OPP transition
notifications would be printed all the time, even when no jobs are being
submitted. This quickly fills the kernel ring buffer with junk.

To fix the above:
- Manually adjust the PM refcnt at device probe and removal time.
- Ensure pm_runtime_dont_use_autosuspend is called in the wind-down path.
- Call pm_runtime_put_autosuspend() when device is ready to accept jobs

Signed-off-by: Adrián Larumbe <adrian.larumbe@xxxxxxxxxxxxx>
Fixes: 635430797d3f ("drm/panfrost: Rework runtime PM initialization")
Fixes: 876b15d2c88d ("drm/panfrost: Fix module unload")
---
drivers/gpu/drm/panfrost/panfrost_device.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c
index 0cc277efb585..f6066aef4766 100644
--- a/drivers/gpu/drm/panfrost/panfrost_device.c
+++ b/drivers/gpu/drm/panfrost/panfrost_device.c
@@ -323,6 +323,7 @@ int panfrost_device_init(struct panfrost_device *pfdev)
pm_runtime_set_active(pfdev->base.dev);
pm_runtime_mark_last_busy(pfdev->base.dev);
pm_runtime_enable(pfdev->base.dev);
+ pm_runtime_get_noresume(pfdev->base.dev);
pm_runtime_set_autosuspend_delay(pfdev->base.dev, 50); /* ~3 frames */
pm_runtime_use_autosuspend(pfdev->base.dev);

@@ -334,9 +335,13 @@ int panfrost_device_init(struct panfrost_device *pfdev)
if (err < 0)
goto out_devreg;

+ pm_runtime_put_autosuspend(pfdev->base.dev);
+
return 0;

out_devreg:
+ pm_runtime_dont_use_autosuspend(pfdev->base.dev);
+ pm_runtime_put_noidle(pfdev->base.dev);
pm_runtime_disable(pfdev->base.dev);
panfrost_device_disable_hw(pfdev);
panfrost_gem_fini(pfdev);
@@ -363,6 +368,8 @@ int panfrost_device_init(struct panfrost_device *pfdev)
void panfrost_device_fini(struct panfrost_device *pfdev)
{
pm_runtime_get_sync(pfdev->base.dev);
+ pm_runtime_dont_use_autosuspend(pfdev->base.dev);
+ pm_runtime_put_noidle(pfdev->base.dev);
pm_runtime_disable(pfdev->base.dev);

panfrost_device_disable_hw(pfdev);

--
2.55.0