summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorLloyd Atkinson <latkinso@codeaurora.org>2017-09-18 16:51:24 -0400
committerLakshmi Narayana Kalavala <lkalaval@codeaurora.org>2018-03-16 17:26:21 -0700
commit3c6964a08c97236bf9a4938cf67becae4a0c5bf5 (patch)
tree36aea76415b8f69f823da504b14a7cc3f2d6fb01 /drivers/gpu/drm
parent1f9861ad386a36c435cf664c5a99e0e15de54c00 (diff)
drm/msm/sde: take irq callback lock before reading cb list
Take the callback spinlock before checking whether the callback table list is empty. This resolves a race condition where the callback list could be empty during the servicing of an interrupt. Change-Id: I8d59c0211526173ce98c8ca2dac36ec4743dc8f8 Signed-off-by: Lloyd Atkinson <latkinso@codeaurora.org> Signed-off-by: Lakshmi Narayana Kalavala <lkalaval@codeaurora.org>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/msm/sde/sde_core_irq.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_core_irq.c b/drivers/gpu/drm/msm/sde/sde_core_irq.c
index 83c8982b2e00..4f7e688650de 100644
--- a/drivers/gpu/drm/msm/sde/sde_core_irq.c
+++ b/drivers/gpu/drm/msm/sde/sde_core_irq.c
@@ -31,23 +31,35 @@ static void sde_core_irq_callback_handler(void *arg, int irq_idx)
struct sde_irq *irq_obj = &sde_kms->irq_obj;
struct sde_irq_callback *cb;
unsigned long irq_flags;
+ bool cb_tbl_error = false;
+ int enable_counts = 0;
pr_debug("irq_idx=%d\n", irq_idx);
- if (list_empty(&irq_obj->irq_cb_tbl[irq_idx]))
- SDE_ERROR("irq_idx=%d has no registered callback\n", irq_idx);
+ spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags);
+ if (list_empty(&irq_obj->irq_cb_tbl[irq_idx])) {
+ /* print error outside lock */
+ cb_tbl_error = true;
+ enable_counts = atomic_read(
+ &sde_kms->irq_obj.enable_counts[irq_idx]);
+ }
atomic_inc(&irq_obj->irq_counts[irq_idx]);
/*
* Perform registered function callback
*/
- spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags);
list_for_each_entry(cb, &irq_obj->irq_cb_tbl[irq_idx], list)
if (cb->func)
cb->func(cb->arg, irq_idx);
spin_unlock_irqrestore(&sde_kms->irq_obj.cb_lock, irq_flags);
+ if (cb_tbl_error) {
+ SDE_ERROR("irq has no registered callback, idx %d enables %d\n",
+ irq_idx, enable_counts);
+ SDE_EVT32_IRQ(irq_idx, enable_counts, SDE_EVTLOG_ERROR);
+ }
+
/*
* Clear pending interrupt status in HW.
* NOTE: sde_core_irq_callback_handler is protected by top-level