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>
This commit is contained in:
parent
8ffca9eae6
commit
43339bed70
|
@ -237,6 +237,8 @@ MEM
|
||||||
devm_kzalloc()
|
devm_kzalloc()
|
||||||
devm_kfree()
|
devm_kfree()
|
||||||
devm_kmemdup()
|
devm_kmemdup()
|
||||||
|
devm_get_free_pages()
|
||||||
|
devm_free_pages()
|
||||||
|
|
||||||
IIO
|
IIO
|
||||||
devm_iio_device_alloc()
|
devm_iio_device_alloc()
|
||||||
|
|
|
@ -852,3 +852,79 @@ void *devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_kmemdup);
|
EXPORT_SYMBOL_GPL(devm_kmemdup);
|
||||||
|
|
||||||
|
struct pages_devres {
|
||||||
|
unsigned long addr;
|
||||||
|
unsigned int order;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int devm_pages_match(struct device *dev, void *res, void *p)
|
||||||
|
{
|
||||||
|
struct pages_devres *devres = res;
|
||||||
|
struct pages_devres *target = p;
|
||||||
|
|
||||||
|
return devres->addr == target->addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void devm_pages_release(struct device *dev, void *res)
|
||||||
|
{
|
||||||
|
struct pages_devres *devres = res;
|
||||||
|
|
||||||
|
free_pages(devres->addr, devres->order);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_get_free_pages - Resource-managed __get_free_pages
|
||||||
|
* @dev: Device to allocate memory for
|
||||||
|
* @gfp_mask: Allocation gfp flags
|
||||||
|
* @order: Allocation size is (1 << order) pages
|
||||||
|
*
|
||||||
|
* Managed get_free_pages. Memory allocated with this function is
|
||||||
|
* automatically freed on driver detach.
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* Address of allocated memory on success, 0 on failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned long devm_get_free_pages(struct device *dev,
|
||||||
|
gfp_t gfp_mask, unsigned int order)
|
||||||
|
{
|
||||||
|
struct pages_devres *devres;
|
||||||
|
unsigned long addr;
|
||||||
|
|
||||||
|
addr = __get_free_pages(gfp_mask, order);
|
||||||
|
|
||||||
|
if (unlikely(!addr))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
devres = devres_alloc(devm_pages_release,
|
||||||
|
sizeof(struct pages_devres), GFP_KERNEL);
|
||||||
|
if (unlikely(!devres)) {
|
||||||
|
free_pages(addr, order);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
devres->addr = addr;
|
||||||
|
devres->order = order;
|
||||||
|
|
||||||
|
devres_add(dev, devres);
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_get_free_pages);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_free_pages - Resource-managed free_pages
|
||||||
|
* @dev: Device this memory belongs to
|
||||||
|
* @addr: Memory to free
|
||||||
|
*
|
||||||
|
* Free memory allocated with devm_get_free_pages(). Unlike free_pages,
|
||||||
|
* there is no need to supply the @order.
|
||||||
|
*/
|
||||||
|
void devm_free_pages(struct device *dev, unsigned long addr)
|
||||||
|
{
|
||||||
|
struct pages_devres devres = { .addr = addr };
|
||||||
|
|
||||||
|
WARN_ON(devres_release(dev, devm_pages_release, devm_pages_match,
|
||||||
|
&devres));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_free_pages);
|
||||||
|
|
|
@ -626,6 +626,10 @@ extern char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp);
|
||||||
extern void *devm_kmemdup(struct device *dev, const void *src, size_t len,
|
extern void *devm_kmemdup(struct device *dev, const void *src, size_t len,
|
||||||
gfp_t gfp);
|
gfp_t gfp);
|
||||||
|
|
||||||
|
extern unsigned long devm_get_free_pages(struct device *dev,
|
||||||
|
gfp_t gfp_mask, unsigned int order);
|
||||||
|
extern void devm_free_pages(struct device *dev, unsigned long addr);
|
||||||
|
|
||||||
void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);
|
void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);
|
||||||
void __iomem *devm_request_and_ioremap(struct device *dev,
|
void __iomem *devm_request_and_ioremap(struct device *dev,
|
||||||
struct resource *res);
|
struct resource *res);
|
||||||
|
|
Loading…
Reference in New Issue