Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43339bed authored by Eli Billauer's avatar Eli Billauer Committed by Greg Kroah-Hartman
Browse files

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: default avatarEli Billauer <eli.billauer@gmail.com>
Acked-by: default avatarTejun Heo <tj@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 8ffca9ea
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -237,6 +237,8 @@ MEM
  devm_kzalloc()
  devm_kfree()
  devm_kmemdup()
  devm_get_free_pages()
  devm_free_pages()

IIO
  devm_iio_device_alloc()
+76 −0
Original line number Diff line number Diff line
@@ -852,3 +852,79 @@ void *devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp)
	return p;
}
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);
+4 −0
Original line number Diff line number Diff line
@@ -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,
			  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_request_and_ioremap(struct device *dev,
			struct resource *res);