diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-05-03 18:15:13 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-04 16:33:16 -0700 |
commit | d926d0e4c74cfcb42a05e91d1cdf698b41e1e118 (patch) | |
tree | 9d7cdc794f6c56ef728c751759d8ef639ee6f38f | |
parent | 698cd2ddd851b34e7200b4f846ae68306e11bae4 (diff) |
devres: Add devres_release()
APIs using devres frequently want to implement a "remove and free the
resource" operation so it seems sensible that they should be able to
just have devres do the freeing for them since that's a big part of what
devres is all about.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/base/devres.c | 31 | ||||
-rw-r--r-- | include/linux/device.h | 2 |
2 files changed, 33 insertions, 0 deletions
diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 1741a60de117..2360adb7a58f 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -330,6 +330,37 @@ int devres_destroy(struct device *dev, dr_release_t release, } EXPORT_SYMBOL_GPL(devres_destroy); + +/** + * 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. + * + * RETURNS: + * 0 if devres is found and freed, -ENOENT if not found. + */ +int devres_release(struct device *dev, dr_release_t release, + dr_match_t match, void *match_data) +{ + void *res; + + res = devres_remove(dev, release, match, match_data); + if (unlikely(!res)) + return -ENOENT; + + (*release)(dev, res); + devres_free(res); + return 0; +} +EXPORT_SYMBOL_GPL(devres_release); + static int remove_nodes(struct device *dev, struct list_head *first, struct list_head *end, struct list_head *todo) diff --git a/include/linux/device.h b/include/linux/device.h index 3ab4d63609b6..863acf8a0dce 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -541,6 +541,8 @@ extern void *devres_remove(struct device *dev, dr_release_t release, dr_match_t match, void *match_data); extern int devres_destroy(struct device *dev, dr_release_t release, dr_match_t match, void *match_data); +extern int devres_release(struct device *dev, dr_release_t release, + dr_match_t match, void *match_data); /* devres group */ extern void * __must_check devres_open_group(struct device *dev, void *id, |