aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/enclosure.c44
-rw-r--r--drivers/scsi/ses.c10
-rw-r--r--include/linux/enclosure.h3
3 files changed, 40 insertions, 17 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);
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index 4f618f487356..e1b8c828f03a 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -413,10 +413,11 @@ static int ses_intf_add(struct device *cdev,
413 413
414 if (!scsi_device_enclosure(sdev)) { 414 if (!scsi_device_enclosure(sdev)) {
415 /* not an enclosure, but might be in one */ 415 /* not an enclosure, but might be in one */
416 edev = enclosure_find(&sdev->host->shost_gendev); 416 struct enclosure_device *prev = NULL;
417 if (edev) { 417
418 while ((edev = enclosure_find(&sdev->host->shost_gendev, prev)) != NULL) {
418 ses_match_to_enclosure(edev, sdev); 419 ses_match_to_enclosure(edev, sdev);
419 put_device(&edev->edev); 420 prev = edev;
420 } 421 }
421 return -ENODEV; 422 return -ENODEV;
422 } 423 }
@@ -625,7 +626,8 @@ static void ses_intf_remove(struct device *cdev,
625 if (!scsi_device_enclosure(sdev)) 626 if (!scsi_device_enclosure(sdev))
626 return; 627 return;
627 628
628 edev = enclosure_find(cdev->parent); 629 /* exact match to this enclosure */
630 edev = enclosure_find(cdev->parent, NULL);
629 if (!edev) 631 if (!edev)
630 return; 632 return;
631 633
diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h
index 4332442b1b57..d77811e9ed84 100644
--- a/include/linux/enclosure.h
+++ b/include/linux/enclosure.h
@@ -123,7 +123,8 @@ enclosure_component_register(struct enclosure_device *, unsigned int,
123int enclosure_add_device(struct enclosure_device *enclosure, int component, 123int enclosure_add_device(struct enclosure_device *enclosure, int component,
124 struct device *dev); 124 struct device *dev);
125int enclosure_remove_device(struct enclosure_device *enclosure, int component); 125int enclosure_remove_device(struct enclosure_device *enclosure, int component);
126struct enclosure_device *enclosure_find(struct device *dev); 126struct enclosure_device *enclosure_find(struct device *dev,
127 struct enclosure_device *start);
127int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *), 128int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *),
128 void *data); 129 void *data);
129 130