Commit d926d0e4c74cfcb42a05e91d1cdf698b41e1e118

Authored by Mark Brown
Committed by Greg Kroah-Hartman
1 parent 698cd2ddd8

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>

Showing 2 changed files with 33 additions and 0 deletions Side-by-side Diff

drivers/base/devres.c
... ... @@ -330,6 +330,37 @@
330 330 }
331 331 EXPORT_SYMBOL_GPL(devres_destroy);
332 332  
  333 +
  334 +/**
  335 + * devres_release - Find a device resource and destroy it, calling release
  336 + * @dev: Device to find resource from
  337 + * @release: Look for resources associated with this release function
  338 + * @match: Match function (optional)
  339 + * @match_data: Data for the match function
  340 + *
  341 + * Find the latest devres of @dev associated with @release and for
  342 + * which @match returns 1. If @match is NULL, it's considered to
  343 + * match all. If found, the resource is removed atomically, the
  344 + * release function called and the resource freed.
  345 + *
  346 + * RETURNS:
  347 + * 0 if devres is found and freed, -ENOENT if not found.
  348 + */
  349 +int devres_release(struct device *dev, dr_release_t release,
  350 + dr_match_t match, void *match_data)
  351 +{
  352 + void *res;
  353 +
  354 + res = devres_remove(dev, release, match, match_data);
  355 + if (unlikely(!res))
  356 + return -ENOENT;
  357 +
  358 + (*release)(dev, res);
  359 + devres_free(res);
  360 + return 0;
  361 +}
  362 +EXPORT_SYMBOL_GPL(devres_release);
  363 +
333 364 static int remove_nodes(struct device *dev,
334 365 struct list_head *first, struct list_head *end,
335 366 struct list_head *todo)
include/linux/device.h
... ... @@ -541,6 +541,8 @@
541 541 dr_match_t match, void *match_data);
542 542 extern int devres_destroy(struct device *dev, dr_release_t release,
543 543 dr_match_t match, void *match_data);
  544 +extern int devres_release(struct device *dev, dr_release_t release,
  545 + dr_match_t match, void *match_data);
544 546  
545 547 /* devres group */
546 548 extern void * __must_check devres_open_group(struct device *dev, void *id,