소스 검색

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 년 전
부모
커밋
909feab5a8
7개의 변경된 파일8개의 추가작업 그리고 1개의 파일을 삭제
  1. 1 0
      hif/src/ce/ce_main.c
  2. 2 1
      hif/src/ce/ce_tasklet.c
  3. 1 0
      hif/src/hif_main.h
  4. 1 0
      hif/src/ipcie/if_ipci.c
  5. 1 0
      hif/src/pcie/if_pci.c
  6. 1 0
      hif/src/snoc/if_ahb.c
  7. 1 0
      hif/src/snoc/if_snoc.c

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