El dom, 04-10-2026 a las 12:42 -0300, Maíra Canal escribió:
> job_lock is taken by the V3D interrupt handler, so nesting an IRQ-
> unsafe
> lock under it creates an inversion. drm_syncobj_replace_fence() takes
> drm_syncobj::lock, which other paths acquire with interrupts enabled.
> For
> example, a thread interrupted while holding it blocks the handler on
> job_lock, and the handler can only make progress once the submit path
> releases job_lock, which it cannot do while waiting for
> drm_syncobj::lock.
> 
> This is reported by lockdep:
> 
> [  188.139076]
> ========================================================
> [  188.139086] WARNING: possible irq lock inversion dependency
> detected
> [  188.139096] 7.3.0-rc3-00067-gc4f3feeaf60f #67 Tainted: G         C
> [  188.139108] ------------------------------------------------------
> --
> [  188.139116] swapper/0/0 just changed the state of lock:
> [  188.139125] ffff0000054f8ff8 (&vc4->job_lock){-...}-{3:3}, at:
> vc4_irq+0xa8/0x28c [vc4]
> [  188.139234] but this lock took another, HARDIRQ-unsafe lock in the
> past:
> [  188.139242]  (&syncobj->lock){+.+.}-{3:3}
> [  188.139256] and interrupts could create inverse lock ordering
> between them.
> [  188.139267] other info that might help us debug this:
> [  188.139275]  Possible interrupt unsafe locking scenario:
> [  188.139284]        CPU0                    CPU1
> [  188.139291]        ----                    ----
> [  188.139299]   lock(&syncobj->lock);
> [  188.139312]                                local_irq_disable();
> [  188.139320]                                lock(&vc4->job_lock);
> [  188.139335]                                lock(&syncobj->lock);
> [  188.139350]   <Interrupt>
> [  188.139358]     lock(&vc4->job_lock);
> [  188.139372] *** DEADLOCK ***
> 
> Hand the fence over after job_lock is dropped. The job can complete
> and
> drop exec->fence in that window, so take a reference first and
> publish
> through the local pointer, as exec may already be gone.
> 
> Fixes: e84fcb95e074 ("drm/vc4: Export fence through syncobj")
> Signed-off-by: Maíra Canal <[email protected]>
> ---
>  drivers/gpu/drm/vc4/vc4_gem.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_gem.c
> b/drivers/gpu/drm/vc4/vc4_gem.c
> index 6ee4bd77d433..f4be154d4eb0 100644
> --- a/drivers/gpu/drm/vc4/vc4_gem.c
> +++ b/drivers/gpu/drm/vc4/vc4_gem.c
> @@ -639,8 +639,11 @@ vc4_queue_submit(struct drm_device *dev, struct
> vc4_exec_info *exec,
>       fence->seqno = exec->seqno;
>       exec->fence = &fence->base;
>  
> +     /* The job can complete and drop exec->fence as soon as
> job_lock is
> +      * released, so hold our own reference.
> +      */
>       if (out_sync)
> -             drm_syncobj_replace_fence(out_sync, exec->fence);
> +             dma_fence_get(&fence->base);
>  
>       vc4_attach_fences(exec);
>  
> @@ -662,6 +665,11 @@ vc4_queue_submit(struct drm_device *dev, struct
> vc4_exec_info *exec,
>  
>       spin_unlock_irqrestore(&vc4->job_lock, irqflags);
>  
> +     if (out_sync) {
> +             drm_syncobj_replace_fence(out_sync, &fence->base);
> +             dma_fence_put(&fence->base);
> +     }
> +

Doesn't this mean that it is theoretically possible that a very small
job completes and its FLDONE/FRDONE interrupts trigger before we had a
chance to install the fence?

Iago

>       return 0;
>  }
>  
> 

Reply via email to