Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 97963442 authored by Jordan Crouse's avatar Jordan Crouse Committed by Jeremy Gebben
Browse files

msm: kgsl: Add kgsl_malloc/kgsl_free helpers



Instead of constantly trying to reinvent the wheel when doing
kernel allocations of indeterminate size create a alloc/free
pair of functions that can do the magic for us. Replace all of
the existing bits and pieces with the new function calls.

Change-Id: Ic0dedbad349ce1196899f4c24a374e0bfed3a923
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent ce80330c
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -12,7 +12,6 @@
 */
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <linux/ioctl.h>
#include <linux/sched.h>
#include <linux/of.h>
+2 −4
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/dma-buf.h>
#include <linux/vmalloc.h>
#include <linux/pm_runtime.h>
#include <linux/rbtree.h>
#include <linux/ashmem.h>
@@ -2545,13 +2544,12 @@ static int memdesc_sg_virt(struct kgsl_memdesc *memdesc,
	int i;
	int sglen = PAGE_ALIGN(size) / PAGE_SIZE;

	memdesc->sg = kgsl_sg_alloc(sglen);
	memdesc->sg = kgsl_malloc(sglen * sizeof(struct scatterlist));

	if (memdesc->sg == NULL)
		return -ENOMEM;

	memdesc->sglen = sglen;
	memdesc->sglen_alloc = sglen;

	sg_init_table(memdesc->sg, sglen);

@@ -2588,7 +2586,7 @@ static int memdesc_sg_virt(struct kgsl_memdesc *memdesc,

err:
	spin_unlock(&current->mm->page_table_lock);
	kgsl_sg_free(memdesc->sg,  sglen);
	kgsl_free(memdesc->sg);
	memdesc->sg = NULL;

	return -EINVAL;
+31 −1
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
#define __KGSL_H

#include <linux/types.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/msm_kgsl.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
@@ -174,7 +176,6 @@ struct kgsl_memdesc {
	unsigned int priv; /* Internal flags and settings */
	struct scatterlist *sg;
	unsigned int sglen; /* Active entries in the sglist */
	unsigned int sglen_alloc;  /* Allocated entries in the sglist */
	struct kgsl_memdesc_ops *ops;
	unsigned int flags; /* Flags set from userspace */
	struct device *dev;
@@ -404,4 +405,33 @@ static inline bool kgsl_addr_range_overlap(unsigned int gpuaddr1,
		(gpuaddr1 >= (gpuaddr2 + size2)));
}

/**
 * kgsl_malloc() - Use either kzalloc or vmalloc to allocate memory
 * @size: Size of the desired allocation
 *
 * Allocate a block of memory for the driver - if it is small try to allocate it
 * from kmalloc (fast!) otherwise we need to go with vmalloc (safe!)
 */
static inline void *kgsl_malloc(size_t size)
{
	if (size <= PAGE_SIZE)
		return kzalloc(size, GFP_KERNEL);

	return vmalloc(size);
}

/**
 * kgsl_free() - Free memory allocated by kgsl_malloc()
 * @ptr: Pointer to the memory to free
 *
 * Free the memory be it in vmalloc or kmalloc space
 */
static inline void kgsl_free(void *ptr)
{
	if (is_vmalloc_addr(ptr))
		return vfree(ptr);

	kfree(ptr);
}

#endif /* __KGSL_H */
+2 −2
Original line number Diff line number Diff line
@@ -1857,11 +1857,11 @@ static int kgsl_iommu_close(struct kgsl_mmu *mmu)

		if (reg_map->hostptr)
			iounmap(reg_map->hostptr);
		kgsl_sg_free(reg_map->sg, reg_map->sglen);
		kgsl_free(reg_map->sg);
		reg_map->priv &= ~KGSL_MEMDESC_GLOBAL;
	}
	/* clear IOMMU GPU CPU sync structures */
	kgsl_sg_free(iommu->sync_lock_desc.sg, iommu->sync_lock_desc.sglen);
	kgsl_free(iommu->sync_lock_desc.sg);
	memset(&iommu->sync_lock_desc, 0, sizeof(iommu->sync_lock_desc));
	iommu->sync_lock_vars = NULL;

+10 −20
Original line number Diff line number Diff line
@@ -462,8 +462,8 @@ static int kgsl_page_alloc_map_kernel(struct kgsl_memdesc *memdesc)
		int i, count = 0;

		/* create a list of pages to call vmap */
		pages = vmalloc(npages * sizeof(struct page *));
		if (!pages) {
		pages = kgsl_malloc(npages * sizeof(struct page *));
		if (pages == NULL) {
			ret = -ENOMEM;
			goto done;
		}
@@ -484,7 +484,7 @@ static int kgsl_page_alloc_map_kernel(struct kgsl_memdesc *memdesc)
				kgsl_driver.stats.vmalloc_max);
		else
			ret = -ENOMEM;
		vfree(pages);
		kgsl_free(pages);
	}
	if (memdesc->hostptr)
		memdesc->hostptr_count++;
@@ -611,8 +611,7 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc,
	memdesc->pagetable = pagetable;
	memdesc->ops = &kgsl_page_alloc_ops;

	memdesc->sglen_alloc = sglen_alloc;
	memdesc->sg = kgsl_sg_alloc(memdesc->sglen_alloc);
	memdesc->sg = kgsl_malloc(sglen_alloc * sizeof(struct scatterlist));

	if (memdesc->sg == NULL) {
		ret = -ENOMEM;
@@ -620,17 +619,11 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc,
	}

	/*
	 * Allocate space to store the list of pages to send to vmap.
	 * This is an array of pointers so we can track 1024 pages per page
	 * of allocation.  Since allocations can be as large as the user dares,
	 * we have to use the kmalloc/vmalloc trick here to make sure we can
	 * get the memory we need.
	 * Allocate space to store the list of pages to send to vmap. This is an
	 * array of pointers so we can track 1024 pages per page of allocation
	 */

	if ((memdesc->sglen_alloc * sizeof(struct page *)) > PAGE_SIZE)
		pages = vmalloc(memdesc->sglen_alloc * sizeof(struct page *));
	else
		pages = kmalloc(PAGE_SIZE, GFP_KERNEL);
	pages = kgsl_malloc(sglen_alloc * sizeof(struct page *));

	if (pages == NULL) {
		ret = -ENOMEM;
@@ -639,7 +632,7 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc,

	kmemleak_not_leak(memdesc->sg);

	sg_init_table(memdesc->sg, memdesc->sglen_alloc);
	sg_init_table(memdesc->sg, sglen_alloc);

	len = size;

@@ -750,10 +743,7 @@ done:
	KGSL_STATS_ADD(memdesc->size, kgsl_driver.stats.page_alloc,
		kgsl_driver.stats.page_alloc_max);

	if ((memdesc->sglen_alloc * sizeof(struct page *)) > PAGE_SIZE)
		vfree(pages);
	else
		kfree(pages);
	kgsl_free(pages);

	if (ret)
		kgsl_sharedmem_free(memdesc);
@@ -845,7 +835,7 @@ void kgsl_sharedmem_free(struct kgsl_memdesc *memdesc)
	if (memdesc->ops && memdesc->ops->free)
		memdesc->ops->free(memdesc);

	kgsl_sg_free(memdesc->sg, memdesc->sglen_alloc);
	kgsl_free(memdesc->sg);

	memset(memdesc, 0, sizeof(*memdesc));
}
Loading