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>
This commit is contained in:
parent
1f9861ad38
commit
3c6964a08c
1 changed files with 15 additions and 3 deletions
|
@ -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 *irq_obj = &sde_kms->irq_obj;
|
||||||
struct sde_irq_callback *cb;
|
struct sde_irq_callback *cb;
|
||||||
unsigned long irq_flags;
|
unsigned long irq_flags;
|
||||||
|
bool cb_tbl_error = false;
|
||||||
|
int enable_counts = 0;
|
||||||
|
|
||||||
pr_debug("irq_idx=%d\n", irq_idx);
|
pr_debug("irq_idx=%d\n", irq_idx);
|
||||||
|
|
||||||
if (list_empty(&irq_obj->irq_cb_tbl[irq_idx]))
|
spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags);
|
||||||
SDE_ERROR("irq_idx=%d has no registered callback\n", irq_idx);
|
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]);
|
atomic_inc(&irq_obj->irq_counts[irq_idx]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform registered function callback
|
* 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)
|
list_for_each_entry(cb, &irq_obj->irq_cb_tbl[irq_idx], list)
|
||||||
if (cb->func)
|
if (cb->func)
|
||||||
cb->func(cb->arg, irq_idx);
|
cb->func(cb->arg, irq_idx);
|
||||||
spin_unlock_irqrestore(&sde_kms->irq_obj.cb_lock, irq_flags);
|
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.
|
* Clear pending interrupt status in HW.
|
||||||
* NOTE: sde_core_irq_callback_handler is protected by top-level
|
* NOTE: sde_core_irq_callback_handler is protected by top-level
|
||||||
|
|
Loading…
Add table
Reference in a new issue