Skip to content

Commit 593286f

Browse files
Krishna ReddyVarun Colbert
Krishna Reddy
authored and
Varun Colbert
committed
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 <[email protected]> Reviewed-on: http://git-master/r/74468 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Stephen Warren <[email protected]>
1 parent fe5e169 commit 593286f

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

include/linux/genalloc.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,17 @@ static inline int gen_pool_add(struct gen_pool *pool, unsigned long addr,
7272
return gen_pool_add_virt(pool, addr, -1, size, nid);
7373
}
7474
extern void gen_pool_destroy(struct gen_pool *);
75-
extern unsigned long gen_pool_alloc(struct gen_pool *, size_t);
75+
extern unsigned long gen_pool_alloc_addr(struct gen_pool *,
76+
size_t, unsigned long);
77+
/**
78+
* gen_pool_alloc - allocate special memory from the pool
79+
* @pool: pool to allocate from
80+
* @size: number of bytes to allocate from the pool
81+
*/
82+
static inline unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
83+
{
84+
return gen_pool_alloc_addr(pool, size);
85+
}
7686
extern void gen_pool_free(struct gen_pool *, unsigned long, size_t);
7787
extern void gen_pool_for_each_chunk(struct gen_pool *,
7888
void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *);

lib/genalloc.c

+20-3
Original file line numberDiff line numberDiff line change
@@ -250,20 +250,23 @@ void gen_pool_destroy(struct gen_pool *pool)
250250
EXPORT_SYMBOL(gen_pool_destroy);
251251

252252
/**
253-
* gen_pool_alloc - allocate special memory from the pool
253+
* gen_pool_alloc_addr - allocate special memory from the pool
254254
* @pool: pool to allocate from
255255
* @size: number of bytes to allocate from the pool
256+
* @alloc_addr: if non-zero, allocate starting at alloc_addr.
256257
*
257258
* Allocate the requested number of bytes from the specified pool.
258259
* Uses a first-fit algorithm. Can not be used in NMI handler on
259260
* architectures without NMI-safe cmpxchg implementation.
260261
*/
261-
unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
262+
unsigned long gen_pool_alloc_addr(struct gen_pool *pool, size_t size,
263+
unsigned long alloc_addr)
262264
{
263265
struct gen_pool_chunk *chunk;
264266
unsigned long addr = 0;
265267
int order = pool->min_alloc_order;
266268
int nbits, start_bit = 0, end_bit, remain;
269+
int alloc_bit_needed = 0;
267270

268271
#ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
269272
BUG_ON(in_nmi());
@@ -272,16 +275,30 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
272275
if (size == 0)
273276
return 0;
274277

278+
if (alloc_addr & (1 << order) - 1)
279+
return 0;
280+
275281
nbits = (size + (1UL << order) - 1) >> order;
276282
rcu_read_lock();
277283
list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) {
278284
if (size > atomic_read(&chunk->avail))
279285
continue;
280286

281287
end_bit = (chunk->end_addr - chunk->start_addr) >> order;
288+
if (alloc_addr) {
289+
if (alloc_addr < chunk->start_addr ||
290+
alloc_addr >= chunk->end_addr)
291+
continue;
292+
if (alloc_addr + size > chunk->end_addr)
293+
return 0;
294+
alloc_bit_needed = start_bit =
295+
(alloc_addr - chunk->start_addr) >> order;
296+
}
282297
retry:
283298
start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit,
284299
start_bit, nbits, 0);
300+
if (alloc_addr && alloc_bit_needed != start_bit)
301+
return 0;
285302
if (start_bit >= end_bit)
286303
continue;
287304
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)
300317
rcu_read_unlock();
301318
return addr;
302319
}
303-
EXPORT_SYMBOL(gen_pool_alloc);
320+
EXPORT_SYMBOL(gen_pool_alloc_addr);
304321

305322
/**
306323
* gen_pool_free - free allocated special memory back to the pool

0 commit comments

Comments
 (0)