aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/enclosure.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/enclosure.c')
-rw-r--r--drivers/misc/enclosure.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 348443bdb23b..789d12128c24 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -33,24 +33,44 @@ static DEFINE_MUTEX(container_list_lock);
33static struct class enclosure_class; 33static struct class enclosure_class;
34 34
35/** 35/**
36 * enclosure_find - find an enclosure given a device 36 * enclosure_find - find an enclosure given a parent device
37 * @dev: the device to find for 37 * @dev: the parent to match against
38 * @start: Optional enclosure device to start from (NULL if none)
38 * 39 *
39 * Looks through the list of registered enclosures to see 40 * Looks through the list of registered enclosures to find all those
40 * if it can find a match for a device. Returns NULL if no 41 * with @dev as a parent. Returns NULL if no enclosure is
41 * enclosure is found. Obtains a reference to the enclosure class 42 * found. @start can be used as a starting point to obtain multiple
42 * device which must be released with device_put(). 43 * enclosures per parent (should begin with NULL and then be set to
44 * each returned enclosure device). Obtains a reference to the
45 * enclosure class device which must be released with device_put().
46 * If @start is not NULL, a reference must be taken on it which is
47 * released before returning (this allows a loop through all
48 * enclosures to exit with only the reference on the enclosure of
49 * interest held). Note that the @dev may correspond to the actual
50 * device housing the enclosure, in which case no iteration via @start
51 * is required.
43 */ 52 */
44struct enclosure_device *enclosure_find(struct device *dev) 53struct enclosure_device *enclosure_find(struct device *dev,
54 struct enclosure_device *start)
45{ 55{
46 struct enclosure_device *edev; 56 struct enclosure_device *edev;
47 57
48 mutex_lock(&container_list_lock); 58 mutex_lock(&container_list_lock);
49 list_for_each_entry(edev, &container_list, node) { 59 edev = list_prepare_entry(start, &container_list, node);
50 if (edev->edev.parent == dev) { 60 if (start)
51 get_device(&edev->edev); 61 put_device(&start->edev);
52 mutex_unlock(&container_list_lock); 62
53 return edev; 63 list_for_each_entry_continue(edev, &container_list, node) {
64 struct device *parent = edev->edev.parent;
65 /* parent might not be immediate, so iterate up to
66 * the root of the tree if necessary */
67 while (parent) {
68 if (parent == dev) {
69 get_device(&edev->edev);
70 mutex_unlock(&container_list_lock);
71 return edev;
72 }
73 parent = parent->parent;
54 } 74 }
55 } 75 }
56 mutex_unlock(&container_list_lock); 76 mutex_unlock(&container_list_lock);