Browse Source

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
Jiachao Wu 7 years ago
parent
commit
ae6c777bd1
3 changed files with 79 additions and 44 deletions
  1. 16 43
      qdf/inc/qdf_mem.h
  2. 13 1
      qdf/linux/src/i_qdf_mem.h
  3. 50 0
      qdf/linux/src/qdf_mem.c

+ 16 - 43
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);
 }
 

+ 13 - 1
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)

+ 50 - 0
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