diff options
-rw-r--r-- | drivers/misc/enclosure.c | 22 | ||||
-rw-r--r-- | drivers/scsi/ses.c | 33 | ||||
-rw-r--r-- | include/linux/enclosure.h | 2 |
3 files changed, 41 insertions, 16 deletions
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c index 789d12128c24..850706a5e553 100644 --- a/drivers/misc/enclosure.c +++ b/drivers/misc/enclosure.c | |||
@@ -332,19 +332,25 @@ EXPORT_SYMBOL_GPL(enclosure_add_device); | |||
332 | * Returns zero on success or an error. | 332 | * Returns zero on success or an error. |
333 | * | 333 | * |
334 | */ | 334 | */ |
335 | int enclosure_remove_device(struct enclosure_device *edev, int component) | 335 | int enclosure_remove_device(struct enclosure_device *edev, struct device *dev) |
336 | { | 336 | { |
337 | struct enclosure_component *cdev; | 337 | struct enclosure_component *cdev; |
338 | int i; | ||
338 | 339 | ||
339 | if (!edev || component >= edev->components) | 340 | if (!edev || !dev) |
340 | return -EINVAL; | 341 | return -EINVAL; |
341 | 342 | ||
342 | cdev = &edev->component[component]; | 343 | for (i = 0; i < edev->components; i++) { |
343 | 344 | cdev = &edev->component[i]; | |
344 | device_del(&cdev->cdev); | 345 | if (cdev->dev == dev) { |
345 | put_device(cdev->dev); | 346 | enclosure_remove_links(cdev); |
346 | cdev->dev = NULL; | 347 | device_del(&cdev->cdev); |
347 | return device_add(&cdev->cdev); | 348 | put_device(dev); |
349 | cdev->dev = NULL; | ||
350 | return device_add(&cdev->cdev); | ||
351 | } | ||
352 | } | ||
353 | return -ENODEV; | ||
348 | } | 354 | } |
349 | EXPORT_SYMBOL_GPL(enclosure_remove_device); | 355 | EXPORT_SYMBOL_GPL(enclosure_remove_device); |
350 | 356 | ||
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index e1b8c828f03a..be593c8525b5 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c | |||
@@ -616,18 +616,26 @@ static int ses_remove(struct device *dev) | |||
616 | return 0; | 616 | return 0; |
617 | } | 617 | } |
618 | 618 | ||
619 | static void ses_intf_remove(struct device *cdev, | 619 | static void ses_intf_remove_component(struct scsi_device *sdev) |
620 | struct class_interface *intf) | 620 | { |
621 | struct enclosure_device *edev, *prev = NULL; | ||
622 | |||
623 | while ((edev = enclosure_find(&sdev->host->shost_gendev, prev)) != NULL) { | ||
624 | prev = edev; | ||
625 | if (!enclosure_remove_device(edev, &sdev->sdev_gendev)) | ||
626 | break; | ||
627 | } | ||
628 | if (edev) | ||
629 | put_device(&edev->edev); | ||
630 | } | ||
631 | |||
632 | static void ses_intf_remove_enclosure(struct scsi_device *sdev) | ||
621 | { | 633 | { |
622 | struct scsi_device *sdev = to_scsi_device(cdev->parent); | ||
623 | struct enclosure_device *edev; | 634 | struct enclosure_device *edev; |
624 | struct ses_device *ses_dev; | 635 | struct ses_device *ses_dev; |
625 | 636 | ||
626 | if (!scsi_device_enclosure(sdev)) | ||
627 | return; | ||
628 | |||
629 | /* exact match to this enclosure */ | 637 | /* exact match to this enclosure */ |
630 | edev = enclosure_find(cdev->parent, NULL); | 638 | edev = enclosure_find(&sdev->sdev_gendev, NULL); |
631 | if (!edev) | 639 | if (!edev) |
632 | return; | 640 | return; |
633 | 641 | ||
@@ -645,6 +653,17 @@ static void ses_intf_remove(struct device *cdev, | |||
645 | enclosure_unregister(edev); | 653 | enclosure_unregister(edev); |
646 | } | 654 | } |
647 | 655 | ||
656 | static void ses_intf_remove(struct device *cdev, | ||
657 | struct class_interface *intf) | ||
658 | { | ||
659 | struct scsi_device *sdev = to_scsi_device(cdev->parent); | ||
660 | |||
661 | if (!scsi_device_enclosure(sdev)) | ||
662 | ses_intf_remove_component(sdev); | ||
663 | else | ||
664 | ses_intf_remove_enclosure(sdev); | ||
665 | } | ||
666 | |||
648 | static struct class_interface ses_interface = { | 667 | static struct class_interface ses_interface = { |
649 | .add_dev = ses_intf_add, | 668 | .add_dev = ses_intf_add, |
650 | .remove_dev = ses_intf_remove, | 669 | .remove_dev = ses_intf_remove, |
diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h index d77811e9ed84..90d1c2184112 100644 --- a/include/linux/enclosure.h +++ b/include/linux/enclosure.h | |||
@@ -122,7 +122,7 @@ enclosure_component_register(struct enclosure_device *, unsigned int, | |||
122 | enum enclosure_component_type, const char *); | 122 | enum enclosure_component_type, const char *); |
123 | int enclosure_add_device(struct enclosure_device *enclosure, int component, | 123 | int enclosure_add_device(struct enclosure_device *enclosure, int component, |
124 | struct device *dev); | 124 | struct device *dev); |
125 | int enclosure_remove_device(struct enclosure_device *enclosure, int component); | 125 | int enclosure_remove_device(struct enclosure_device *, struct device *); |
126 | struct enclosure_device *enclosure_find(struct device *dev, | 126 | struct enclosure_device *enclosure_find(struct device *dev, |
127 | struct enclosure_device *start); | 127 | struct enclosure_device *start); |
128 | int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *), | 128 | int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *), |