aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/driver-model/devres.txt2
-rw-r--r--drivers/base/devres.c76
-rw-r--r--include/linux/device.h4
3 files changed, 82 insertions, 0 deletions
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 499951873997..e1a27074caae 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -237,6 +237,8 @@ MEM
237 devm_kzalloc() 237 devm_kzalloc()
238 devm_kfree() 238 devm_kfree()
239 devm_kmemdup() 239 devm_kmemdup()
240 devm_get_free_pages()
241 devm_free_pages()
240 242
241IIO 243IIO
242 devm_iio_device_alloc() 244 devm_iio_device_alloc()
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);
diff --git a/include/linux/device.h b/include/linux/device.h
index ab871588da89..3dc69a2faa51 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -626,6 +626,10 @@ extern char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp);
626extern void *devm_kmemdup(struct device *dev, const void *src, size_t len, 626extern void *devm_kmemdup(struct device *dev, const void *src, size_t len,
627 gfp_t gfp); 627 gfp_t gfp);
628 628
629extern unsigned long devm_get_free_pages(struct device *dev,
630 gfp_t gfp_mask, unsigned int order);
631extern void devm_free_pages(struct device *dev, unsigned long addr);
632
629void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res); 633void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);
630void __iomem *devm_request_and_ioremap(struct device *dev, 634void __iomem *devm_request_and_ioremap(struct device *dev,
631 struct resource *res); 635 struct resource *res);