devres: add devm_kmalloc() and friends (managed memory allocators)

devm_kmalloc() is identical to kmalloc() except that the memory
allocated with it is managed and will be automatically released
when the device is removed/unbound.

Likewise for the other variants.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Acked-by: Simon Glass <sjg@chromium.org>
master
Masahiro Yamada 9 years ago committed by Simon Glass
parent 608f26c51b
commit 2b07f6859a
  1. 34
      drivers/core/devres.c
  2. 44
      include/dm/device.h

@ -194,3 +194,37 @@ void devres_release_all(struct udevice *dev)
{
release_nodes(dev, &dev->devres_head, false);
}
/*
* Managed kmalloc/kfree
*/
static void devm_kmalloc_release(struct udevice *dev, void *res)
{
/* noop */
}
static int devm_kmalloc_match(struct udevice *dev, void *res, void *data)
{
return res == data;
}
void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp)
{
void *data;
data = _devres_alloc(devm_kmalloc_release, size, gfp);
if (unlikely(!data))
return NULL;
devres_add(dev, data);
return data;
}
void devm_kfree(struct udevice *dev, void *p)
{
int rc;
rc = devres_destroy(dev, devm_kmalloc_release, devm_kmalloc_match, p);
WARN_ON(rc);
}

@ -14,6 +14,8 @@
#include <dm/uclass-id.h>
#include <fdtdec.h>
#include <linker_lists.h>
#include <linux/compat.h>
#include <linux/kernel.h>
#include <linux/list.h>
struct driver_info;
@ -605,4 +607,46 @@ int devres_destroy(struct udevice *dev, dr_release_t release,
int devres_release(struct udevice *dev, dr_release_t release,
dr_match_t match, void *match_data);
/* managed devm_k.alloc/kfree for device drivers */
/**
* devm_kmalloc - Resource-managed kmalloc
* @dev: Device to allocate memory for
* @size: Allocation size
* @gfp: Allocation gfp flags
*
* Managed kmalloc. Memory allocated with this function is
* automatically freed on driver detach. Like all other devres
* resources, guaranteed alignment is unsigned long long.
*
* RETURNS:
* Pointer to allocated memory on success, NULL on failure.
*/
void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp);
static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp)
{
return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
}
static inline void *devm_kmalloc_array(struct udevice *dev,
size_t n, size_t size, gfp_t flags)
{
if (size != 0 && n > SIZE_MAX / size)
return NULL;
return devm_kmalloc(dev, n * size, flags);
}
static inline void *devm_kcalloc(struct udevice *dev,
size_t n, size_t size, gfp_t flags)
{
return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
}
/**
* devm_kfree - Resource-managed kfree
* @dev: Device this memory belongs to
* @p: Memory to free
*
* Free memory allocated with devm_kmalloc().
*/
void devm_kfree(struct udevice *dev, void *p);
#endif

Loading…
Cancel
Save