Эх сурвалжийг харах

qcacmn: Check irq free before enable

During deinit process we free the IRQs and call kill tasklet.
There is the possibility that Tasklet might be running when we
call kill tasklet and as part of tasklet exit it will try to
enable the corresponding CE IRQ which has already been freed.

Adding check for IRQ free condition to avoid any IRQ enable
calls after IRQ free is done.

Change-Id: I9d58ffbb3738251e3d8114631e2daacd07e33d7d
CRs-Fixed: 2973309
Amit Mehta 4 жил өмнө
parent
commit
909feab5a8

+ 1 - 0
hif/src/ce/ce_main.c

@@ -3768,6 +3768,7 @@ void hif_ce_prepare_config(struct hif_softc *scn)
 
 	scn->ce_count = HOST_CE_COUNT;
 	scn->int_assignment = &ce_int_context[msi_data_count];
+	scn->free_irq_done = false;
 	/* if epping is enabled we need to use the epping configuration. */
 	if (QDF_IS_EPPING_ENABLED(mode)) {
 		hif_ce_prepare_epping_config(scn, hif_state);

+ 2 - 1
hif/src/ce/ce_tasklet.c

@@ -442,7 +442,8 @@ static void ce_tasklet(unsigned long data)
 	if (scn->ce_latency_stats)
 		ce_tasklet_update_bucket(hif_ce_state, tasklet_entry->ce_id);
 
-	if (scn->target_status != TARGET_STATUS_RESET)
+	if ((scn->target_status != TARGET_STATUS_RESET) &&
+	    !scn->free_irq_done)
 		hif_irq_enable(scn, tasklet_entry->ce_id);
 
 	qdf_atomic_dec(&scn->active_tasklet_cnt);

+ 1 - 0
hif/src/hif_main.h

@@ -217,6 +217,7 @@ struct hif_softc {
 	bool hif_init_done;
 	bool request_irq_done;
 	bool ext_grp_irq_configured;
+	bool free_irq_done;
 	uint8_t ce_latency_stats;
 	/* Packet statistics */
 	struct hif_ce_stats pkt_stats;

+ 1 - 0
hif/src/ipcie/if_ipci.c

@@ -252,6 +252,7 @@ void hif_ipci_nointrs(struct hif_softc *scn)
 	int ret;
 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
 
+	scn->free_irq_done = true;
 	ce_unregister_irq(hif_state, CE_ALL_BITMAP);
 
 	if (scn->request_irq_done == false)

+ 1 - 0
hif/src/pcie/if_pci.c

@@ -2046,6 +2046,7 @@ void hif_pci_nointrs(struct hif_softc *scn)
 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
 
+	scn->free_irq_done = true;
 	ce_unregister_irq(hif_state, CE_ALL_BITMAP);
 
 	if (scn->request_irq_done == false)

+ 1 - 0
hif/src/snoc/if_ahb.c

@@ -732,6 +732,7 @@ void hif_ahb_nointrs(struct hif_softc *scn)
 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
 	struct CE_attr *host_ce_conf = hif_state->host_ce_config;
 
+	scn->free_irq_done = true;
 	ce_unregister_irq(hif_state, CE_ALL_BITMAP);
 
 	if (scn->request_irq_done == false)

+ 1 - 0
hif/src/snoc/if_snoc.c

@@ -340,6 +340,7 @@ void hif_snoc_nointrs(struct hif_softc *scn)
 {
 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
 
+	scn->free_irq_done = true;
 	ce_unregister_irq(hif_state, CE_ALL_BITMAP);
 }