Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 161036
b: refs/heads/master
c: 163f52b
h: refs/heads/master
v: v3
  • Loading branch information
James Bottomley authored and James Bottomley committed Aug 22, 2009
1 parent bd9aa1c commit 0c0c73d
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 18 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0124ca9d8ee58b3cd028a23cef2fe225fcfee3b8
refs/heads/master: 163f52b6cf3a639df6a72c7937e0eb88b20f1ef3
44 changes: 32 additions & 12 deletions trunk/drivers/misc/enclosure.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 6 additions & 4 deletions trunk/drivers/scsi/ses.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,10 +413,11 @@ static int ses_intf_add(struct device *cdev,

if (!scsi_device_enclosure(sdev)) {
/* not an enclosure, but might be in one */
edev = enclosure_find(&sdev->host->shost_gendev);
if (edev) {
struct enclosure_device *prev = NULL;

while ((edev = enclosure_find(&sdev->host->shost_gendev, prev)) != NULL) {
ses_match_to_enclosure(edev, sdev);
put_device(&edev->edev);
prev = edev;
}
return -ENODEV;
}
Expand Down Expand Up @@ -625,7 +626,8 @@ static void ses_intf_remove(struct device *cdev,
if (!scsi_device_enclosure(sdev))
return;

edev = enclosure_find(cdev->parent);
/* exact match to this enclosure */
edev = enclosure_find(cdev->parent, NULL);
if (!edev)
return;

Expand Down
3 changes: 2 additions & 1 deletion trunk/include/linux/enclosure.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ enclosure_component_register(struct enclosure_device *, unsigned int,
int enclosure_add_device(struct enclosure_device *enclosure, int component,
struct device *dev);
int enclosure_remove_device(struct enclosure_device *enclosure, int component);
struct enclosure_device *enclosure_find(struct device *dev);
struct enclosure_device *enclosure_find(struct device *dev,
struct enclosure_device *start);
int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *),
void *data);

Expand Down

0 comments on commit 0c0c73d

Please sign in to comment.