]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/scsi_sysfs.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bunk/trivial
[linux-2.6-omap-h63xx.git] / drivers / scsi / scsi_sysfs.c
index dae59d1da07a720b11f2f74b5696263a8d863e3b..15842b1f0f4a3499f20a06f6529fa5e38e4ca917 100644 (file)
@@ -21,7 +21,7 @@
 #include "scsi_priv.h"
 #include "scsi_logging.h"
 
-static struct {
+static const struct {
        enum scsi_device_state  value;
        char                    *name;
 } sdev_states[] = {
@@ -48,7 +48,7 @@ const char *scsi_device_state_name(enum scsi_device_state state)
        return name;
 }
 
-static struct {
+static const struct {
        enum scsi_host_state    value;
        char                    *name;
 } shost_states[] = {
@@ -57,6 +57,8 @@ static struct {
        { SHOST_CANCEL, "cancel" },
        { SHOST_DEL, "deleted" },
        { SHOST_RECOVERY, "recovery" },
+       { SHOST_CANCEL_RECOVERY, "cancel/recovery" },
+       { SHOST_DEL_RECOVERY, "deleted/recovery", },
 };
 const char *scsi_host_state_name(enum scsi_host_state state)
 {
@@ -653,7 +655,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
                        error = attr_add(&sdev->sdev_gendev,
                                        sdev->host->hostt->sdev_attrs[i]);
                        if (error) {
-                               scsi_remove_device(sdev);
+                               __scsi_remove_device(sdev);
                                goto out;
                        }
                }
@@ -667,7 +669,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
                                                        scsi_sysfs_sdev_attrs[i]);
                        error = device_create_file(&sdev->sdev_gendev, attr);
                        if (error) {
-                               scsi_remove_device(sdev);
+                               __scsi_remove_device(sdev);
                                goto out;
                        }
                }
@@ -687,6 +689,23 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
        return error;
 }
 
+void __scsi_remove_device(struct scsi_device *sdev)
+{
+       struct device *dev = &sdev->sdev_gendev;
+
+       if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
+               return;
+
+       class_device_unregister(&sdev->sdev_classdev);
+       transport_remove_device(dev);
+       device_del(dev);
+       scsi_device_set_state(sdev, SDEV_DEL);
+       if (sdev->host->hostt->slave_destroy)
+               sdev->host->hostt->slave_destroy(sdev);
+       transport_destroy_device(dev);
+       put_device(dev);
+}
+
 /**
  * scsi_remove_device - unregister a device from the scsi bus
  * @sdev:      scsi_device to unregister
@@ -696,17 +715,7 @@ void scsi_remove_device(struct scsi_device *sdev)
        struct Scsi_Host *shost = sdev->host;
 
        down(&shost->scan_mutex);
-       if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
-               goto out;
-
-       class_device_unregister(&sdev->sdev_classdev);
-       device_del(&sdev->sdev_gendev);
-       scsi_device_set_state(sdev, SDEV_DEL);
-       if (sdev->host->hostt->slave_destroy)
-               sdev->host->hostt->slave_destroy(sdev);
-       transport_unregister_device(&sdev->sdev_gendev);
-       put_device(&sdev->sdev_gendev);
-out:
+       __scsi_remove_device(sdev);
        up(&shost->scan_mutex);
 }
 EXPORT_SYMBOL(scsi_remove_device);
@@ -715,17 +724,20 @@ void __scsi_remove_target(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
        unsigned long flags;
-       struct scsi_device *sdev, *tmp;
+       struct scsi_device *sdev;
 
        spin_lock_irqsave(shost->host_lock, flags);
        starget->reap_ref++;
-       list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) {
+ restart:
+       list_for_each_entry(sdev, &shost->__devices, siblings) {
                if (sdev->channel != starget->channel ||
-                   sdev->id != starget->id)
+                   sdev->id != starget->id ||
+                   sdev->sdev_state == SDEV_DEL)
                        continue;
                spin_unlock_irqrestore(shost->host_lock, flags);
                scsi_remove_device(sdev);
                spin_lock_irqsave(shost->host_lock, flags);
+               goto restart;
        }
        spin_unlock_irqrestore(shost->host_lock, flags);
        scsi_target_reap(starget);