From ae6c777bd1246b8553be1af2dd8d4e90f44b9273 Mon Sep 17 00:00:00 2001 From: Jiachao Wu Date: Mon, 23 Oct 2017 14:41:19 +0800 Subject: [PATCH] qcacmn: Fix a memory leak in qdf_mem_shared_mem_alloc qdf_mem_shared_mem_alloc invokes qdf_mem_dma_get_sgtable which will alloc memory. This memory should be free in qdf_mem_shared_mem_free by sg_free_table. Change-Id: I3ad4bd2ff7a80d4051f15dcb04e0265707c2712d CRs-Fixed: 2131270 --- qdf/inc/qdf_mem.h | 59 +++++++++++---------------------------- qdf/linux/src/i_qdf_mem.h | 14 +++++++++- qdf/linux/src/qdf_mem.c | 50 +++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 44 deletions(-) diff --git a/qdf/inc/qdf_mem.h b/qdf/inc/qdf_mem.h index ca0542d626..8541789c81 100644 --- a/qdf/inc/qdf_mem.h +++ b/qdf/inc/qdf_mem.h @@ -568,11 +568,23 @@ qdf_mem_dma_get_sgtable(struct device *dev, void *sgt, void *cpu_addr, return __qdf_os_mem_dma_get_sgtable(dev, sgt, cpu_addr, dma_addr, size); } +/** + * qdf_mem_free_sgtable() - Free a previously allocated sg table + * @sgt: the mapped sg table header + * + * Return: None + */ +static inline void +qdf_mem_free_sgtable(struct sg_table *sgt) +{ + __qdf_os_mem_free_sgtable(sgt); +} + /** * qdf_dma_get_sgtable_dma_addr() - Assigns DMA address to scatterlist elements * @sgt: scatter gather table pointer * - * @Return: None + * Return: None */ static inline void qdf_dma_get_sgtable_dma_addr(struct sg_table *sgt) @@ -683,49 +695,9 @@ qdf_mem_set_dma_pa(qdf_device_t osdev, * Allocate DMA memory which will be shared with external kernel module. This * information is needed for SMMU mapping. * - * Return: 0 suceess + * Return: 0 success */ -static inline qdf_shared_mem_t *qdf_mem_shared_mem_alloc(qdf_device_t osdev, - uint32_t size) -{ - qdf_shared_mem_t *shared_mem; - - shared_mem = qdf_mem_malloc(sizeof(*shared_mem)); - if (!shared_mem) { - __qdf_print("%s: Unable to allocate memory for shared resource struct\n", - __func__); - return NULL; - } - - shared_mem->vaddr = qdf_mem_alloc_consistent(osdev, osdev->dev, - size, qdf_mem_get_dma_addr_ptr(osdev, - &shared_mem->mem_info)); - if (!shared_mem->vaddr) { - __qdf_print("%s; Unable to allocate DMA memory for shared resource\n", - __func__); - qdf_mem_free(shared_mem); - return NULL; - } - - qdf_mem_set_dma_size(osdev, &shared_mem->mem_info, size); - qdf_mem_zero(shared_mem->vaddr, - qdf_mem_get_dma_size(osdev, &shared_mem->mem_info)); - qdf_mem_set_dma_pa(osdev, &shared_mem->mem_info, - qdf_mem_paddr_from_dmaaddr(osdev, - qdf_mem_get_dma_addr(osdev, - &shared_mem->mem_info))); - qdf_mem_dma_get_sgtable(osdev->dev, - (void *)&shared_mem->sgtable, - shared_mem->vaddr, - qdf_mem_get_dma_addr(osdev, - &shared_mem->mem_info), - qdf_mem_get_dma_size(osdev, - &shared_mem->mem_info)); - - qdf_dma_get_sgtable_dma_addr(&shared_mem->sgtable); - - return shared_mem; -} +qdf_shared_mem_t *qdf_mem_shared_mem_alloc(qdf_device_t osdev, uint32_t size); /** * qdf_mem_shared_mem_free() - Free shared memory @@ -755,6 +727,7 @@ static inline void qdf_mem_shared_mem_free(qdf_device_t osdev, qdf_get_dma_mem_context(shared_mem, memctx)); } + qdf_mem_free_sgtable(&shared_mem->sgtable); qdf_mem_free(shared_mem); } diff --git a/qdf/linux/src/i_qdf_mem.h b/qdf/linux/src/i_qdf_mem.h index 9c4772c2cc..21a92979b0 100644 --- a/qdf/linux/src/i_qdf_mem.h +++ b/qdf/linux/src/i_qdf_mem.h @@ -266,11 +266,23 @@ __qdf_os_mem_dma_get_sgtable(struct device *dev, void *sgt, void *cpu_addr, size); } +/** + * __qdf_os_mem_free_sgtable() - Free a previously allocated sg table + * @sgt: the mapped sg table header + * + * Return: None + */ +static inline void +__qdf_os_mem_free_sgtable(struct sg_table *sgt) +{ + sg_free_table(sgt); +} + /** * __qdf_dma_get_sgtable_dma_addr()-Assigns DMA address to scatterlist elements * @sgt: scatter gather table pointer * - * @Return: None + * Return: None */ static inline void __qdf_dma_get_sgtable_dma_addr(struct sg_table *sgt) diff --git a/qdf/linux/src/qdf_mem.c b/qdf/linux/src/qdf_mem.c index c427bcd496..35d3b39579 100644 --- a/qdf/linux/src/qdf_mem.c +++ b/qdf/linux/src/qdf_mem.c @@ -1468,6 +1468,56 @@ void qdf_mem_copy(void *dst_addr, const void *src_addr, uint32_t num_bytes) } qdf_export_symbol(qdf_mem_copy); +qdf_shared_mem_t *qdf_mem_shared_mem_alloc(qdf_device_t osdev, uint32_t size) +{ + qdf_shared_mem_t *shared_mem; + qdf_dma_addr_t dma_addr, paddr; + int ret; + + shared_mem = qdf_mem_malloc(sizeof(*shared_mem)); + if (!shared_mem) { + qdf_err("Unable to allocate memory for shared resource struct"); + return NULL; + } + + shared_mem->vaddr = qdf_mem_alloc_consistent(osdev, osdev->dev, + size, qdf_mem_get_dma_addr_ptr(osdev, + &shared_mem->mem_info)); + if (!shared_mem->vaddr) { + qdf_err("Unable to allocate DMA memory for shared resource"); + qdf_mem_free(shared_mem); + return NULL; + } + + qdf_mem_set_dma_size(osdev, &shared_mem->mem_info, size); + size = qdf_mem_get_dma_size(osdev, &shared_mem->mem_info); + + qdf_mem_zero(shared_mem->vaddr, size); + dma_addr = qdf_mem_get_dma_addr(osdev, &shared_mem->mem_info); + paddr = qdf_mem_paddr_from_dmaaddr(osdev, dma_addr); + + qdf_mem_set_dma_pa(osdev, &shared_mem->mem_info, paddr); + ret = qdf_mem_dma_get_sgtable(osdev->dev, &shared_mem->sgtable, + shared_mem->vaddr, dma_addr, size); + if (ret) { + qdf_err("Unable to get DMA sgtable"); + qdf_mem_free_consistent(osdev, osdev->dev, + shared_mem->mem_info.size, + shared_mem->vaddr, + dma_addr, + qdf_get_dma_mem_context(shared_mem, + memctx)); + qdf_mem_free(shared_mem); + return NULL; + } + + qdf_dma_get_sgtable_dma_addr(&shared_mem->sgtable); + + return shared_mem; +} + +qdf_export_symbol(qdf_mem_shared_mem_alloc); + /** * qdf_mem_zero() - zero out memory * @ptr: pointer to memory that will be set to zero