[PATCH 1/6] drm/vc4: Bound the wait for a binner slot in the overflow work
Maíra Canal <[email protected]>
| Newsgroups | org.freedesktop.lists.dri-devel |
|---|---|
| Message-ID | <[email protected]> |
vc4_v3d_get_bin_slot() waits for a render job to retire when every binner
slot is in use, and the wait has no timeout. That suits its caller in
vc4_validate.c, which runs in a user task and already handles -EINTR and
-ERESTARTSYS, but vc4_overflow_mem_work() calls it from a kworker, where
an interruptible wait cannot be broken by a signal.
vc4_reset() cannot get past that. It reaches cancel_work_sync() through
vc4_irq_disable() before it calls vc4_irq_reset(), and
vc4_irq_finish_render_job() is the only place that advances
finished_seqno and wakes the queue. Once the render job being waited on is
itself hung, the work never returns, cancel_work_sync() never completes,
and the reset that would have freed the job never runs.
Pass the timeout in from the caller and give the overflow work a second.
vc4_overflow_mem_work() already handles a failed allocation by leaving the
binner stalled for the hangcheck to reset, and that reset now completes.
Assisted-by: Claude:claude-opus-5
Fixes: 553c942f8b2c ("drm/vc4: Allow using more than 256MB of CMA memory.")
Signed-off-by: Maíra Canal <[email protected]>
---
drivers/gpu/drm/vc4/vc4_drv.h | 2 +-
drivers/gpu/drm/vc4/vc4_irq.c | 4 +++-
drivers/gpu/drm/vc4/vc4_v3d.c | 4 ++--
drivers/gpu/drm/vc4/vc4_validate.c | 2 +-
4 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 86e0e7c12901..35b9b574671b 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -1053,7 +1053,7 @@ void vc4_plane_async_set_fb(struct drm_plane *plane,
/* vc4_v3d.c */
extern struct platform_driver vc4_v3d_driver;
extern const struct of_device_id vc4_v3d_dt_match[];
-int vc4_v3d_get_bin_slot(struct vc4_dev *vc4);
+int vc4_v3d_get_bin_slot(struct vc4_dev *vc4, uint64_t timeout_ns);
int vc4_v3d_bin_bo_get(struct vc4_dev *vc4, bool *used);
void vc4_v3d_bin_bo_put(struct vc4_dev *vc4);
int vc4_v3d_pm_get(struct vc4_dev *vc4);
diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c
index 90c5194a1c93..95b1a8ad848b 100644
--- a/drivers/gpu/drm/vc4/vc4_irq.c
+++ b/drivers/gpu/drm/vc4/vc4_irq.c
@@ -57,6 +57,8 @@
V3D_INT_FLDONE | \
V3D_INT_FRDONE)
+#define VC4_OVERFLOW_SLOT_TIMEOUT_NS NSEC_PER_SEC
+
static void
vc4_overflow_mem_work(struct work_struct *work)
{
@@ -74,7 +76,7 @@ vc4_overflow_mem_work(struct work_struct *work)
bo = vc4->bin_bo;
- bin_bo_slot = vc4_v3d_get_bin_slot(vc4);
+ bin_bo_slot = vc4_v3d_get_bin_slot(vc4, VC4_OVERFLOW_SLOT_TIMEOUT_NS);
if (bin_bo_slot < 0) {
drm_err(&vc4->base, "Couldn't allocate binner overflow mem\n");
goto complete;
diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c
index d2da8d2f8eeb..b943a003bcbc 100644
--- a/drivers/gpu/drm/vc4/vc4_v3d.c
+++ b/drivers/gpu/drm/vc4/vc4_v3d.c
@@ -152,7 +152,7 @@ void vc4_v3d_init_hw(struct drm_device *dev)
V3D_WRITE(V3D_VPMBASE, 0);
}
-int vc4_v3d_get_bin_slot(struct vc4_dev *vc4)
+int vc4_v3d_get_bin_slot(struct vc4_dev *vc4, uint64_t timeout_ns)
{
struct drm_device *dev = &vc4->base;
unsigned long irqflags;
@@ -183,7 +183,7 @@ int vc4_v3d_get_bin_slot(struct vc4_dev *vc4)
spin_unlock_irqrestore(&vc4->job_lock, irqflags);
if (seqno) {
- int ret = vc4_wait_for_seqno(dev, seqno, ~0ull, true);
+ int ret = vc4_wait_for_seqno(dev, seqno, timeout_ns, true);
if (ret == 0)
goto try_again;
diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c
index 7f2fadfde7a8..a7add99a65a2 100644
--- a/drivers/gpu/drm/vc4/vc4_validate.c
+++ b/drivers/gpu/drm/vc4/vc4_validate.c
@@ -385,7 +385,7 @@ validate_tile_binning_config(VALIDATE_ARGS)
return -EINVAL;
}
- bin_slot = vc4_v3d_get_bin_slot(vc4);
+ bin_slot = vc4_v3d_get_bin_slot(vc4, ~0ull);
if (bin_slot < 0) {
if (bin_slot != -EINTR && bin_slot != -ERESTARTSYS) {
drm_err(dev, "Failed to allocate binner memory: %d\n",
--
2.55.0