aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/devres.c
diff options
context:
space:
mode:
authorEli Billauer <eli.billauer@gmail.com>2014-05-16 04:26:35 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-23 13:19:25 -0400
commit43339bed7010da6e7cf797db3216a136a974a0cd (patch)
tree3ee6929132df08a32ff8887297181da78de7715b /drivers/base/devres.c
parent8ffca9eae662004016a6d60a2a79ce93f81f150e (diff)
devres: Add devm_get_free_pages API
devm_get_free_pages() and devm_free_pages() are the managed counterparts for __get_free_pages() and free_pages(). Signed-off-by: Eli Billauer <eli.billauer@gmail.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base/devres.c')
-rw-r--r--drivers/base/devres.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index d0914cba2413..52302946770f 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -852,3 +852,79 @@ void *devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp)
852 return p; 852 return p;
853} 853}
854EXPORT_SYMBOL_GPL(devm_kmemdup); 854EXPORT_SYMBOL_GPL(devm_kmemdup);
855
856struct pages_devres {
857 unsigned long addr;
858 unsigned int order;
859};
860
861static int devm_pages_match(struct device *dev, void *res, void *p)
862{
863 struct pages_devres *devres = res;
864 struct pages_devres *target = p;
865
866 return devres->addr == target->addr;
867}
868
869static void devm_pages_release(struct device *dev, void *res)
870{
871 struct pages_devres *devres = res;
872
873 free_pages(devres->addr, devres->order);
874}
875
876/**
877 * devm_get_free_pages - Resource-managed __get_free_pages
878 * @dev: Device to allocate memory for
879 * @gfp_mask: Allocation gfp flags
880 * @order: Allocation size is (1 << order) pages
881 *
882 * Managed get_free_pages. Memory allocated with this function is
883 * automatically freed on driver detach.
884 *
885 * RETURNS:
886 * Address of allocated memory on success, 0 on failure.
887 */
888
889unsigned long devm_get_free_pages(struct device *dev,
890 gfp_t gfp_mask, unsigned int order)
891{
892 struct pages_devres *devres;
893 unsigned long addr;
894
895 addr = __get_free_pages(gfp_mask, order);
896
897 if (unlikely(!addr))
898 return 0;
899
900 devres = devres_alloc(devm_pages_release,
901 sizeof(struct pages_devres), GFP_KERNEL);
902 if (unlikely(!devres)) {
903 free_pages(addr, order);
904 return 0;
905 }
906
907 devres->addr = addr;
908 devres->order = order;
909
910 devres_add(dev, devres);
911 return addr;
912}
913EXPORT_SYMBOL_GPL(devm_get_free_pages);
914
915/**
916 * devm_free_pages - Resource-managed free_pages
917 * @dev: Device this memory belongs to
918 * @addr: Memory to free
919 *
920 * Free memory allocated with devm_get_free_pages(). Unlike free_pages,
921 * there is no need to supply the @order.
922 */
923void devm_free_pages(struct device *dev, unsigned long addr)
924{
925 struct pages_devres devres = { .addr = addr };
926
927 WARN_ON(devres_release(dev, devm_pages_release, devm_pages_match,
928 &devres));
929}
930EXPORT_SYMBOL_GPL(devm_free_pages);