From 48aac96d6164a3d2af8547729d611eca9e96c2ca Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Mon, 12 Oct 2020 12:21:15 +0530 Subject: [PATCH] qcacmn: Free mem leak in qmi bypass mode QMI bypass mode uses 2mb of of mem region for fw uses. Current implementation does not free this memory region when qmi bypass mode in enabled. Free mem leak in qmi bypass mode. Change-Id: Ie11aa9f20f93183e0b999cd6578aea4b231f8d8b --- hif/src/ce/ce_main.c | 77 +++++++++++++++++++++++++++++++++++--------- hif/src/hif_main.c | 1 + hif/src/hif_main.h | 5 +++ 3 files changed, 68 insertions(+), 15 deletions(-) diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c index 7549ff38b805..ddc5ba662b91 100644 --- a/hif/src/ce/ce_main.c +++ b/hif/src/ce/ce_main.c @@ -3441,7 +3441,6 @@ void hif_unconfig_ce(struct hif_softc *hif_sc) */ static void hif_post_static_buf_to_target(struct hif_softc *scn) { - void *target_va; phys_addr_t target_pa; struct ce_info *ce_info_ptr; uint32_t msi_data_start; @@ -3450,15 +3449,19 @@ static void hif_post_static_buf_to_target(struct hif_softc *scn) uint32_t i = 0; int ret; - target_va = qdf_mem_alloc_consistent(scn->qdf_dev, - scn->qdf_dev->dev, - FW_SHARED_MEM + - sizeof(struct ce_info), - &target_pa); - if (!target_va) + scn->vaddr_qmi_bypass = + (uint32_t *)qdf_mem_alloc_consistent(scn->qdf_dev, + scn->qdf_dev->dev, + FW_SHARED_MEM, + &target_pa); + if (!scn->vaddr_qmi_bypass) { + hif_err("Memory allocation failed could not post target buf"); return; + } - ce_info_ptr = (struct ce_info *)target_va; + scn->paddr_qmi_bypass = target_pa; + + ce_info_ptr = (struct ce_info *)scn->vaddr_qmi_bypass; if (scn->vaddr_rri_on_ddr) { ce_info_ptr->rri_over_ddr_low_paddr = @@ -3482,7 +3485,26 @@ static void hif_post_static_buf_to_target(struct hif_softc *scn) } hif_write32_mb(scn, scn->mem + BYPASS_QMI_TEMP_REGISTER, target_pa); - hif_info("target va %pK target pa %pa", target_va, &target_pa); + hif_info("target va %pK target pa %pa", scn->vaddr_qmi_bypass, + &target_pa); +} + +/** + * hif_cleanup_static_buf_to_target() - clean up static buffer to WLAN FW + * @scn: pointer to HIF structure + * + * + * Return: void + */ +void hif_cleanup_static_buf_to_target(struct hif_softc *scn) +{ + void *target_va = scn->vaddr_qmi_bypass; + phys_addr_t target_pa = scn->paddr_qmi_bypass; + + qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev, + FW_SHARED_MEM, target_va, + target_pa, 0); + hif_write32_mb(scn, scn->mem + BYPASS_QMI_TEMP_REGISTER, 0); } #else /** @@ -3495,17 +3517,38 @@ static void hif_post_static_buf_to_target(struct hif_softc *scn) */ static void hif_post_static_buf_to_target(struct hif_softc *scn) { - void *target_va; - phys_addr_t target_pa; + qdf_dma_addr_t target_pa; - target_va = qdf_mem_alloc_consistent(scn->qdf_dev, scn->qdf_dev->dev, - FW_SHARED_MEM, &target_pa); - if (!target_va) { + scn->vaddr_qmi_bypass = + (uint32_t *)qdf_mem_alloc_consistent(scn->qdf_dev, + scn->qdf_dev->dev, + FW_SHARED_MEM, + &target_pa); + if (!scn->vaddr_qmi_bypass) { hif_err("Memory allocation failed could not post target buf"); return; } + + scn->paddr_qmi_bypass = target_pa; hif_write32_mb(scn, scn->mem + BYPASS_QMI_TEMP_REGISTER, target_pa); - hif_info("target va %pK target pa %pa", target_va, &target_pa); +} + +/** + * hif_cleanup_static_buf_to_target() - clean up static buffer to WLAN FW + * @scn: pointer to HIF structure + * + * + * Return: void + */ +void hif_cleanup_static_buf_to_target(struct hif_softc *scn) +{ + void *target_va = scn->vaddr_qmi_bypass; + phys_addr_t target_pa = scn->paddr_qmi_bypass; + + qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev, + FW_SHARED_MEM, target_va, + target_pa, 0); + hif_write32_mb(snc, scn->mem + BYPASS_QMI_TEMP_REGISTER, 0); } #endif @@ -3513,6 +3556,10 @@ static void hif_post_static_buf_to_target(struct hif_softc *scn) static inline void hif_post_static_buf_to_target(struct hif_softc *scn) { } + +void hif_cleanup_static_buf_to_target(struct hif_softc *scn) +{ +} #endif static int hif_srng_sleep_state_adjust(struct hif_softc *scn, bool sleep_ok, diff --git a/hif/src/hif_main.c b/hif/src/hif_main.c index 2ef4ab6ebb7d..f25b49d67e9b 100644 --- a/hif/src/hif_main.c +++ b/hif/src/hif_main.c @@ -725,6 +725,7 @@ void hif_close(struct hif_opaque_softc *hif_ctx) } hif_uninit_rri_on_ddr(scn); + hif_cleanup_static_buf_to_target(scn); hif_cpuhp_unregister(scn); hif_bus_close(scn); diff --git a/hif/src/hif_main.h b/hif/src/hif_main.h index 94512a4dbbab..8ad42f65e271 100644 --- a/hif/src/hif_main.h +++ b/hif/src/hif_main.h @@ -204,6 +204,10 @@ struct hif_softc { atomic_t link_suspended; uint32_t *vaddr_rri_on_ddr; qdf_dma_addr_t paddr_rri_on_ddr; +#ifdef CONFIG_BYPASS_QMI + uint32_t *vaddr_qmi_bypass; + qdf_dma_addr_t paddr_qmi_bypass; +#endif int linkstate_vote; bool fastpath_mode_on; atomic_t tasklet_from_intr; @@ -464,4 +468,5 @@ void hif_uninit_rri_on_ddr(struct hif_softc *scn); static inline void hif_uninit_rri_on_ddr(struct hif_softc *scn) {} #endif +void hif_cleanup_static_buf_to_target(struct hif_softc *scn); #endif /* __HIF_MAIN_H__ */