[PATCH v4 06/13] drm/panfrost: Explicitly enable MMU interrupts at device init

From: Adrián Larumbe

Date: Tue Jul 28 2026 - 23:01:51 EST


Because the device must be in a position to accept jobs between the time
drm_dev_register() is called and autosuspend first kicks in, there's a very
narrow window inbetween during which jobs targeting the tiler buffer
object would time out, since the device's PM status is 'Active', but no MMU
interrupts were enabled at device initialisation time.

Signed-off-by: Adrián Larumbe <adrian.larumbe@xxxxxxxxxxxxx>
Fixes: 73e467f60acd ("drm/panfrost: Consolidate reset handling")
---
drivers/gpu/drm/panfrost/panfrost_job.c | 3 ++-
drivers/gpu/drm/panfrost/panfrost_mmu.c | 14 ++++++++++++--
2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c
index 35ff5b0f0013..bda1494eb430 100644
--- a/drivers/gpu/drm/panfrost/panfrost_job.c
+++ b/drivers/gpu/drm/panfrost/panfrost_job.c
@@ -871,7 +871,6 @@ int panfrost_jm_init(struct panfrost_device *pfdev)
js = devm_kzalloc(pfdev->base.dev, sizeof(*js), GFP_KERNEL);
if (!js)
return -ENOMEM;
- pfdev->js = js;

INIT_WORK(&pfdev->reset.work, panfrost_reset_work);
spin_lock_init(&js->job_lock);
@@ -906,6 +905,8 @@ int panfrost_jm_init(struct panfrost_device *pfdev)
}
}

+ pfdev->js = js;
+
panfrost_jm_reset_interrupts(pfdev);
panfrost_jm_enable_interrupts(pfdev);

diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 4a3162c3b659..aad0cd31516d 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -336,6 +336,12 @@ void panfrost_mmu_as_put(struct panfrost_device *pfdev, struct panfrost_mmu *mmu
WARN_ON(atomic_read(&mmu->as_count) < 0);
}

+static void panfrost_mmu_enable_interrupts(struct panfrost_device *pfdev)
+{
+ mmu_write(pfdev, MMU_INT_CLEAR, ~0);
+ mmu_write(pfdev, MMU_INT_MASK, ~0);
+}
+
void panfrost_mmu_reset(struct panfrost_device *pfdev)
{
struct panfrost_mmu *mmu, *mmu_tmp;
@@ -355,8 +361,7 @@ void panfrost_mmu_reset(struct panfrost_device *pfdev)

spin_unlock(&pfdev->as_lock);

- mmu_write(pfdev, MMU_INT_CLEAR, ~0);
- mmu_write(pfdev, MMU_INT_MASK, ~0);
+ panfrost_mmu_enable_interrupts(pfdev);
}

static size_t get_pgsize(u64 addr, size_t size, size_t *count)
@@ -880,6 +885,9 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
u32 status = mmu_read(pfdev, MMU_INT_RAWSTAT);
int ret;

+ if (!pfdev->js)
+ return IRQ_NONE;
+
while (status) {
u32 as = ffs(status | (status >> 16)) - 1;
u32 mask = BIT(as) | BIT(as + 16);
@@ -970,6 +978,8 @@ int panfrost_mmu_init(struct panfrost_device *pfdev)
return err;
}

+ panfrost_mmu_enable_interrupts(pfdev);
+
return 0;
}


--
2.55.0