diff options
Diffstat (limited to 'lib/genalloc.c')
| -rw-r--r-- | lib/genalloc.c | 33 | 
1 files changed, 12 insertions, 21 deletions
diff --git a/lib/genalloc.c b/lib/genalloc.c index eed2bdb865e..e67f97495dd 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -11,6 +11,7 @@   */  #include <linux/module.h> +#include <linux/bitmap.h>  #include <linux/genalloc.h> @@ -114,7 +115,7 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)  	struct gen_pool_chunk *chunk;  	unsigned long addr, flags;  	int order = pool->min_alloc_order; -	int nbits, bit, start_bit, end_bit; +	int nbits, start_bit, end_bit;  	if (size == 0)  		return 0; @@ -129,29 +130,19 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)  		end_bit -= nbits + 1;  		spin_lock_irqsave(&chunk->lock, flags); -		bit = -1; -		while (bit + 1 < end_bit) { -			bit = find_next_zero_bit(chunk->bits, end_bit, bit + 1); -			if (bit >= end_bit) -				break; - -			start_bit = bit; -			if (nbits > 1) { -				bit = find_next_bit(chunk->bits, bit + nbits, -							bit + 1); -				if (bit - start_bit < nbits) -					continue; -			} - -			addr = chunk->start_addr + -					    ((unsigned long)start_bit << order); -			while (nbits--) -				__set_bit(start_bit++, chunk->bits); +		start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit, 0, +						nbits, 0); +		if (start_bit >= end_bit) {  			spin_unlock_irqrestore(&chunk->lock, flags); -			read_unlock(&pool->lock); -			return addr; +			continue;  		} + +		addr = chunk->start_addr + ((unsigned long)start_bit << order); + +		bitmap_set(chunk->bits, start_bit, nbits);  		spin_unlock_irqrestore(&chunk->lock, flags); +		read_unlock(&pool->lock); +		return addr;  	}  	read_unlock(&pool->lock);  	return 0;  | 
