|
@@ -33,24 +33,44 @@ static DEFINE_MUTEX(container_list_lock);
|
|
|
static struct class enclosure_class;
|
|
|
|
|
|
/**
|
|
|
- * enclosure_find - find an enclosure given a device
|
|
|
- * @dev: the device to find for
|
|
|
+ * enclosure_find - find an enclosure given a parent device
|
|
|
+ * @dev: the parent to match against
|
|
|
+ * @start: Optional enclosure device to start from (NULL if none)
|
|
|
*
|
|
|
- * Looks through the list of registered enclosures to see
|
|
|
- * if it can find a match for a device. Returns NULL if no
|
|
|
- * enclosure is found. Obtains a reference to the enclosure class
|
|
|
- * device which must be released with device_put().
|
|
|
+ * Looks through the list of registered enclosures to find all those
|
|
|
+ * with @dev as a parent. Returns NULL if no enclosure is
|
|
|
+ * found. @start can be used as a starting point to obtain multiple
|
|
|
+ * enclosures per parent (should begin with NULL and then be set to
|
|
|
+ * each returned enclosure device). Obtains a reference to the
|
|
|
+ * enclosure class device which must be released with device_put().
|
|
|
+ * If @start is not NULL, a reference must be taken on it which is
|
|
|
+ * released before returning (this allows a loop through all
|
|
|
+ * enclosures to exit with only the reference on the enclosure of
|
|
|
+ * interest held). Note that the @dev may correspond to the actual
|
|
|
+ * device housing the enclosure, in which case no iteration via @start
|
|
|
+ * is required.
|
|
|
*/
|
|
|
-struct enclosure_device *enclosure_find(struct device *dev)
|
|
|
+struct enclosure_device *enclosure_find(struct device *dev,
|
|
|
+ struct enclosure_device *start)
|
|
|
{
|
|
|
struct enclosure_device *edev;
|
|
|
|
|
|
mutex_lock(&container_list_lock);
|
|
|
- list_for_each_entry(edev, &container_list, node) {
|
|
|
- if (edev->edev.parent == dev) {
|
|
|
- get_device(&edev->edev);
|
|
|
- mutex_unlock(&container_list_lock);
|
|
|
- return edev;
|
|
|
+ edev = list_prepare_entry(start, &container_list, node);
|
|
|
+ if (start)
|
|
|
+ put_device(&start->edev);
|
|
|
+
|
|
|
+ list_for_each_entry_continue(edev, &container_list, node) {
|
|
|
+ struct device *parent = edev->edev.parent;
|
|
|
+ /* parent might not be immediate, so iterate up to
|
|
|
+ * the root of the tree if necessary */
|
|
|
+ while (parent) {
|
|
|
+ if (parent == dev) {
|
|
|
+ get_device(&edev->edev);
|
|
|
+ mutex_unlock(&container_list_lock);
|
|
|
+ return edev;
|
|
|
+ }
|
|
|
+ parent = parent->parent;
|
|
|
}
|
|
|
}
|
|
|
mutex_unlock(&container_list_lock);
|