From 77f3c438f0776185a35662eaa14bf41319ddbc92 Mon Sep 17 00:00:00 2001 From: Sathish Kumar Date: Fri, 20 Apr 2018 16:14:43 +0530 Subject: [PATCH] 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 --- target_if/core/src/target_if_main.c | 1 + .../src/target_if_direct_buf_rx_main.c | 22 +++++++++++-------- .../init_deinit/inc/service_ready_util.h | 11 ++++++++++ .../init_deinit/src/service_ready_util.c | 14 ++++++++++++ 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/target_if/core/src/target_if_main.c b/target_if/core/src/target_if_main.c index 7d54f6911aa5..f77fae30721c 100644 --- a/target_if/core/src/target_if_main.c +++ b/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); diff --git a/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c b/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c index fa6efc3ba9a9..ea92307d139f 100644 --- a/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c +++ b/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; } diff --git a/target_if/init_deinit/inc/service_ready_util.h b/target_if/init_deinit/inc/service_ready_util.h index d19593b6a3be..3d1cb32c12d7 100644 --- a/target_if/init_deinit/inc/service_ready_util.h +++ b/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 diff --git a/target_if/init_deinit/src/service_ready_util.c b/target_if/init_deinit/src/service_ready_util.c index 2e4b6103a100..d9bbbc53acd2 100644 --- a/target_if/init_deinit/src/service_ready_util.c +++ b/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)