Przeglądaj źródła

qcacmn: Fix a memory leak during soc attach

hif_ext_group and soc->intr_ctx[i].lro_ctx are allocated
but not free while fail to register parts of ext_group in
hif_register_ext_group, which cause memory leak. Fix is
to detach according resource before return.

Change-Id: I03ecc37437d09bf9275f128b1f2b320124a7df64
CRs-Fixed: 2988891
lihual 4 lat temu
rodzic
commit
bde0001eed
2 zmienionych plików z 47 dodań i 44 usunięć
  1. 43 43
      dp/wifi3.0/dp_main.c
  2. 4 1
      hif/src/hif_exec.c

+ 43 - 43
dp/wifi3.0/dp_main.c

@@ -2913,6 +2913,48 @@ dp_soc_near_full_interrupt_attach(struct dp_soc *soc, int num_irq,
 }
 #endif
 
+/*
+ * dp_soc_interrupt_detach() - Deregister any allocations done for interrupts
+ * @txrx_soc: DP SOC handle
+ *
+ * Return: none
+ */
+static void dp_soc_interrupt_detach(struct cdp_soc_t *txrx_soc)
+{
+	struct dp_soc *soc = (struct dp_soc *)txrx_soc;
+	int i;
+
+	if (soc->intr_mode == DP_INTR_POLL) {
+		qdf_timer_free(&soc->int_timer);
+	} else {
+		hif_deconfigure_ext_group_interrupts(soc->hif_handle);
+		hif_deregister_exec_group(soc->hif_handle, "dp_intr");
+		hif_deregister_exec_group(soc->hif_handle, "dp_nf_intr");
+	}
+
+	for (i = 0; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++) {
+		soc->intr_ctx[i].tx_ring_mask = 0;
+		soc->intr_ctx[i].rx_ring_mask = 0;
+		soc->intr_ctx[i].rx_mon_ring_mask = 0;
+		soc->intr_ctx[i].rx_err_ring_mask = 0;
+		soc->intr_ctx[i].rx_wbm_rel_ring_mask = 0;
+		soc->intr_ctx[i].reo_status_ring_mask = 0;
+		soc->intr_ctx[i].rxdma2host_ring_mask = 0;
+		soc->intr_ctx[i].host2rxdma_ring_mask = 0;
+		soc->intr_ctx[i].host2rxdma_mon_ring_mask = 0;
+		soc->intr_ctx[i].rx_near_full_grp_1_mask = 0;
+		soc->intr_ctx[i].rx_near_full_grp_2_mask = 0;
+		soc->intr_ctx[i].tx_ring_near_full_mask = 0;
+
+		hif_event_history_deinit(soc->hif_handle, i);
+		qdf_lro_deinit(soc->intr_ctx[i].lro_ctx);
+	}
+
+	qdf_mem_set(&soc->mon_intr_id_lmac_map,
+		    sizeof(soc->mon_intr_id_lmac_map),
+		    DP_MON_INVALID_LMAC_ID);
+}
+
 /*
  * dp_soc_interrupt_attach() - Register handlers for DP interrupts
  * @txrx_soc: DP SOC handle
@@ -3011,7 +3053,7 @@ static QDF_STATUS dp_soc_interrupt_attach(struct cdp_soc_t *txrx_soc)
 
 		if (ret) {
 			dp_init_err("%pK: failed, ret = %d", soc, ret);
-
+			dp_soc_interrupt_detach(txrx_soc);
 			return QDF_STATUS_E_FAILURE;
 		}
 
@@ -3030,48 +3072,6 @@ static QDF_STATUS dp_soc_interrupt_attach(struct cdp_soc_t *txrx_soc)
 	return QDF_STATUS_SUCCESS;
 }
 
-/*
- * dp_soc_interrupt_detach() - Deregister any allocations done for interrupts
- * @txrx_soc: DP SOC handle
- *
- * Return: none
- */
-static void dp_soc_interrupt_detach(struct cdp_soc_t *txrx_soc)
-{
-	struct dp_soc *soc = (struct dp_soc *)txrx_soc;
-	int i;
-
-	if (soc->intr_mode == DP_INTR_POLL) {
-		qdf_timer_free(&soc->int_timer);
-	} else {
-		hif_deconfigure_ext_group_interrupts(soc->hif_handle);
-		hif_deregister_exec_group(soc->hif_handle, "dp_intr");
-		hif_deregister_exec_group(soc->hif_handle, "dp_nf_intr");
-	}
-
-	for (i = 0; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++) {
-		soc->intr_ctx[i].tx_ring_mask = 0;
-		soc->intr_ctx[i].rx_ring_mask = 0;
-		soc->intr_ctx[i].rx_mon_ring_mask = 0;
-		soc->intr_ctx[i].rx_err_ring_mask = 0;
-		soc->intr_ctx[i].rx_wbm_rel_ring_mask = 0;
-		soc->intr_ctx[i].reo_status_ring_mask = 0;
-		soc->intr_ctx[i].rxdma2host_ring_mask = 0;
-		soc->intr_ctx[i].host2rxdma_ring_mask = 0;
-		soc->intr_ctx[i].host2rxdma_mon_ring_mask = 0;
-		soc->intr_ctx[i].rx_near_full_grp_1_mask = 0;
-		soc->intr_ctx[i].rx_near_full_grp_2_mask = 0;
-		soc->intr_ctx[i].tx_ring_near_full_mask = 0;
-
-		hif_event_history_deinit(soc->hif_handle, i);
-		qdf_lro_deinit(soc->intr_ctx[i].lro_ctx);
-	}
-
-	qdf_mem_set(&soc->mon_intr_id_lmac_map,
-		    sizeof(soc->mon_intr_id_lmac_map),
-		    DP_MON_INVALID_LMAC_ID);
-}
-
 #define AVG_MAX_MPDUS_PER_TID 128
 #define AVG_TIDS_PER_CLIENT 2
 #define AVG_FLOWS_PER_TID 2

+ 4 - 1
hif/src/hif_exec.c

@@ -1044,7 +1044,10 @@ 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);
+	struct hif_softc *scn = HIF_GET_SOFTC(ctx->hif);
+
+	if (scn->ext_grp_irq_configured)
+		qdf_spinlock_destroy(&ctx->irq_lock);
 	qdf_mem_free(ctx);
 }