vc4_queue_submit() calls drm_exec_fini() with job_lock held and interrupts
disabled. Besides unlocking the reservations, drm_exec_fini() frees the
object array with kvfree(), which asks for preemptible task context or a
non-NMI interrupt, and may reach might_sleep() through vfree().

Considering that an array that exceeds a page can take the vmalloc
fallback, call drm_exec_fini() once job_lock is dropped. The reservations
are then held across the job kick, which is harmless as nothing in the
completion path takes a BO reservation.

Note that vc4_attach_fences() has to stay inside the critical section, as
it walks exec, which the job done worker is free to release as soon as
job_lock is dropped.

Fixes: 04630796c437 ("drm/vc4: Use DRM Execution Contexts")
Signed-off-by: Maíra Canal <[email protected]>
---
 drivers/gpu/drm/vc4/vc4_gem.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
index f4be154d4eb0..0fef9b48d3c6 100644
--- a/drivers/gpu/drm/vc4/vc4_gem.c
+++ b/drivers/gpu/drm/vc4/vc4_gem.c
@@ -647,8 +647,6 @@ vc4_queue_submit(struct drm_device *dev, struct 
vc4_exec_info *exec,
 
        vc4_attach_fences(exec);
 
-       drm_exec_fini(exec_ctx);
-
        list_add_tail(&exec->head, &vc4->bin_job_list);
 
        /* If no bin job was executing and if the render job (if any) has the
@@ -665,6 +663,8 @@ vc4_queue_submit(struct drm_device *dev, struct 
vc4_exec_info *exec,
 
        spin_unlock_irqrestore(&vc4->job_lock, irqflags);
 
+       drm_exec_fini(exec_ctx);
+
        if (out_sync) {
                drm_syncobj_replace_fence(out_sync, &fence->base);
                dma_fence_put(&fence->base);

-- 
2.55.0

Reply via email to