qcacmn: Fix for crash during unload of driver modules

Cleanup usage of irq_request_done flag. This flag is
set after registering irq. Irq register is skipped for emulation.
Setting this flag here causes detach path to release
irq even though it was not registered. Add new bitmap
ce_register_irq_done to track CE irqs.

Change-Id: I84cb4463b8ad51f22cb17c55dab36a398ccbaef0
CRs-Fixed: 1097695
diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c
index 5a960c1..74f0bf5 100644
--- a/hif/src/ce/ce_main.c
+++ b/hif/src/ce/ce_main.c
@@ -2178,7 +2178,6 @@
 		pipe_info = &hif_state->pipe_info[pipe_num];
 		if (pipe_info->ce_hdl) {
 			ce_unregister_irq(hif_state, (1 << pipe_num));
-			hif_sc->request_irq_done = false;
 			ce_fini(pipe_info->ce_hdl);
 			pipe_info->ce_hdl = NULL;
 			pipe_info->buf_sz = 0;
@@ -2305,7 +2304,6 @@
 		}
 		ce_tasklet_init(hif_state, (1 << pipe_num));
 		ce_register_irq(hif_state, (1 << pipe_num));
-		scn->request_irq_done = true;
 	}
 
 	if (athdiag_procfs_init(scn) != 0) {
diff --git a/hif/src/ce/ce_main.h b/hif/src/ce/ce_main.h
index 9549ea2..4b416cc 100644
--- a/hif/src/ce/ce_main.h
+++ b/hif/src/ce/ce_main.h
@@ -144,6 +144,7 @@
 	qdf_timer_t sleep_timer;
 	bool sleep_timer_init;
 	qdf_time_t sleep_ticks;
+	uint32_t ce_register_irq_done;
 
 	struct CE_pipe_config *target_ce_config;
 	struct CE_attr *host_ce_config;
diff --git a/hif/src/ce/ce_tasklet.c b/hif/src/ce/ce_tasklet.c
index 52595f2..ef13e4e 100644
--- a/hif/src/ce/ce_tasklet.c
+++ b/hif/src/ce/ce_tasklet.c
@@ -557,6 +557,8 @@
 			  __func__, ret);
 	/* this is not fatal, continue */
 
+	/* filter mask to free only for ce's with irq registered */
+	mask &= hif_ce_state->ce_register_irq_done;
 	for (id = 0; id < ce_count; id++) {
 		if ((mask & (1 << id)) && hif_ce_state->tasklets[id].inited) {
 			ret = pld_ce_free_irq(scn->qdf_dev->dev, id,
@@ -567,6 +569,8 @@
 					__func__, id, ret);
 		}
 	}
+	hif_ce_state->ce_register_irq_done &= ~mask;
+
 	return QDF_STATUS_SUCCESS;
 }
 /**
@@ -607,6 +611,7 @@
 			}
 		}
 	}
+	hif_ce_state->ce_register_irq_done |= done_mask;
 
 	return QDF_STATUS_SUCCESS;
 }
diff --git a/hif/src/pcie/if_pci.c b/hif/src/pcie/if_pci.c
index 2ab29b6..d5dd28c 100644
--- a/hif/src/pcie/if_pci.c
+++ b/hif/src/pcie/if_pci.c
@@ -2593,6 +2593,8 @@
 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
 
+	ce_unregister_irq(hif_state, CE_ALL_BITMAP);
+
 	if (scn->request_irq_done == false)
 		return;
 
@@ -2609,8 +2611,8 @@
 		platform_device pdev doesn't have an irq field */
 		free_irq(sc->irq, sc);
 	}
-	ce_unregister_irq(hif_state, 0xfff);
 	scn->request_irq_done = false;
+
 }
 
 /**
diff --git a/hif/src/snoc/if_ahb.c b/hif/src/snoc/if_ahb.c
index 7dc95b8..a137c1e 100644
--- a/hif/src/snoc/if_ahb.c
+++ b/hif/src/snoc/if_ahb.c
@@ -557,6 +557,8 @@
 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
 
+	ce_unregister_irq(hif_state, CE_ALL_BITMAP);
+
 	if (scn->request_irq_done == false)
 		return;
 
@@ -576,8 +578,8 @@
 			}
 		}
 	}
-	ce_unregister_irq(hif_state, CE_ALL_BITMAP);
 	scn->request_irq_done = false;
+
 }
 
 /**
diff --git a/hif/src/snoc/if_snoc.c b/hif/src/snoc/if_snoc.c
index 22103d4..3b5e0f6 100644
--- a/hif/src/snoc/if_snoc.c
+++ b/hif/src/snoc/if_snoc.c
@@ -309,10 +309,8 @@
 void hif_snoc_nointrs(struct hif_softc *scn)
 {
 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
-	if (scn->request_irq_done) {
-		ce_unregister_irq(hif_state, 0xfff);
-		scn->request_irq_done = false;
-	}
+
+	ce_unregister_irq(hif_state, CE_ALL_BITMAP);
 }
 
 /**