diff options
-rw-r--r-- | include/linux/genalloc.h | 4 | ||||
-rw-r--r-- | lib/genalloc.c | 19 |
2 files changed, 14 insertions, 9 deletions
diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h index 661d374aeb2d..f8d41cb1cbe0 100644 --- a/include/linux/genalloc.h +++ b/include/linux/genalloc.h | |||
@@ -66,8 +66,8 @@ struct gen_pool_chunk { | |||
66 | struct list_head next_chunk; /* next chunk in pool */ | 66 | struct list_head next_chunk; /* next chunk in pool */ |
67 | atomic_t avail; | 67 | atomic_t avail; |
68 | phys_addr_t phys_addr; /* physical starting address of memory chunk */ | 68 | phys_addr_t phys_addr; /* physical starting address of memory chunk */ |
69 | unsigned long start_addr; /* starting address of memory chunk */ | 69 | unsigned long start_addr; /* start address of memory chunk */ |
70 | unsigned long end_addr; /* ending address of memory chunk */ | 70 | unsigned long end_addr; /* end address of memory chunk (inclusive) */ |
71 | unsigned long bits[0]; /* bitmap for allocating memory chunk */ | 71 | unsigned long bits[0]; /* bitmap for allocating memory chunk */ |
72 | }; | 72 | }; |
73 | 73 | ||
diff --git a/lib/genalloc.c b/lib/genalloc.c index b35cfa9bc3d4..2a39bf62d8c1 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c | |||
@@ -37,6 +37,11 @@ | |||
37 | #include <linux/of_address.h> | 37 | #include <linux/of_address.h> |
38 | #include <linux/of_device.h> | 38 | #include <linux/of_device.h> |
39 | 39 | ||
40 | static inline size_t chunk_size(const struct gen_pool_chunk *chunk) | ||
41 | { | ||
42 | return chunk->end_addr - chunk->start_addr + 1; | ||
43 | } | ||
44 | |||
40 | static int set_bits_ll(unsigned long *addr, unsigned long mask_to_set) | 45 | static int set_bits_ll(unsigned long *addr, unsigned long mask_to_set) |
41 | { | 46 | { |
42 | unsigned long val, nval; | 47 | unsigned long val, nval; |
@@ -188,7 +193,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy | |||
188 | 193 | ||
189 | chunk->phys_addr = phys; | 194 | chunk->phys_addr = phys; |
190 | chunk->start_addr = virt; | 195 | chunk->start_addr = virt; |
191 | chunk->end_addr = virt + size; | 196 | chunk->end_addr = virt + size - 1; |
192 | atomic_set(&chunk->avail, size); | 197 | atomic_set(&chunk->avail, size); |
193 | 198 | ||
194 | spin_lock(&pool->lock); | 199 | spin_lock(&pool->lock); |
@@ -213,7 +218,7 @@ phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long addr) | |||
213 | 218 | ||
214 | rcu_read_lock(); | 219 | rcu_read_lock(); |
215 | list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) { | 220 | list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) { |
216 | if (addr >= chunk->start_addr && addr < chunk->end_addr) { | 221 | if (addr >= chunk->start_addr && addr <= chunk->end_addr) { |
217 | paddr = chunk->phys_addr + (addr - chunk->start_addr); | 222 | paddr = chunk->phys_addr + (addr - chunk->start_addr); |
218 | break; | 223 | break; |
219 | } | 224 | } |
@@ -242,7 +247,7 @@ void gen_pool_destroy(struct gen_pool *pool) | |||
242 | chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk); | 247 | chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk); |
243 | list_del(&chunk->next_chunk); | 248 | list_del(&chunk->next_chunk); |
244 | 249 | ||
245 | end_bit = (chunk->end_addr - chunk->start_addr) >> order; | 250 | end_bit = chunk_size(chunk) >> order; |
246 | bit = find_next_bit(chunk->bits, end_bit, 0); | 251 | bit = find_next_bit(chunk->bits, end_bit, 0); |
247 | BUG_ON(bit < end_bit); | 252 | BUG_ON(bit < end_bit); |
248 | 253 | ||
@@ -283,7 +288,7 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size) | |||
283 | if (size > atomic_read(&chunk->avail)) | 288 | if (size > atomic_read(&chunk->avail)) |
284 | continue; | 289 | continue; |
285 | 290 | ||
286 | end_bit = (chunk->end_addr - chunk->start_addr) >> order; | 291 | end_bit = chunk_size(chunk) >> order; |
287 | retry: | 292 | retry: |
288 | start_bit = pool->algo(chunk->bits, end_bit, start_bit, nbits, | 293 | start_bit = pool->algo(chunk->bits, end_bit, start_bit, nbits, |
289 | pool->data); | 294 | pool->data); |
@@ -330,8 +335,8 @@ void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size) | |||
330 | nbits = (size + (1UL << order) - 1) >> order; | 335 | nbits = (size + (1UL << order) - 1) >> order; |
331 | rcu_read_lock(); | 336 | rcu_read_lock(); |
332 | list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) { | 337 | list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) { |
333 | if (addr >= chunk->start_addr && addr < chunk->end_addr) { | 338 | if (addr >= chunk->start_addr && addr <= chunk->end_addr) { |
334 | BUG_ON(addr + size > chunk->end_addr); | 339 | BUG_ON(addr + size - 1 > chunk->end_addr); |
335 | start_bit = (addr - chunk->start_addr) >> order; | 340 | start_bit = (addr - chunk->start_addr) >> order; |
336 | remain = bitmap_clear_ll(chunk->bits, start_bit, nbits); | 341 | remain = bitmap_clear_ll(chunk->bits, start_bit, nbits); |
337 | BUG_ON(remain); | 342 | BUG_ON(remain); |
@@ -400,7 +405,7 @@ size_t gen_pool_size(struct gen_pool *pool) | |||
400 | 405 | ||
401 | rcu_read_lock(); | 406 | rcu_read_lock(); |
402 | list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) | 407 | list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) |
403 | size += chunk->end_addr - chunk->start_addr; | 408 | size += chunk_size(chunk); |
404 | rcu_read_unlock(); | 409 | rcu_read_unlock(); |
405 | return size; | 410 | return size; |
406 | } | 411 | } |