driver core: devres: introduce devres_for_each_res
authorMing Lei <ming.lei@canonical.com>
Sat, 4 Aug 2012 04:01:26 +0000 (12:01 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 16 Aug 2012 20:30:29 +0000 (13:30 -0700)
This patch introduces one devres API of devres_for_each_res
so that the device's driver can iterate each resource it has
interest in.

The firmware loader will use the API to get each firmware name
from the device instance.

Signed-off-by: Ming Lei <ming.lei@canonical.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/base/devres.c
include/linux/device.h

index 2360adb7a58f0b924402169edba8936e1257ee3f..8731979d668a0592cc966191f8af1df9ab155a60 100644 (file)
@@ -143,6 +143,48 @@ void * devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
 EXPORT_SYMBOL_GPL(devres_alloc);
 #endif
 
+/**
+ * devres_for_each_res - Resource iterator
+ * @dev: Device to iterate resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ * @fn: Function to be called for each matched resource.
+ * @data: Data for @fn, the 3rd parameter of @fn
+ *
+ * Call @fn for each devres of @dev which is associated with @release
+ * and for which @match returns 1.
+ *
+ * RETURNS:
+ *     void
+ */
+void devres_for_each_res(struct device *dev, dr_release_t release,
+                       dr_match_t match, void *match_data,
+                       void (*fn)(struct device *, void *, void *),
+                       void *data)
+{
+       struct devres_node *node;
+       struct devres_node *tmp;
+       unsigned long flags;
+
+       if (!fn)
+               return;
+
+       spin_lock_irqsave(&dev->devres_lock, flags);
+       list_for_each_entry_safe_reverse(node, tmp,
+                       &dev->devres_head, entry) {
+               struct devres *dr = container_of(node, struct devres, node);
+
+               if (node->release != release)
+                       continue;
+               if (match && !match(dev, dr->data, match_data))
+                       continue;
+               fn(dev, dr->data, data);
+       }
+       spin_unlock_irqrestore(&dev->devres_lock, flags);
+}
+EXPORT_SYMBOL_GPL(devres_for_each_res);
+
 /**
  * devres_free - Free device resource data
  * @res: Pointer to devres data to free
index 52a5f15a2223ecb916391138ca9cb44f5d5d108a..ecd900663726397a185ba4586f123f17e8d1fccb 100644 (file)
@@ -536,6 +536,10 @@ extern void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
 #else
 extern void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp);
 #endif
+extern void devres_for_each_res(struct device *dev, dr_release_t release,
+                               dr_match_t match, void *match_data,
+                               void (*fn)(struct device *, void *, void *),
+                               void *data);
 extern void devres_free(void *res);
 extern void devres_add(struct device *dev, void *res);
 extern void *devres_find(struct device *dev, dr_release_t release,