Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Eli Billauer and committed by
Greg Kroah-Hartman
43339bed 8ffca9ea

+82
+2
Documentation/driver-model/devres.txt
··· 237 237 devm_kzalloc() 238 238 devm_kfree() 239 239 devm_kmemdup() 240 + devm_get_free_pages() 241 + devm_free_pages() 240 242 241 243 IIO 242 244 devm_iio_device_alloc()
+76
drivers/base/devres.c
··· 852 852 return p; 853 853 } 854 854 EXPORT_SYMBOL_GPL(devm_kmemdup); 855 + 856 + struct pages_devres { 857 + unsigned long addr; 858 + unsigned int order; 859 + }; 860 + 861 + static 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 + 869 + static 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 + 889 + unsigned 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 + } 913 + EXPORT_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 + */ 923 + void 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 + } 930 + EXPORT_SYMBOL_GPL(devm_free_pages);
+4
include/linux/device.h
··· 626 626 extern void *devm_kmemdup(struct device *dev, const void *src, size_t len, 627 627 gfp_t gfp); 628 628 629 + extern unsigned long devm_get_free_pages(struct device *dev, 630 + gfp_t gfp_mask, unsigned int order); 631 + extern void devm_free_pages(struct device *dev, unsigned long addr); 632 + 629 633 void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res); 630 634 void __iomem *devm_request_and_ioremap(struct device *dev, 631 635 struct resource *res);