diff options
| author | Shubhraprakash Das <sadas@codeaurora.org> | 2012-08-14 00:25:43 -0700 |
|---|---|---|
| committer | Moyster <oysterized@gmail.com> | 2018-11-29 15:20:25 +0100 |
| commit | 666bda46d733bc4a3f6ff72b3589ccbdd0be3fc4 (patch) | |
| tree | bde84375b862afc10fb8ecb28f7d9d2525f11d8a /lib | |
| parent | abf4059571e05d12199ae473bdfd95e6803a7bbf (diff) | |
lib: genalloc: Change chunk allocation to vmalloc
Change the chunk allocation from kmalloc to vmalloc for
allocations greater than a page. This allows large
chunks to be allocated from physically non-contiguous
memory and increases the chance of the allocation
succeeding.
CRs-fixed: 387655
Signed-off-by: Shubhraprakash Das <sadas@codeaurora.org>
(cherry picked from commit e461457b134e55c3ca68b91b70b8796e3f3dba69)
Change-Id: I576fed3dd33fdfa9742f0c91bea72417c4f0086f
Signed-off-by: Sudhir Sharma <sudsha@codeaurora.org>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/genalloc.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/lib/genalloc.c b/lib/genalloc.c index ac5fba950..e4ac53328 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -36,6 +36,7 @@ #include <linux/genalloc.h> #include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/vmalloc.h> static inline size_t chunk_size(const struct gen_pool_chunk *chunk) { @@ -187,9 +188,14 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy int nbytes = sizeof(struct gen_pool_chunk) + BITS_TO_LONGS(nbits) * sizeof(long); - chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid); + if (nbytes <= PAGE_SIZE) + chunk = kmalloc_node(nbytes, __GFP_ZERO, nid); + else + chunk = vmalloc(nbytes); if (unlikely(chunk == NULL)) return -ENOMEM; + if (nbytes > PAGE_SIZE) + memset(chunk, 0, nbytes); chunk->phys_addr = phys; chunk->start_addr = virt; @@ -244,14 +250,20 @@ void gen_pool_destroy(struct gen_pool *pool) int bit, end_bit; list_for_each_safe(_chunk, _next_chunk, &pool->chunks) { + int nbytes; chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk); list_del(&chunk->next_chunk); end_bit = chunk_size(chunk) >> order; + nbytes = sizeof(struct gen_pool_chunk) + + (end_bit + BITS_PER_BYTE - 1) / BITS_PER_BYTE; bit = find_next_bit(chunk->bits, end_bit, 0); BUG_ON(bit < end_bit); - kfree(chunk); + if (nbytes <= PAGE_SIZE) + kfree(chunk); + else + vfree(chunk); } kfree(pool); return; |
