X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Fscsi_sysfs.c;h=e7fe565b96de93ffb5354d4c86d36dfd46410806;hb=aa7677d40072a97a861390f0ed1a8c25ce312201;hp=72a6550a056c9dc14ba33f2383a04b7fb9711d99;hpb=9189674026e86e624b1ef1b4eb430e9ad19f9641;p=linux-2.6-omap-h63xx.git diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 72a6550a056..e7fe565b96d 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -6,7 +6,6 @@ * Created to pull SCSI mid layer sysfs routines into one file. */ -#include #include #include #include @@ -21,7 +20,7 @@ #include "scsi_priv.h" #include "scsi_logging.h" -static struct { +static const struct { enum scsi_device_state value; char *name; } sdev_states[] = { @@ -39,7 +38,7 @@ const char *scsi_device_state_name(enum scsi_device_state state) int i; char *name = NULL; - for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(sdev_states); i++) { if (sdev_states[i].value == state) { name = sdev_states[i].name; break; @@ -48,7 +47,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[] = { @@ -65,7 +64,7 @@ const char *scsi_host_state_name(enum scsi_host_state state) int i; char *name = NULL; - for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(shost_states); i++) { if (shost_states[i].value == state) { name = shost_states[i].name; break; @@ -106,7 +105,10 @@ static int scsi_scan(struct Scsi_Host *shost, const char *str) return -EINVAL; if (check_set(&lun, s3)) return -EINVAL; - res = scsi_scan_host_selected(shost, channel, id, lun, 1); + if (shost->transportt->user_scan) + res = shost->transportt->user_scan(shost, channel, id, lun); + else + res = scsi_scan_host_selected(shost, channel, id, lun, 1); return res; } @@ -157,7 +159,7 @@ store_shost_state(struct class_device *class_dev, const char *buf, size_t count) struct Scsi_Host *shost = class_to_shost(class_dev); enum scsi_host_state state = 0; - for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(shost_states); i++) { const int len = strlen(shost_states[i].name); if (strncmp(shost_states[i].name, buf, len) == 0 && buf[len] == '\n') { @@ -214,8 +216,9 @@ static void scsi_device_cls_release(struct class_device *class_dev) put_device(&sdev->sdev_gendev); } -static void scsi_device_dev_release(struct device *dev) +static void scsi_device_dev_release_usercontext(void *data) { + struct device *dev = data; struct scsi_device *sdev; struct device *parent; struct scsi_target *starget; @@ -234,6 +237,7 @@ static void scsi_device_dev_release(struct device *dev) if (sdev->request_queue) { sdev->request_queue->queuedata = NULL; + /* user context needed to free queue */ scsi_free_queue(sdev->request_queue); /* temporary expedient, try to catch use of queue lock * after free of sdev */ @@ -249,6 +253,13 @@ static void scsi_device_dev_release(struct device *dev) put_device(parent); } +static void scsi_device_dev_release(struct device *dev) +{ + struct scsi_device *sdp = to_scsi_device(dev); + execute_in_process_context(scsi_device_dev_release_usercontext, dev, + &sdp->ew); +} + static struct class sdev_class = { .name = "scsi_device", .release = scsi_device_cls_release, @@ -263,9 +274,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, state); + + 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) @@ -423,7 +465,7 @@ store_state_field(struct device *dev, struct device_attribute *attr, const char struct scsi_device *sdev = to_scsi_device(dev); enum scsi_device_state state = 0; - for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(sdev_states); i++) { const int len = strlen(sdev_states[i].name); if (strncmp(sdev_states[i].name, buf, len) == 0 && buf[len] == '\n') { @@ -691,16 +733,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); } /** @@ -711,9 +756,9 @@ void scsi_remove_device(struct scsi_device *sdev) { struct Scsi_Host *shost = sdev->host; - down(&shost->scan_mutex); + mutex_lock(&shost->scan_mutex); __scsi_remove_device(sdev); - up(&shost->scan_mutex); + mutex_unlock(&shost->scan_mutex); } EXPORT_SYMBOL(scsi_remove_device);