vc4_job_handle_completed() drops and retakes job_lock around every job it completes, so a batch of N finished jobs costs N + 1 acquisitions of a lock the interrupt handler takes on every bin and render done. Each retake can contend with the handler.
Splice job_done_list onto a local list under a single acquisition and complete the jobs from there. Jobs finishing meanwhile requeue the done work, which picks them up on its next run. Signed-off-by: Maíra Canal <[email protected]> --- drivers/gpu/drm/vc4/vc4_gem.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index b65b3f62b098..b61f9b0a7c09 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -908,24 +908,19 @@ vc4_exec_put(struct vc4_exec_info *exec) void vc4_job_handle_completed(struct vc4_dev *vc4) { - unsigned long irqflags; + struct vc4_exec_info *exec, *next; + LIST_HEAD(done); if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) return; - spin_lock_irqsave(&vc4->job_lock, irqflags); - while (!list_empty(&vc4->job_done_list)) { - struct vc4_exec_info *exec = - list_first_entry(&vc4->job_done_list, - struct vc4_exec_info, head); + scoped_guard(spinlock_irqsave, &vc4->job_lock) + list_splice_init(&vc4->job_done_list, &done); + + list_for_each_entry_safe(exec, next, &done, head) { list_del(&exec->head); - - spin_unlock_irqrestore(&vc4->job_lock, irqflags); vc4_exec_put(exec); - spin_lock_irqsave(&vc4->job_lock, irqflags); } - - spin_unlock_irqrestore(&vc4->job_lock, irqflags); } /* Scheduled when any job has been completed, this walks the list of -- 2.55.0
