From: Simon Glass Date: Mon, 30 Dec 2019 04:19:22 +0000 (-0700) Subject: dm: devres: Create a new devres header file X-Git-Url: http://git.dujemihanovic.xyz/%22http:/www.sics.se/static/git-favicon.png?a=commitdiff_plain;h=42a8db5c5ba8541b43a1aea439b3605195b122de;p=u-boot.git dm: devres: Create a new devres header file At present these functions are lumped in with the core device functions. They have their own #ifdef to control their availability, so it seems better to split them out. Move them into their own header file. Signed-off-by: Simon Glass --- diff --git a/include/dm/device.h b/include/dm/device.h index 9ebfd0a34e..1138a09149 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -720,260 +720,7 @@ static inline bool device_is_on_pci_bus(struct udevice *dev) */ int dm_scan_fdt_dev(struct udevice *dev); -/* device resource management */ -typedef void (*dr_release_t)(struct udevice *dev, void *res); -typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data); - -#ifdef CONFIG_DEVRES - -#ifdef CONFIG_DEBUG_DEVRES -void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp, - const char *name); -#define _devres_alloc(release, size, gfp) \ - __devres_alloc(release, size, gfp, #release) -#else -void *_devres_alloc(dr_release_t release, size_t size, gfp_t gfp); -#endif - -/** - * devres_alloc() - Allocate device resource data - * @release: Release function devres will be associated with - * @size: Allocation size - * @gfp: Allocation flags - * - * Allocate devres of @size bytes. The allocated area is associated - * with @release. The returned pointer can be passed to - * other devres_*() functions. - * - * RETURNS: - * Pointer to allocated devres on success, NULL on failure. - */ -#define devres_alloc(release, size, gfp) \ - _devres_alloc(release, size, gfp | __GFP_ZERO) - -/** - * devres_free() - Free device resource data - * @res: Pointer to devres data to free - * - * Free devres created with devres_alloc(). - */ -void devres_free(void *res); - -/** - * devres_add() - Register device resource - * @dev: Device to add resource to - * @res: Resource to register - * - * Register devres @res to @dev. @res should have been allocated - * using devres_alloc(). On driver detach, the associated release - * function will be invoked and devres will be freed automatically. - */ -void devres_add(struct udevice *dev, void *res); - -/** - * devres_find() - Find device resource - * @dev: Device to lookup resource from - * @release: Look for resources associated with this release function - * @match: Match function (optional) - * @match_data: Data for the match function - * - * Find the latest devres of @dev which is associated with @release - * and for which @match returns 1. If @match is NULL, it's considered - * to match all. - * - * @return pointer to found devres, NULL if not found. - */ -void *devres_find(struct udevice *dev, dr_release_t release, - dr_match_t match, void *match_data); - -/** - * devres_get() - Find devres, if non-existent, add one atomically - * @dev: Device to lookup or add devres for - * @new_res: Pointer to new initialized devres to add if not found - * @match: Match function (optional) - * @match_data: Data for the match function - * - * Find the latest devres of @dev which has the same release function - * as @new_res and for which @match return 1. If found, @new_res is - * freed; otherwise, @new_res is added atomically. - * - * @return ointer to found or added devres. - */ -void *devres_get(struct udevice *dev, void *new_res, - dr_match_t match, void *match_data); - -/** - * devres_remove() - Find a device resource and remove it - * @dev: Device to find resource from - * @release: Look for resources associated with this release function - * @match: Match function (optional) - * @match_data: Data for the match function - * - * Find the latest devres of @dev associated with @release and for - * which @match returns 1. If @match is NULL, it's considered to - * match all. If found, the resource is removed atomically and - * returned. - * - * @return ointer to removed devres on success, NULL if not found. - */ -void *devres_remove(struct udevice *dev, dr_release_t release, - dr_match_t match, void *match_data); - -/** - * devres_destroy() - Find a device resource and destroy it - * @dev: Device to find resource from - * @release: Look for resources associated with this release function - * @match: Match function (optional) - * @match_data: Data for the match function - * - * Find the latest devres of @dev associated with @release and for - * which @match returns 1. If @match is NULL, it's considered to - * match all. If found, the resource is removed atomically and freed. - * - * Note that the release function for the resource will not be called, - * only the devres-allocated data will be freed. The caller becomes - * responsible for freeing any other data. - * - * @return 0 if devres is found and freed, -ENOENT if not found. - */ -int devres_destroy(struct udevice *dev, dr_release_t release, - dr_match_t match, void *match_data); - -/** - * devres_release() - Find a device resource and destroy it, calling release - * @dev: Device to find resource from - * @release: Look for resources associated with this release function - * @match: Match function (optional) - * @match_data: Data for the match function - * - * Find the latest devres of @dev associated with @release and for - * which @match returns 1. If @match is NULL, it's considered to - * match all. If found, the resource is removed atomically, the - * release function called and the resource freed. - * - * @return 0 if devres is found and freed, -ENOENT if not found. - */ -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. - * - * @return 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 - * @ptr: Memory to free - * - * Free memory allocated with devm_kmalloc(). - */ -void devm_kfree(struct udevice *dev, void *ptr); - -#else /* ! CONFIG_DEVRES */ - -static inline void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp) -{ - return kzalloc(size, gfp); -} - -static inline void devres_free(void *res) -{ - kfree(res); -} - -static inline void devres_add(struct udevice *dev, void *res) -{ -} - -static inline void *devres_find(struct udevice *dev, dr_release_t release, - dr_match_t match, void *match_data) -{ - return NULL; -} - -static inline void *devres_get(struct udevice *dev, void *new_res, - dr_match_t match, void *match_data) -{ - return NULL; -} - -static inline void *devres_remove(struct udevice *dev, dr_release_t release, - dr_match_t match, void *match_data) -{ - return NULL; -} - -static inline int devres_destroy(struct udevice *dev, dr_release_t release, - dr_match_t match, void *match_data) -{ - return 0; -} - -static inline int devres_release(struct udevice *dev, dr_release_t release, - dr_match_t match, void *match_data) -{ - return 0; -} - -static inline void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp) -{ - return kmalloc(size, gfp); -} - -static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp) -{ - return kzalloc(size, gfp); -} - -static inline void *devm_kmalloc_array(struct udevice *dev, - size_t n, size_t size, gfp_t flags) -{ - /* TODO: add kmalloc_array() to linux/compat.h */ - if (size != 0 && n > SIZE_MAX / size) - return NULL; - return kmalloc(n * size, flags); -} - -static inline void *devm_kcalloc(struct udevice *dev, - size_t n, size_t size, gfp_t flags) -{ - /* TODO: add kcalloc() to linux/compat.h */ - return kmalloc(n * size, flags | __GFP_ZERO); -} - -static inline void devm_kfree(struct udevice *dev, void *ptr) -{ - kfree(ptr); -} - -#endif /* ! CONFIG_DEVRES */ +#include /* * REVISIT: diff --git a/include/dm/devres.h b/include/dm/devres.h new file mode 100644 index 0000000000..32fbf38054 --- /dev/null +++ b/include/dm/devres.h @@ -0,0 +1,269 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2015 Masahiro Yamada + * + * Based on the original work in Linux by + * Copyright (c) 2006 SUSE Linux Products GmbH + * Copyright (c) 2006 Tejun Heo + * Copyright 2019 Google LLC + */ + +#ifndef _DM_DEVRES_H +#define _DM_DEVRES_H + +/* device resource management */ +typedef void (*dr_release_t)(struct udevice *dev, void *res); +typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data); + +#ifdef CONFIG_DEVRES + +#ifdef CONFIG_DEBUG_DEVRES +void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp, + const char *name); +#define _devres_alloc(release, size, gfp) \ + __devres_alloc(release, size, gfp, #release) +#else +void *_devres_alloc(dr_release_t release, size_t size, gfp_t gfp); +#endif + +/** + * devres_alloc() - Allocate device resource data + * @release: Release function devres will be associated with + * @size: Allocation size + * @gfp: Allocation flags + * + * Allocate devres of @size bytes. The allocated area is associated + * with @release. The returned pointer can be passed to + * other devres_*() functions. + * + * RETURNS: + * Pointer to allocated devres on success, NULL on failure. + */ +#define devres_alloc(release, size, gfp) \ + _devres_alloc(release, size, (gfp) | __GFP_ZERO) + +/** + * devres_free() - Free device resource data + * @res: Pointer to devres data to free + * + * Free devres created with devres_alloc(). + */ +void devres_free(void *res); + +/** + * devres_add() - Register device resource + * @dev: Device to add resource to + * @res: Resource to register + * + * Register devres @res to @dev. @res should have been allocated + * using devres_alloc(). On driver detach, the associated release + * function will be invoked and devres will be freed automatically. + */ +void devres_add(struct udevice *dev, void *res); + +/** + * devres_find() - Find device resource + * @dev: Device to lookup resource from + * @release: Look for resources associated with this release function + * @match: Match function (optional) + * @match_data: Data for the match function + * + * Find the latest devres of @dev which is associated with @release + * and for which @match returns 1. If @match is NULL, it's considered + * to match all. + * + * @return pointer to found devres, NULL if not found. + */ +void *devres_find(struct udevice *dev, dr_release_t release, + dr_match_t match, void *match_data); + +/** + * devres_get() - Find devres, if non-existent, add one atomically + * @dev: Device to lookup or add devres for + * @new_res: Pointer to new initialized devres to add if not found + * @match: Match function (optional) + * @match_data: Data for the match function + * + * Find the latest devres of @dev which has the same release function + * as @new_res and for which @match return 1. If found, @new_res is + * freed; otherwise, @new_res is added atomically. + * + * @return ointer to found or added devres. + */ +void *devres_get(struct udevice *dev, void *new_res, + dr_match_t match, void *match_data); + +/** + * devres_remove() - Find a device resource and remove it + * @dev: Device to find resource from + * @release: Look for resources associated with this release function + * @match: Match function (optional) + * @match_data: Data for the match function + * + * Find the latest devres of @dev associated with @release and for + * which @match returns 1. If @match is NULL, it's considered to + * match all. If found, the resource is removed atomically and + * returned. + * + * @return ointer to removed devres on success, NULL if not found. + */ +void *devres_remove(struct udevice *dev, dr_release_t release, + dr_match_t match, void *match_data); + +/** + * devres_destroy() - Find a device resource and destroy it + * @dev: Device to find resource from + * @release: Look for resources associated with this release function + * @match: Match function (optional) + * @match_data: Data for the match function + * + * Find the latest devres of @dev associated with @release and for + * which @match returns 1. If @match is NULL, it's considered to + * match all. If found, the resource is removed atomically and freed. + * + * Note that the release function for the resource will not be called, + * only the devres-allocated data will be freed. The caller becomes + * responsible for freeing any other data. + * + * @return 0 if devres is found and freed, -ENOENT if not found. + */ +int devres_destroy(struct udevice *dev, dr_release_t release, + dr_match_t match, void *match_data); + +/** + * devres_release() - Find a device resource and destroy it, calling release + * @dev: Device to find resource from + * @release: Look for resources associated with this release function + * @match: Match function (optional) + * @match_data: Data for the match function + * + * Find the latest devres of @dev associated with @release and for + * which @match returns 1. If @match is NULL, it's considered to + * match all. If found, the resource is removed atomically, the + * release function called and the resource freed. + * + * @return 0 if devres is found and freed, -ENOENT if not found. + */ +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. + * + * @return 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 + * @ptr: Memory to free + * + * Free memory allocated with devm_kmalloc(). + */ +void devm_kfree(struct udevice *dev, void *ptr); + +#else /* ! CONFIG_DEVRES */ + +static inline void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp) +{ + return kzalloc(size, gfp); +} + +static inline void devres_free(void *res) +{ + kfree(res); +} + +static inline void devres_add(struct udevice *dev, void *res) +{ +} + +static inline void *devres_find(struct udevice *dev, dr_release_t release, + dr_match_t match, void *match_data) +{ + return NULL; +} + +static inline void *devres_get(struct udevice *dev, void *new_res, + dr_match_t match, void *match_data) +{ + return NULL; +} + +static inline void *devres_remove(struct udevice *dev, dr_release_t release, + dr_match_t match, void *match_data) +{ + return NULL; +} + +static inline int devres_destroy(struct udevice *dev, dr_release_t release, + dr_match_t match, void *match_data) +{ + return 0; +} + +static inline int devres_release(struct udevice *dev, dr_release_t release, + dr_match_t match, void *match_data) +{ + return 0; +} + +static inline void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp) +{ + return kmalloc(size, gfp); +} + +static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp) +{ + return kzalloc(size, gfp); +} + +static inline void *devm_kmalloc_array(struct udevice *dev, + size_t n, size_t size, gfp_t flags) +{ + /* TODO: add kmalloc_array() to linux/compat.h */ + if (size != 0 && n > SIZE_MAX / size) + return NULL; + return kmalloc(n * size, flags); +} + +static inline void *devm_kcalloc(struct udevice *dev, + size_t n, size_t size, gfp_t flags) +{ + /* TODO: add kcalloc() to linux/compat.h */ + return kmalloc(n * size, flags | __GFP_ZERO); +} + +static inline void devm_kfree(struct udevice *dev, void *ptr) +{ + kfree(ptr); +} +#endif /* DEVRES */ +#endif /* _DM_DEVRES_H */