From 08b3ab10cc1c4caac73dbef159ba8c8f00c21cf8 Mon Sep 17 00:00:00 2001 From: "hyesoo.yu" Date: Tue, 20 Jun 2017 15:13:28 +0900 Subject: [PATCH] [COMMON] g2d: fix spinlock lockup for fence 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 --- drivers/gpu/exynos/g2d/g2d_fence.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/exynos/g2d/g2d_fence.c b/drivers/gpu/exynos/g2d/g2d_fence.c index cba020fda6a0..1cedcc167e66 100644 --- a/drivers/gpu/exynos/g2d/g2d_fence.c +++ b/drivers/gpu/exynos/g2d/g2d_fence.c @@ -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) -- 2.20.1