[PATCH 4/6] drm/vc4: Rebuild the V3D interrupt mask on every power transition

Maíra Canal <[email protected]>
Newsgroups org.freedesktop.lists.dri-devel
Message-ID <[email protected]>
The out-of-memory interrupt is armed once, by bin_bo_alloc(), when the
binner BO is allocated. vc4_irq_disable() masks it on the way down,
vc4_irq_enable() brings back only the render bits, and bin_bo_alloc() does
not run again for a binner BO that is still referenced. An overflow after
an autosuspend therefore raises nothing and the binner stalls, until the
hangcheck resets the GPU and arms the interrupt again.

Therefore, derive the out-of-memory bit in vc4_irq_enable() from whether a
binner BO exists, which is the condition bin_bo_alloc() was standing in
for.

While here, clear the complement of the wanted mask while enabling.
V3D_INTENA and V3D_INTDIS are set/clear registers and the driver only ever
set bits, so a source left enabled will stay enabled and can reach
vc4_irq(), which returns IRQ_NONE for anything outside the three bits it
handles.

Fixes: 35c8b4b2c0fe ("drm/vc4: Allocate binner bo when starting to use the V3D")
Signed-off-by: Maíra Canal <[email protected]>
---
 drivers/gpu/drm/vc4/vc4_irq.c | 42 +++++++++++++++++-------------------------
 1 file changed, 17 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c
index a1004c64e71b..2efed552c08a 100644
--- a/drivers/gpu/drm/vc4/vc4_irq.c
+++ b/drivers/gpu/drm/vc4/vc4_irq.c
@@ -53,10 +53,6 @@
 #include "vc4_regs.h"
 #include "vc4_trace.h"
 
-#define V3D_DRIVER_IRQS (V3D_INT_OUTOMEM | \
-			 V3D_INT_FLDONE | \
-			 V3D_INT_FRDONE)
-
 #define VC4_OVERFLOW_SLOT_TIMEOUT_NS	NSEC_PER_SEC
 
 static void
@@ -247,6 +243,7 @@ void
 vc4_irq_enable(struct drm_device *dev)
 {
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	u32 mask = V3D_INT_FLDONE | V3D_INT_FRDONE;
 
 	if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4))
 		return;
@@ -254,10 +251,18 @@ vc4_irq_enable(struct drm_device *dev)
 	if (!vc4->v3d)
 		return;
 
-	/* Enable the render done interrupts. The out-of-memory interrupt is
-	 * enabled as soon as we have a binner BO allocated.
+	/* Arming the OOM interrupt before there is a binner BO would raise an
+	 * interrupt nothing can clear.
 	 */
-	V3D_WRITE(V3D_INTENA, V3D_INT_FLDONE | V3D_INT_FRDONE);
+	if (vc4->bin_bo)
+		mask |= V3D_INT_OUTOMEM;
+
+	/* Clear any pending interrupts someone might have left around for us. */
+	V3D_WRITE(V3D_INTCTL, mask);
+
+	/* Enable our set of interrupts, masking out any others. */
+	V3D_WRITE(V3D_INTDIS, ~mask);
+	V3D_WRITE(V3D_INTENA, mask);
 }
 
 void
@@ -272,14 +277,14 @@ vc4_irq_disable(struct drm_device *dev)
 		return;
 
 	/* Disable sending interrupts for our driver's IRQs. */
-	V3D_WRITE(V3D_INTDIS, V3D_DRIVER_IRQS);
-
-	/* Clear any pending interrupts we might have left. */
-	V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
+	V3D_WRITE(V3D_INTDIS, ~0);
 
 	/* Finish any interrupt handler still in flight. */
 	synchronize_irq(vc4->irq);
 
+	/* Clear any pending interrupts we might have left. */
+	V3D_WRITE(V3D_INTCTL, ~0);
+
 	cancel_work_sync(&vc4->overflow_mem_work);
 }
 
@@ -297,11 +302,6 @@ int vc4_irq_install(struct drm_device *dev)
 	init_waitqueue_head(&vc4->job_wait_queue);
 	INIT_WORK(&vc4->overflow_mem_work, vc4_overflow_mem_work);
 
-	/* Clear any pending interrupts someone might have left around
-	 * for us.
-	 */
-	V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
-
 	ret = devm_request_irq(dev->dev, vc4->irq, vc4_irq, 0,
 			       dev_name(dev->dev), dev);
 	if (ret)
@@ -331,15 +331,7 @@ void vc4_irq_reset(struct drm_device *dev)
 	if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4))
 		return;
 
-	/* Acknowledge any stale IRQs. */
-	V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
-
-	/*
-	 * Turn all our interrupts on. Binner out of memory is the only
-	 * one we expect to trigger at this point, since the reset cleared
-	 * the overflow memory address and none has been supplied yet.
-	 */
-	V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS);
+	vc4_irq_enable(dev);
 
 	spin_lock_irqsave(&vc4->job_lock, irqflags);
 	vc4_cancel_bin_job(dev);

-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.