From 9b8dcb46d9b0e6f03d7560d506bb189394374be0 Mon Sep 17 00:00:00 2001 From: Venkateswara Swamy Bandaru Date: Tue, 8 Aug 2017 18:13:15 +0530 Subject: [PATCH] qcacmn: Fix race condition issue with enabling interrupts Add lock before disabling and enabling group interrups to avoid race condition between enabling and disabling group interrupts. Avoid mutiple enabling/disabling of interrupts by maintaining the irq enabled information. Change-Id: I79afc987e3853de84aaa05321cfcee72cdc0acb0 CRs-Fixed: 2087792 --- hif/src/hif_exec.c | 3 +++ hif/src/hif_exec.h | 2 ++ hif/src/snoc/if_ahb.c | 18 ++++++++++++++---- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/hif/src/hif_exec.c b/hif/src/hif_exec.c index d1fc6379b44b..6ea83ec4df90 100644 --- a/hif/src/hif_exec.c +++ b/hif/src/hif_exec.c @@ -278,6 +278,8 @@ uint32_t hif_configure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx) status = hif_grp_irq_configure(scn, hif_ext_group); if (status != 0) HIF_ERROR("%s: failed for group %d", __func__, i); + qdf_spinlock_create(&hif_ext_group->irq_lock); + hif_ext_group->irq_enabled = true; } scn->ext_grp_irq_configured = true; @@ -405,5 +407,6 @@ struct hif_exec_context *hif_exec_create(enum hif_exec_type type) */ void hif_exec_destroy(struct hif_exec_context *ctx) { + qdf_spinlock_destroy(&ctx->irq_lock); qdf_mem_free(ctx); } diff --git a/hif/src/hif_exec.h b/hif/src/hif_exec.h index 5897a4295edb..7334f17e23cf 100644 --- a/hif/src/hif_exec.h +++ b/hif/src/hif_exec.h @@ -69,6 +69,8 @@ struct hif_exec_context { bool inited; bool configured; bool irq_requested; + bool irq_enabled; + qdf_spinlock_t irq_lock; }; /** diff --git a/hif/src/snoc/if_ahb.c b/hif/src/snoc/if_ahb.c index 3b17361a1790..ea5ab63060dd 100644 --- a/hif/src/snoc/if_ahb.c +++ b/hif/src/snoc/if_ahb.c @@ -687,17 +687,27 @@ void hif_ahb_exec_grp_irq_disable(struct hif_exec_context *hif_ext_group) { int i; - for (i = 0; i < hif_ext_group->numirq; i++) { - disable_irq_nosync(hif_ext_group->os_irq[i]); + qdf_spin_lock_irqsave(&hif_ext_group->irq_lock); + if (hif_ext_group->irq_enabled) { + for (i = 0; i < hif_ext_group->numirq; i++) { + disable_irq_nosync(hif_ext_group->os_irq[i]); + } + hif_ext_group->irq_enabled = false; } + qdf_spin_unlock_irqrestore(&hif_ext_group->irq_lock); } void hif_ahb_exec_grp_irq_enable(struct hif_exec_context *hif_ext_group) { int i; - for (i = 0; i < hif_ext_group->numirq; i++) { - enable_irq(hif_ext_group->os_irq[i]); + qdf_spin_lock_irqsave(&hif_ext_group->irq_lock); + if (!hif_ext_group->irq_enabled) { + for (i = 0; i < hif_ext_group->numirq; i++) { + enable_irq(hif_ext_group->os_irq[i]); + } + hif_ext_group->irq_enabled = true; } + qdf_spin_unlock_irqrestore(&hif_ext_group->irq_lock); }