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
diff --git a/hif/src/hif_exec.c b/hif/src/hif_exec.c
index d1fc637..6ea83ec 100644
--- a/hif/src/hif_exec.c
+++ b/hif/src/hif_exec.c
@@ -278,6 +278,8 @@
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 @@
*/
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 5897a42..7334f17 100644
--- a/hif/src/hif_exec.h
+++ b/hif/src/hif_exec.h
@@ -69,6 +69,8 @@
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 3b17361..ea5ab63 100644
--- a/hif/src/snoc/if_ahb.c
+++ b/hif/src/snoc/if_ahb.c
@@ -687,17 +687,27 @@
{
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);
}