driver core: devres: introduce devres_for_each_res
[firefly-linux-kernel-4.4.55.git] / drivers / base / devres.c
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