[COMMON] g2d: fix spinlock lockup for fence
authorhyesoo.yu <hyesoo.yu@samsung.com>
Tue, 20 Jun 2017 06:13:28 +0000 (15:13 +0900)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:22:13 +0000 (20:22 +0300)
CPU1 CPU2
spin_lock_irqsave(task->fence_timeout_lock)

fence_signal_locked() /* called with fence->lock held */
g2d_fence_callback()
spin_lock_irqsave(task->fence_timeout_lock)
g2d_fence_timeout_handler()
fence_remove_callback()
spin_lock_irqsave(fence->lock)

On the above condition, two spinlock are deadlocked.

So, move fence_remove_callback() from fence_timeout_lock section.

Change-Id: If023ac94c2130ec0320814f3f2dc638c0031e761
Signed-off-by: hyesoo.yu <hyesoo.yu@samsung.com>
drivers/gpu/exynos/g2d/g2d_fence.c

index cba020fda6a0559aafada8e13f9441343ddca790..1cedcc167e669b07a6a89e4f7e8cdb0340d4bbeb 100644 (file)
@@ -90,6 +90,11 @@ void g2d_fence_timeout_handler(unsigned long arg)
                atomic_read(&task->starter.refcount.refs),
                G2D_FENCE_TIMEOUT_MSEC);
 
+       /* Increase reference to prevent running the workqueue in callback */
+       kref_get(&task->starter);
+
+       spin_unlock_irqrestore(&task->fence_timeout_lock, flags);
+
        for (i = 0; i < task->num_source; i++) {
                fence = task->source[i].fence;
                if (fence)
@@ -101,14 +106,9 @@ void g2d_fence_timeout_handler(unsigned long arg)
        if (fence)
                dma_fence_remove_callback(fence, &task->target.fence_cb);
 
-       /* Increase reference to prevent running the workqueue in callback */
-       kref_get(&task->starter);
+       g2d_stamp_task(task, G2D_STAMP_STATE_TIMEOUT_FENCE);
 
        g2d_queuework_task(&task->starter);
-
-       spin_unlock_irqrestore(&task->fence_timeout_lock, flags);
-
-       g2d_stamp_task(task, G2D_STAMP_STATE_TIMEOUT_FENCE);
 };
 
 static const char *g2d_fence_get_driver_name(struct dma_fence *fence)