瀏覽代碼

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
Venkateswara Swamy Bandaru 7 年之前
父節點
當前提交
9b8dcb46d9
共有 3 個文件被更改,包括 19 次插入4 次删除
  1. 3 0
      hif/src/hif_exec.c
  2. 2 0
      hif/src/hif_exec.h
  3. 14 4
      hif/src/snoc/if_ahb.c

+ 3 - 0
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);
 }

+ 2 - 0
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;
 };
 
 /**

+ 14 - 4
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);
 }