From 6f3aabd183984120acb59f5d57a45cfa7455be9a Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Thu, 25 Sep 2014 16:05:25 -0700 Subject: genalloc: fix device node resource counter Decrement the np_pool device_node refcount, which was incremented on the preceding of_parse_phandle() call. Signed-off-by: Vladimir Zapolskiy Cc: Will Deacon Cc: Olof Johansson Cc: Catalin Marinas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/genalloc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/genalloc.c') diff --git a/lib/genalloc.c b/lib/genalloc.c index bdb9a456bcb..38d2db82228 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -588,6 +588,7 @@ struct gen_pool *of_get_named_gen_pool(struct device_node *np, if (!np_pool) return NULL; pdev = of_find_device_by_node(np_pool); + of_node_put(np_pool); if (!pdev) return NULL; return dev_get_gen_pool(&pdev->dev); -- cgit v1.2.3-70-g09d2 From 505e3be6c082489a32a88e042f930d047b6415bc Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Thu, 9 Oct 2014 15:26:35 -0700 Subject: lib/genalloc.c: add power aligned algorithm One of the more common algorithms used for allocation is to align the start address of the allocation to the order of size requested. Add this as an algorithm option for genalloc. Signed-off-by: Laura Abbott Acked-by: Will Deacon Acked-by: Olof Johansson Reviewed-by: Catalin Marinas Cc: Arnd Bergmann Cc: David Riley Cc: Ritesh Harjain Cc: Russell King Cc: Thierry Reding Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/genalloc.h | 4 ++++ lib/genalloc.c | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+) (limited to 'lib/genalloc.c') diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h index 1c2fdaa2ffc..3cd0934d62b 100644 --- a/include/linux/genalloc.h +++ b/include/linux/genalloc.h @@ -110,6 +110,10 @@ extern void gen_pool_set_algo(struct gen_pool *pool, genpool_algo_t algo, extern unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, void *data); +extern unsigned long gen_pool_first_fit_order_align(unsigned long *map, + unsigned long size, unsigned long start, unsigned int nr, + void *data); + extern unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, void *data); diff --git a/lib/genalloc.c b/lib/genalloc.c index 38d2db82228..166f17b9f16 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -480,6 +480,26 @@ unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size, } EXPORT_SYMBOL(gen_pool_first_fit); +/** + * gen_pool_first_fit_order_align - find the first available region + * of memory matching the size requirement. The region will be aligned + * to the order of the size specified. + * @map: The address to base the search on + * @size: The bitmap size in bits + * @start: The bitnumber to start searching at + * @nr: The number of zeroed bits we're looking for + * @data: additional data - unused + */ +unsigned long gen_pool_first_fit_order_align(unsigned long *map, + unsigned long size, unsigned long start, + unsigned int nr, void *data) +{ + unsigned long align_mask = roundup_pow_of_two(nr) - 1; + + return bitmap_find_next_zero_area(map, size, start, nr, align_mask); +} +EXPORT_SYMBOL(gen_pool_first_fit_order_align); + /** * gen_pool_best_fit - find the best fitting region of memory * macthing the size requirement (no alignment constraint) -- cgit v1.2.3-70-g09d2 From 9efb3a421d55d30b65fb0dbee05108d15c6c55f7 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Thu, 9 Oct 2014 15:26:38 -0700 Subject: lib/genalloc.c: add genpool range check function After allocating an address from a particular genpool, there is no good way to verify if that address actually belongs to a genpool. Introduce addr_in_gen_pool which will return if an address plus size falls completely within the genpool range. Signed-off-by: Laura Abbott Acked-by: Will Deacon Reviewed-by: Olof Johansson Reviewed-by: Catalin Marinas Cc: Arnd Bergmann Cc: David Riley Cc: Ritesh Harjain Cc: Russell King Cc: Thierry Reding Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/genalloc.h | 3 +++ lib/genalloc.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) (limited to 'lib/genalloc.c') diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h index 3cd0934d62b..1ccaab44abc 100644 --- a/include/linux/genalloc.h +++ b/include/linux/genalloc.h @@ -121,6 +121,9 @@ extern struct gen_pool *devm_gen_pool_create(struct device *dev, int min_alloc_order, int nid); extern struct gen_pool *dev_get_gen_pool(struct device *dev); +bool addr_in_gen_pool(struct gen_pool *pool, unsigned long start, + size_t size); + #ifdef CONFIG_OF extern struct gen_pool *of_get_named_gen_pool(struct device_node *np, const char *propname, int index); diff --git a/lib/genalloc.c b/lib/genalloc.c index 166f17b9f16..cce4dd68c40 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -402,6 +402,35 @@ void gen_pool_for_each_chunk(struct gen_pool *pool, } EXPORT_SYMBOL(gen_pool_for_each_chunk); +/** + * addr_in_gen_pool - checks if an address falls within the range of a pool + * @pool: the generic memory pool + * @start: start address + * @size: size of the region + * + * Check if the range of addresses falls within the specified pool. Returns + * true if the entire range is contained in the pool and false otherwise. + */ +bool addr_in_gen_pool(struct gen_pool *pool, unsigned long start, + size_t size) +{ + bool found = false; + unsigned long end = start + size; + struct gen_pool_chunk *chunk; + + rcu_read_lock(); + list_for_each_entry_rcu(chunk, &(pool)->chunks, next_chunk) { + if (start >= chunk->start_addr && start <= chunk->end_addr) { + if (end <= chunk->end_addr) { + found = true; + break; + } + } + } + rcu_read_unlock(); + return found; +} + /** * gen_pool_avail - get available free space of the pool * @pool: pool to get available free space -- cgit v1.2.3-70-g09d2