Sfoglia il codice sorgente

qcacmn: Fix memory leaks in direct buffer receive(DBR) module

Module param capabilities stored per module per pdev and overall
target dbr ring capabilities allocated and stored during service ready
are not freed during detach.

Fix above mentioned memory leaks through below changes
1. Free module param capabilities allocated per pdev during ring deinit
2. Free DBR ring capabilities allocated during service ready event
   as part of target psoc info free.
3. Free DBR entries allocated per event received from target

Change-Id: I93d5126063d3fa0094e15d57a75f03cf63b3c494
CRs-Fixed: 2228428
Sathish Kumar 7 anni fa
parent
commit
77f3c438f0

+ 1 - 0
target_if/core/src/target_if_main.c

@@ -545,6 +545,7 @@ QDF_STATUS target_if_free_psoc_tgt_info(struct wlan_objmgr_psoc *psoc)
 		return QDF_STATUS_E_INVAL;
 	}
 	init_deinit_chainmask_table_free(ext_param);
+	init_deinit_dbr_ring_cap_free(tgt_psoc_info);
 
 	wlan_psoc_set_tgt_if_handle(psoc, NULL);
 

+ 13 - 9
target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c

@@ -204,6 +204,9 @@ QDF_STATUS target_if_direct_buf_rx_pdev_destroy_handler(
 	for (mod_idx = 0; mod_idx < num_modules; mod_idx++)
 		target_if_deinit_dbr_ring(pdev, dbr_pdev_obj, mod_idx);
 
+	qdf_mem_free(dbr_pdev_obj->dbr_mod_param);
+	dbr_pdev_obj->dbr_mod_param = NULL;
+
 	status = wlan_objmgr_pdev_component_obj_detach(pdev,
 					WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
 					dbr_pdev_obj);
@@ -845,6 +848,7 @@ static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn,
 			&dbr_rsp.dbr_entries[i]) != QDF_STATUS_SUCCESS) {
 			direct_buf_rx_err("Unable to extract DBR buf entry %d",
 					  i+1);
+			qdf_mem_free(dbr_rsp.dbr_entries);
 			wlan_objmgr_pdev_release_ref(pdev,
 						     WLAN_DIRECT_BUF_RX_ID);
 			return QDF_STATUS_E_FAILURE;
@@ -854,6 +858,7 @@ static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn,
 
 		if (QDF_IS_STATUS_ERROR(status)) {
 			direct_buf_rx_err("DBR data get failed");
+			qdf_mem_free(dbr_rsp.dbr_entries);
 			wlan_objmgr_pdev_release_ref(pdev,
 						     WLAN_DIRECT_BUF_RX_ID);
 			return QDF_STATUS_E_FAILURE;
@@ -871,12 +876,14 @@ static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn,
 						      dbr_data.vaddr, cookie);
 		if (QDF_IS_STATUS_ERROR(status)) {
 			direct_buf_rx_err("dir buf rx ring replenish failed");
+			qdf_mem_free(dbr_rsp.dbr_entries);
 			wlan_objmgr_pdev_release_ref(pdev,
 						     WLAN_DIRECT_BUF_RX_ID);
 			return QDF_STATUS_E_FAILURE;
 		}
 	}
 
+	qdf_mem_free(dbr_rsp.dbr_entries);
 	wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID);
 
 	return ret;
@@ -960,7 +967,7 @@ static QDF_STATUS target_if_dbr_deinit_srng(
 	direct_buf_rx_info("dbr buf pool %pK", dbr_buf_pool);
 	target_if_dbr_deinit_ring(pdev, mod_param);
 	qdf_mem_free(dbr_buf_pool);
-	dbr_buf_pool = NULL;
+	mod_param->dbr_buf_pool = NULL;
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -970,7 +977,6 @@ QDF_STATUS target_if_deinit_dbr_ring(struct wlan_objmgr_pdev *pdev,
 			enum DBR_MODULE mod_id)
 {
 	struct direct_buf_rx_module_param *mod_param;
-	struct direct_buf_rx_ring_cap *dbr_ring_cap;
 
 	direct_buf_rx_enter();
 	mod_param = &(dbr_pdev_obj->dbr_mod_param[mod_id]);
@@ -980,14 +986,12 @@ QDF_STATUS target_if_deinit_dbr_ring(struct wlan_objmgr_pdev *pdev,
 		return QDF_STATUS_E_FAILURE;
 	}
 	direct_buf_rx_info("mod_param %pK", mod_param);
-
-	dbr_ring_cap = mod_param->dbr_ring_cap;
-	direct_buf_rx_info("dbr_ring_cap %pK", dbr_ring_cap);
+	direct_buf_rx_info("dbr_ring_cap %pK", mod_param->dbr_ring_cap);
 	target_if_dbr_deinit_srng(pdev, mod_param);
-	qdf_mem_free(dbr_ring_cap);
-	dbr_ring_cap = NULL;
-	qdf_mem_free(mod_param);
-	mod_param = NULL;
+	qdf_mem_free(mod_param->dbr_ring_cap);
+	mod_param->dbr_ring_cap = NULL;
+	qdf_mem_free(mod_param->dbr_ring_cfg);
+	mod_param->dbr_ring_cfg = NULL;
 
 	return QDF_STATUS_SUCCESS;
 }

+ 11 - 0
target_if/init_deinit/inc/service_ready_util.h

@@ -157,6 +157,17 @@ int init_deinit_populate_dbr_ring_cap(struct wlan_objmgr_psoc *psoc,
 				void *handle, uint8_t *event,
 				struct tgt_info *info);
 
+/**
+ * init_deinit_dbr_ring_cap_free() - free dbr ring capability
+ * @tgt_psoc_info: target psoc info object
+ *
+ * API to free dbr ring capability
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS init_deinit_dbr_ring_cap_free(
+				struct target_psoc_info *tgt_psoc_info);
+
 /**
  * init_deinit_populate_phy_reg_cap() - populate phy reg capability
  * @psoc: PSOC object

+ 14 - 0
target_if/init_deinit/src/service_ready_util.c

@@ -287,6 +287,20 @@ free_and_return:
 	return qdf_status_to_os_return(status);
 }
 
+QDF_STATUS init_deinit_dbr_ring_cap_free(
+		struct target_psoc_info *tgt_psoc_info)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	if (tgt_psoc_info->info.dbr_ring_cap) {
+		qdf_mem_free(tgt_psoc_info->info.dbr_ring_cap);
+		tgt_psoc_info->info.dbr_ring_cap = NULL;
+	}
+
+	return status;
+}
+qdf_export_symbol(init_deinit_dbr_ring_cap_free);
+
 int init_deinit_populate_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
 				void *handle, uint8_t *event,
 				struct tgt_info *info, bool service_ready)