X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Fscsi_sysfs.c;h=2cb962751a7ee76bbbe7f503a41a390cbc3004a6;hb=7686f132653fa3d52d45c3f021215f714094f1ca;hp=b8052d5206cca22f03a782044b9ca5b7d78f605f;hpb=033d974405276c22609c45d50167dd11df20aa82;p=linux-2.6-omap-h63xx.git diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index b8052d5206c..2cb962751a7 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -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) { @@ -261,9 +263,40 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; } +static int scsi_bus_suspend(struct device * dev, pm_message_t state) +{ + struct scsi_device *sdev = to_scsi_device(dev); + struct scsi_host_template *sht = sdev->host->hostt; + int err; + + err = scsi_device_quiesce(sdev); + if (err) + return err; + + if (sht->suspend) + err = sht->suspend(sdev); + + return err; +} + +static int scsi_bus_resume(struct device * dev) +{ + struct scsi_device *sdev = to_scsi_device(dev); + struct scsi_host_template *sht = sdev->host->hostt; + int err = 0; + + if (sht->resume) + err = sht->resume(sdev); + + scsi_device_resume(sdev); + return err; +} + struct bus_type scsi_bus_type = { .name = "scsi", .match = scsi_bus_match, + .suspend = scsi_bus_suspend, + .resume = scsi_bus_resume, }; int scsi_sysfs_register(void) @@ -689,16 +722,19 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) 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); - device_del(&sdev->sdev_gendev); + 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_unregister_device(&sdev->sdev_gendev); - put_device(&sdev->sdev_gendev); + transport_destroy_device(dev); + put_device(dev); } /** @@ -707,9 +743,11 @@ void __scsi_remove_device(struct scsi_device *sdev) **/ void scsi_remove_device(struct scsi_device *sdev) { - down(&sdev->host->scan_mutex); + struct Scsi_Host *shost = sdev->host; + + mutex_lock(&shost->scan_mutex); __scsi_remove_device(sdev); - up(&sdev->host->scan_mutex); + mutex_unlock(&shost->scan_mutex); } EXPORT_SYMBOL(scsi_remove_device); @@ -717,17 +755,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);