diff options
author | Shrenuj Bansal <shrenujb@codeaurora.org> | 2016-04-29 09:28:02 -0600 |
---|---|---|
committer | Jeevan Shriram <jshriram@codeaurora.org> | 2016-05-11 17:44:06 -0700 |
commit | 8cdea23e0363e5edc074b5031cbd94e772efd9c9 (patch) | |
tree | 4b2f30836ad93a8b5755f7454b830ecccc5f125a /drivers/gpu/msm/kgsl_sharedmem.c | |
parent | 01da6d8db6880db3ffe2e7c7c720c214ba18136f (diff) |
msm: kgsl: Add 1M and 8K pools to the allocator
This change includes the below:
- Add 1M and 8k pools and structure the allocator to use all pools
from the largest page to the smallest
- Reserve a set number of pages for each of these pools at init time
- When allocating, use the reserved pools and then fall back to
allocating from system memory using only 8k and 4k pages
- Remove maximums on the pool sizes
- Zero the memory when we create the pool initially and add pages
back to the pool on free
CRs-Fixed: 995735
Change-Id: I9440bad62d3e13b434902f167c9d23467b1c4235
Signed-off-by: Shrenuj Bansal <shrenujb@codeaurora.org>
Diffstat (limited to 'drivers/gpu/msm/kgsl_sharedmem.c')
-rw-r--r-- | drivers/gpu/msm/kgsl_sharedmem.c | 85 |
1 files changed, 18 insertions, 67 deletions
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index 4cb9bc5d1651..50dcd39fac58 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -656,8 +656,14 @@ EXPORT_SYMBOL(kgsl_cache_range_op); #ifndef CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS static inline int get_page_size(size_t size, unsigned int align) { - return (align >= ilog2(SZ_64K) && size >= SZ_64K) - ? SZ_64K : PAGE_SIZE; + if (align >= ilog2(SZ_1M) && size >= SZ_1M) + return SZ_1M; + else if (align >= ilog2(SZ_64K) && size >= SZ_64K) + return SZ_64K; + else if (align >= ilog2(SZ_8K) && size >= SZ_8K) + return SZ_8K; + else + return PAGE_SIZE; } #else static inline int get_page_size(size_t size, unsigned int align) @@ -666,56 +672,6 @@ static inline int get_page_size(size_t size, unsigned int align) } #endif -static void kgsl_zero_pages(struct page **pages, unsigned int pcount) -{ - unsigned int j; - unsigned int step = ((VMALLOC_END - VMALLOC_START)/8) >> PAGE_SHIFT; - pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL); - void *ptr; - - /* - * All memory that goes to the user has to be zeroed out before it gets - * exposed to userspace. This means that the memory has to be mapped in - * the kernel, zeroed (memset) and then unmapped. This also means that - * the dcache has to be flushed to ensure coherency between the kernel - * and user pages. We used to pass __GFP_ZERO to alloc_page which mapped - * zeroed and unmaped each individual page, and then we had to turn - * around and call flush_dcache_page() on that page to clear the caches. - * This was killing us for performance. Instead, we found it is much - * faster to allocate the pages without GFP_ZERO, map a chunk of the - * range ('step' pages), memset it, flush it and then unmap - * - this results in a factor of 4 improvement for speed for large - * buffers. There is a small decrease in speed for small buffers, - * but only on the order of a few microseconds at best. The 'step' - * size is based on a guess at the amount of free vmalloc space, but - * will scale down if there's not enough free space. - */ - for (j = 0; j < pcount; j += step) { - step = min(step, pcount - j); - - ptr = vmap(&pages[j], step, VM_IOREMAP, page_prot); - - if (ptr != NULL) { - memset(ptr, 0, step * PAGE_SIZE); - dmac_flush_range(ptr, ptr + step * PAGE_SIZE); - vunmap(ptr); - } else { - int k; - /* Very, very, very slow path */ - - for (k = j; k < j + step; k++) { - ptr = kmap_atomic(pages[k]); - memset(ptr, 0, PAGE_SIZE); - dmac_flush_range(ptr, ptr + PAGE_SIZE); - kunmap_atomic(ptr); - } - /* scale down the step size to avoid this path */ - if (step > 1) - step >>= 1; - } - } -} - static int kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc, struct kgsl_pagetable *pagetable, @@ -741,8 +697,10 @@ kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc, * larger however to accomodate hardware quirks */ - if (align < ilog2(page_size)) + if (align < ilog2(page_size)) { kgsl_memdesc_set_align(memdesc, ilog2(page_size)); + align = ilog2(page_size); + } /* * There needs to be enough room in the page array to be able to @@ -775,18 +733,13 @@ kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc, while (len > 0) { int page_count; - /* don't waste space at the end of the allocation*/ - if (len < page_size) - page_size = PAGE_SIZE; - - page_count = kgsl_pool_alloc_page(page_size, - pages + pcount, len_alloc - pcount); + page_count = kgsl_pool_alloc_page(&page_size, + pages + pcount, len_alloc - pcount, + &align); if (page_count <= 0) { - if (page_size != PAGE_SIZE) { - page_size = PAGE_SIZE; + if (page_count == -EAGAIN) continue; - } /* * Update sglen and memdesc size,as requested allocation @@ -807,6 +760,9 @@ kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc, pcount += page_count; len -= page_size; memdesc->size += page_size; + + /* Get the needed page size for the next iteration */ + page_size = get_page_size(len, align); } ret = sg_alloc_table_from_pages(memdesc->sgt, pages, pcount, 0, @@ -844,11 +800,6 @@ kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc, KGSL_STATS_ADD(memdesc->size, &kgsl_driver.stats.page_alloc, &kgsl_driver.stats.page_alloc_max); - /* - * Zero out the pages. - */ - kgsl_zero_pages(pages, pcount); - done: if (ret) { if (pages) { |