From d1965c6ca89f36a4c0eaf8d68e7f9f1fea0a1e20 Mon Sep 17 00:00:00 2001 From: Yashwanth Date: Mon, 2 Mar 2020 23:42:36 +0530 Subject: [PATCH] disp: msm: sde: add cb func check before enabling irq Acquiring mutex lock after enabling irq might lead to deadlock if irq is dispatched immediately in some cases. This change moves callback func check for irq prior to enabling the irq line. Change-Id: Ie1622e1ade268e41e97bf6d7683fa0bd972bcb7c Signed-off-by: Yashwanth --- msm/sde/sde_core_irq.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/msm/sde/sde_core_irq.c b/msm/sde/sde_core_irq.c index f2dc66fa6f59..5ee1865be632 100644 --- a/msm/sde/sde_core_irq.c +++ b/msm/sde/sde_core_irq.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ @@ -115,24 +115,26 @@ static int _sde_core_irq_enable(struct sde_kms *sde_kms, int irq_idx) SDE_EVT32(irq_idx, atomic_read(&sde_kms->irq_obj.enable_counts[irq_idx])); - spin_lock_irqsave(&sde_kms->hw_intr->irq_lock, irq_flags); - if (atomic_inc_return(&sde_kms->irq_obj.enable_counts[irq_idx]) == 1) + + if (atomic_inc_return(&sde_kms->irq_obj.enable_counts[irq_idx]) == 1) { + spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags); + /* empty callback list but interrupt is being enabled */ + if (list_empty(&sde_kms->irq_obj.irq_cb_tbl[irq_idx])) + SDE_ERROR("enabling irq_idx=%d with no callback\n", + irq_idx); + spin_unlock_irqrestore(&sde_kms->irq_obj.cb_lock, irq_flags); + + spin_lock_irqsave(&sde_kms->hw_intr->irq_lock, irq_flags); ret = sde_kms->hw_intr->ops.enable_irq_nolock( sde_kms->hw_intr, irq_idx); - spin_unlock_irqrestore(&sde_kms->hw_intr->irq_lock, irq_flags); + spin_unlock_irqrestore(&sde_kms->hw_intr->irq_lock, irq_flags); + } + if (ret) SDE_ERROR("Fail to enable IRQ for irq_idx:%d\n", irq_idx); SDE_DEBUG("irq_idx=%d ret=%d\n", irq_idx, ret); - if (atomic_read(&sde_kms->irq_obj.enable_counts[irq_idx]) == 1) { - spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags); - /* empty callback list but interrupt is enabled */ - if (list_empty(&sde_kms->irq_obj.irq_cb_tbl[irq_idx])) - SDE_ERROR("irq_idx=%d enabled with no callback\n", - irq_idx); - spin_unlock_irqrestore(&sde_kms->irq_obj.cb_lock, irq_flags); - } return ret; }