diff options
author | Philipp Zabel <p.zabel@pengutronix.de> | 2013-04-29 19:17:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-29 21:28:13 -0400 |
commit | 9375db07adeaeea5f5ea7ca0463a8b371d71ddbb (patch) | |
tree | 8825d1985a7bd6acd9e13de4594c574c81dd11fe /lib | |
parent | 3119b487e03650b51589a86aac33098b7cc2a09e (diff) |
genalloc: add devres support, allow to find a managed pool by device
This patch adds three exported functions to lib/genalloc.c:
devm_gen_pool_create, dev_get_gen_pool, and of_get_named_gen_pool.
devm_gen_pool_create is a managed version of gen_pool_create that keeps
track of the pool via devres and allows the management code to
automatically destroy it after device removal.
dev_get_gen_pool retrieves the gen_pool for a given device, if it was
created with devm_gen_pool_create, using devres_find.
of_get_named_gen_pool retrieves the gen_pool for a given device node and
property name, where the property must contain a phandle pointing to a
platform device node. The corresponding platform device is then fed into
dev_get_gen_pool and the resulting gen_pool is returned.
[akpm@linux-foundation.org: make the of_get_named_gen_pool() stub static, fixing a zillion link errors]
[akpm@linux-foundation.org: squish "struct device declared inside parameter list" warning]
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: Michal Simek <monstr@monstr.eu>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Matt Porter <mporter@ti.com>
Cc: Dong Aisheng <dong.aisheng@linaro.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Javier Martin <javier.martin@vista-silicon.com>
Cc: Huang Shijie <shijie8@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/genalloc.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/lib/genalloc.c b/lib/genalloc.c index 54920433705a..b35cfa9bc3d4 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <linux/rculist.h> | 34 | #include <linux/rculist.h> |
35 | #include <linux/interrupt.h> | 35 | #include <linux/interrupt.h> |
36 | #include <linux/genalloc.h> | 36 | #include <linux/genalloc.h> |
37 | #include <linux/of_address.h> | ||
38 | #include <linux/of_device.h> | ||
37 | 39 | ||
38 | static int set_bits_ll(unsigned long *addr, unsigned long mask_to_set) | 40 | static int set_bits_ll(unsigned long *addr, unsigned long mask_to_set) |
39 | { | 41 | { |
@@ -480,3 +482,82 @@ unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size, | |||
480 | return start_bit; | 482 | return start_bit; |
481 | } | 483 | } |
482 | EXPORT_SYMBOL(gen_pool_best_fit); | 484 | EXPORT_SYMBOL(gen_pool_best_fit); |
485 | |||
486 | static void devm_gen_pool_release(struct device *dev, void *res) | ||
487 | { | ||
488 | gen_pool_destroy(*(struct gen_pool **)res); | ||
489 | } | ||
490 | |||
491 | /** | ||
492 | * devm_gen_pool_create - managed gen_pool_create | ||
493 | * @dev: device that provides the gen_pool | ||
494 | * @min_alloc_order: log base 2 of number of bytes each bitmap bit represents | ||
495 | * @nid: node id of the node the pool structure should be allocated on, or -1 | ||
496 | * | ||
497 | * Create a new special memory pool that can be used to manage special purpose | ||
498 | * memory not managed by the regular kmalloc/kfree interface. The pool will be | ||
499 | * automatically destroyed by the device management code. | ||
500 | */ | ||
501 | struct gen_pool *devm_gen_pool_create(struct device *dev, int min_alloc_order, | ||
502 | int nid) | ||
503 | { | ||
504 | struct gen_pool **ptr, *pool; | ||
505 | |||
506 | ptr = devres_alloc(devm_gen_pool_release, sizeof(*ptr), GFP_KERNEL); | ||
507 | |||
508 | pool = gen_pool_create(min_alloc_order, nid); | ||
509 | if (pool) { | ||
510 | *ptr = pool; | ||
511 | devres_add(dev, ptr); | ||
512 | } else { | ||
513 | devres_free(ptr); | ||
514 | } | ||
515 | |||
516 | return pool; | ||
517 | } | ||
518 | |||
519 | /** | ||
520 | * dev_get_gen_pool - Obtain the gen_pool (if any) for a device | ||
521 | * @dev: device to retrieve the gen_pool from | ||
522 | * @name: Optional name for the gen_pool, usually NULL | ||
523 | * | ||
524 | * Returns the gen_pool for the device if one is present, or NULL. | ||
525 | */ | ||
526 | struct gen_pool *dev_get_gen_pool(struct device *dev) | ||
527 | { | ||
528 | struct gen_pool **p = devres_find(dev, devm_gen_pool_release, NULL, | ||
529 | NULL); | ||
530 | |||
531 | if (!p) | ||
532 | return NULL; | ||
533 | return *p; | ||
534 | } | ||
535 | EXPORT_SYMBOL_GPL(dev_get_gen_pool); | ||
536 | |||
537 | #ifdef CONFIG_OF | ||
538 | /** | ||
539 | * of_get_named_gen_pool - find a pool by phandle property | ||
540 | * @np: device node | ||
541 | * @propname: property name containing phandle(s) | ||
542 | * @index: index into the phandle array | ||
543 | * | ||
544 | * Returns the pool that contains the chunk starting at the physical | ||
545 | * address of the device tree node pointed at by the phandle property, | ||
546 | * or NULL if not found. | ||
547 | */ | ||
548 | struct gen_pool *of_get_named_gen_pool(struct device_node *np, | ||
549 | const char *propname, int index) | ||
550 | { | ||
551 | struct platform_device *pdev; | ||
552 | struct device_node *np_pool; | ||
553 | |||
554 | np_pool = of_parse_phandle(np, propname, index); | ||
555 | if (!np_pool) | ||
556 | return NULL; | ||
557 | pdev = of_find_device_by_node(np_pool); | ||
558 | if (!pdev) | ||
559 | return NULL; | ||
560 | return dev_get_gen_pool(&pdev->dev); | ||
561 | } | ||
562 | EXPORT_SYMBOL_GPL(of_get_named_gen_pool); | ||
563 | #endif /* CONFIG_OF */ | ||