Permalink
Browse files

lib: genalloc: Add API to allocate at specified addr.

Add API to allocate at specified alloc address.

Change-Id: I188e5430220c050026c6a3e17a586012d9a9fa04
Signed-off-by: Krishna Reddy <vdumpa@nvidia.com>
Reviewed-on: http://git-master/r/74468
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Stephen Warren <swarren@nvidia.com>
  • Loading branch information...
1 parent fe5e169 commit 593286fff9e08c417817c3cf4bfc0716fe89a93e Krishna Reddy committed with Varun Colbert Jan 11, 2012
Showing with 31 additions and 4 deletions.
  1. +11 −1 include/linux/genalloc.h
  2. +20 −3 lib/genalloc.c
View
@@ -72,7 +72,17 @@ static inline int gen_pool_add(struct gen_pool *pool, unsigned long addr,
return gen_pool_add_virt(pool, addr, -1, size, nid);
}
extern void gen_pool_destroy(struct gen_pool *);
-extern unsigned long gen_pool_alloc(struct gen_pool *, size_t);
+extern unsigned long gen_pool_alloc_addr(struct gen_pool *,
+ size_t, unsigned long);
+/**
+ * gen_pool_alloc - allocate special memory from the pool
+ * @pool: pool to allocate from
+ * @size: number of bytes to allocate from the pool
+ */
+static inline unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
+{
+ return gen_pool_alloc_addr(pool, size);
+}
extern void gen_pool_free(struct gen_pool *, unsigned long, size_t);
extern void gen_pool_for_each_chunk(struct gen_pool *,
void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *);
View
@@ -250,20 +250,23 @@ void gen_pool_destroy(struct gen_pool *pool)
EXPORT_SYMBOL(gen_pool_destroy);
/**
- * gen_pool_alloc - allocate special memory from the pool
+ * gen_pool_alloc_addr - allocate special memory from the pool
* @pool: pool to allocate from
* @size: number of bytes to allocate from the pool
+ * @alloc_addr: if non-zero, allocate starting at alloc_addr.
*
* Allocate the requested number of bytes from the specified pool.
* Uses a first-fit algorithm. Can not be used in NMI handler on
* architectures without NMI-safe cmpxchg implementation.
*/
-unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
+unsigned long gen_pool_alloc_addr(struct gen_pool *pool, size_t size,
+ unsigned long alloc_addr)
{
struct gen_pool_chunk *chunk;
unsigned long addr = 0;
int order = pool->min_alloc_order;
int nbits, start_bit = 0, end_bit, remain;
+ int alloc_bit_needed = 0;
#ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
BUG_ON(in_nmi());
@@ -272,16 +275,30 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
if (size == 0)
return 0;
+ if (alloc_addr & (1 << order) - 1)
+ return 0;
+
nbits = (size + (1UL << order) - 1) >> order;
rcu_read_lock();
list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) {
if (size > atomic_read(&chunk->avail))
continue;
end_bit = (chunk->end_addr - chunk->start_addr) >> order;
+ if (alloc_addr) {
+ if (alloc_addr < chunk->start_addr ||
+ alloc_addr >= chunk->end_addr)
+ continue;
+ if (alloc_addr + size > chunk->end_addr)
+ return 0;
+ alloc_bit_needed = start_bit =
+ (alloc_addr - chunk->start_addr) >> order;
+ }
retry:
start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit,
start_bit, nbits, 0);
+ if (alloc_addr && alloc_bit_needed != start_bit)
+ return 0;
if (start_bit >= end_bit)
continue;
remain = bitmap_set_ll(chunk->bits, start_bit, nbits);
@@ -300,7 +317,7 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
rcu_read_unlock();
return addr;
}
-EXPORT_SYMBOL(gen_pool_alloc);
+EXPORT_SYMBOL(gen_pool_alloc_addr);
/**
* gen_pool_free - free allocated special memory back to the pool

0 comments on commit 593286f

Please sign in to comment.