diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_spi.c')
| -rw-r--r-- | drivers/scsi/scsi_transport_spi.c | 325 |
1 files changed, 200 insertions, 125 deletions
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 1fb60313a51..cf08071a9b6 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -24,6 +24,8 @@ #include <linux/workqueue.h> #include <linux/blkdev.h> #include <linux/mutex.h> +#include <linux/sysfs.h> +#include <linux/slab.h> #include <scsi/scsi.h> #include "scsi_priv.h" #include <scsi/scsi_device.h> @@ -45,6 +47,22 @@ #define DV_RETRIES 3 /* should only need at most * two cc/ua clears */ +/* Our blacklist flags */ +enum { + SPI_BLIST_NOIUS = 0x1, +}; + +/* blacklist table, modelled on scsi_devinfo.c */ +static struct { + char *vendor; + char *model; + unsigned flags; +} spi_static_device_list[] __initdata = { + {"HP", "Ultrium 3-SCSI", SPI_BLIST_NOIUS }, + {"IBM", "ULTRIUM-TD3", SPI_BLIST_NOIUS }, + {NULL, NULL, 0} +}; + /* Private data accessors (keep these out of the header file) */ #define spi_dv_in_progress(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_in_progress) #define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex) @@ -108,8 +126,11 @@ static int spi_execute(struct scsi_device *sdev, const void *cmd, for(i = 0; i < DV_RETRIES; i++) { result = scsi_execute(sdev, cmd, dir, buffer, bufflen, sense, DV_TIMEOUT, /* retries */ 1, - REQ_FAILFAST); - if (result & DRIVER_SENSE) { + REQ_FAILFAST_DEV | + REQ_FAILFAST_TRANSPORT | + REQ_FAILFAST_DRIVER, + NULL); + if (driver_byte(result) & DRIVER_SENSE) { struct scsi_sense_hdr sshdr_tmp; if (!sshdr) sshdr = &sshdr_tmp; @@ -158,7 +179,7 @@ static inline enum spi_signal_type spi_signal_to_value(const char *name) } static int spi_host_setup(struct transport_container *tc, struct device *dev, - struct class_device *cdev) + struct device *cdev) { struct Scsi_Host *shost = dev_to_shost(dev); @@ -169,7 +190,7 @@ static int spi_host_setup(struct transport_container *tc, struct device *dev, static int spi_host_configure(struct transport_container *tc, struct device *dev, - struct class_device *cdev); + struct device *cdev); static DECLARE_TRANSPORT_CLASS(spi_host_class, "spi_host", @@ -195,14 +216,17 @@ static int spi_host_match(struct attribute_container *cont, static int spi_target_configure(struct transport_container *tc, struct device *dev, - struct class_device *cdev); + struct device *cdev); static int spi_device_configure(struct transport_container *tc, struct device *dev, - struct class_device *cdev) + struct device *cdev) { struct scsi_device *sdev = to_scsi_device(dev); struct scsi_target *starget = sdev->sdev_target; + unsigned bflags = scsi_get_device_flags_keyed(sdev, &sdev->inquiry[8], + &sdev->inquiry[16], + SCSI_DEVINFO_SPI); /* Populate the target capability fields with the values * gleaned from the device inquiry */ @@ -212,6 +236,10 @@ static int spi_device_configure(struct transport_container *tc, spi_support_dt(starget) = scsi_device_dt(sdev); spi_support_dt_only(starget) = scsi_device_dt_only(sdev); spi_support_ius(starget) = scsi_device_ius(sdev); + if (bflags & SPI_BLIST_NOIUS) { + dev_info(dev, "Information Units disabled by blacklist\n"); + spi_support_ius(starget) = 0; + } spi_support_qas(starget) = scsi_device_qas(sdev); return 0; @@ -219,7 +247,7 @@ static int spi_device_configure(struct transport_container *tc, static int spi_setup_transport_attrs(struct transport_container *tc, struct device *dev, - struct class_device *cdev) + struct device *cdev) { struct scsi_target *starget = to_scsi_target(dev); @@ -230,8 +258,10 @@ static int spi_setup_transport_attrs(struct transport_container *tc, spi_width(starget) = 0; /* narrow */ spi_max_width(starget) = 1; spi_iu(starget) = 0; /* no IU */ + spi_max_iu(starget) = 1; spi_dt(starget) = 0; /* ST */ spi_qas(starget) = 0; + spi_max_qas(starget) = 1; spi_wr_flow(starget) = 0; spi_rd_strm(starget) = 0; spi_rti(starget) = 0; @@ -248,9 +278,10 @@ static int spi_setup_transport_attrs(struct transport_container *tc, #define spi_transport_show_simple(field, format_string) \ \ static ssize_t \ -show_spi_transport_##field(struct class_device *cdev, char *buf) \ +show_spi_transport_##field(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ - struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct scsi_target *starget = transport_class_to_starget(dev); \ struct spi_transport_attrs *tp; \ \ tp = (struct spi_transport_attrs *)&starget->starget_data; \ @@ -260,11 +291,12 @@ show_spi_transport_##field(struct class_device *cdev, char *buf) \ #define spi_transport_store_simple(field, format_string) \ \ static ssize_t \ -store_spi_transport_##field(struct class_device *cdev, const char *buf, \ - size_t count) \ +store_spi_transport_##field(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ { \ int val; \ - struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct scsi_target *starget = transport_class_to_starget(dev); \ struct spi_transport_attrs *tp; \ \ tp = (struct spi_transport_attrs *)&starget->starget_data; \ @@ -276,9 +308,10 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \ #define spi_transport_show_function(field, format_string) \ \ static ssize_t \ -show_spi_transport_##field(struct class_device *cdev, char *buf) \ +show_spi_transport_##field(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ - struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct scsi_target *starget = transport_class_to_starget(dev); \ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \ struct spi_transport_attrs *tp; \ struct spi_internal *i = to_spi_internal(shost->transportt); \ @@ -290,11 +323,12 @@ show_spi_transport_##field(struct class_device *cdev, char *buf) \ #define spi_transport_store_function(field, format_string) \ static ssize_t \ -store_spi_transport_##field(struct class_device *cdev, const char *buf, \ - size_t count) \ +store_spi_transport_##field(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ { \ int val; \ - struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct scsi_target *starget = transport_class_to_starget(dev); \ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \ struct spi_internal *i = to_spi_internal(shost->transportt); \ \ @@ -307,11 +341,12 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \ #define spi_transport_store_max(field, format_string) \ static ssize_t \ -store_spi_transport_##field(struct class_device *cdev, const char *buf, \ - size_t count) \ +store_spi_transport_##field(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ { \ int val; \ - struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct scsi_target *starget = transport_class_to_starget(dev); \ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \ struct spi_internal *i = to_spi_internal(shost->transportt); \ struct spi_transport_attrs *tp \ @@ -329,55 +364,58 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \ #define spi_transport_rd_attr(field, format_string) \ spi_transport_show_function(field, format_string) \ spi_transport_store_function(field, format_string) \ -static CLASS_DEVICE_ATTR(field, S_IRUGO, \ - show_spi_transport_##field, \ - store_spi_transport_##field); +static DEVICE_ATTR(field, S_IRUGO, \ + show_spi_transport_##field, \ + store_spi_transport_##field); #define spi_transport_simple_attr(field, format_string) \ spi_transport_show_simple(field, format_string) \ spi_transport_store_simple(field, format_string) \ -static CLASS_DEVICE_ATTR(field, S_IRUGO, \ - show_spi_transport_##field, \ - store_spi_transport_##field); +static DEVICE_ATTR(field, S_IRUGO, \ + show_spi_transport_##field, \ + store_spi_transport_##field); #define spi_transport_max_attr(field, format_string) \ spi_transport_show_function(field, format_string) \ spi_transport_store_max(field, format_string) \ spi_transport_simple_attr(max_##field, format_string) \ -static CLASS_DEVICE_ATTR(field, S_IRUGO, \ - show_spi_transport_##field, \ - store_spi_transport_##field); +static DEVICE_ATTR(field, S_IRUGO, \ + show_spi_transport_##field, \ + store_spi_transport_##field); /* The Parallel SCSI Tranport Attributes: */ spi_transport_max_attr(offset, "%d\n"); spi_transport_max_attr(width, "%d\n"); -spi_transport_rd_attr(iu, "%d\n"); +spi_transport_max_attr(iu, "%d\n"); spi_transport_rd_attr(dt, "%d\n"); -spi_transport_rd_attr(qas, "%d\n"); +spi_transport_max_attr(qas, "%d\n"); spi_transport_rd_attr(wr_flow, "%d\n"); spi_transport_rd_attr(rd_strm, "%d\n"); spi_transport_rd_attr(rti, "%d\n"); spi_transport_rd_attr(pcomp_en, "%d\n"); spi_transport_rd_attr(hold_mcs, "%d\n"); -/* we only care about the first child device so we return 1 */ +/* we only care about the first child device that's a real SCSI device + * so we return 1 to terminate the iteration when we find it */ static int child_iter(struct device *dev, void *data) { - struct scsi_device *sdev = to_scsi_device(dev); + if (!scsi_is_sdev_device(dev)) + return 0; - spi_dv_device(sdev); + spi_dv_device(to_scsi_device(dev)); return 1; } static ssize_t -store_spi_revalidate(struct class_device *cdev, const char *buf, size_t count) +store_spi_revalidate(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - struct scsi_target *starget = transport_class_to_starget(cdev); + struct scsi_target *starget = transport_class_to_starget(dev); device_for_each_child(&starget->dev, NULL, child_iter); return count; } -static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate); +static DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate); /* Translate the period into ns according to the current spec * for SDTR/PPR messages */ @@ -412,7 +450,7 @@ show_spi_transport_period_helper(char *buf, int period) } static ssize_t -store_spi_transport_period_helper(struct class_device *cdev, const char *buf, +store_spi_transport_period_helper(struct device *dev, const char *buf, size_t count, int *periodp) { int j, picosec, period = -1; @@ -449,9 +487,10 @@ store_spi_transport_period_helper(struct class_device *cdev, const char *buf, } static ssize_t -show_spi_transport_period(struct class_device *cdev, char *buf) +show_spi_transport_period(struct device *dev, + struct device_attribute *attr, char *buf) { - struct scsi_target *starget = transport_class_to_starget(cdev); + struct scsi_target *starget = transport_class_to_starget(dev); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct spi_internal *i = to_spi_internal(shost->transportt); struct spi_transport_attrs *tp = @@ -464,8 +503,8 @@ show_spi_transport_period(struct class_device *cdev, char *buf) } static ssize_t -store_spi_transport_period(struct class_device *cdev, const char *buf, - size_t count) +store_spi_transport_period(struct device *cdev, struct device_attribute *attr, + const char *buf, size_t count) { struct scsi_target *starget = transport_class_to_starget(cdev); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); @@ -487,12 +526,13 @@ store_spi_transport_period(struct class_device *cdev, const char *buf, return retval; } -static CLASS_DEVICE_ATTR(period, S_IRUGO, - show_spi_transport_period, - store_spi_transport_period); +static DEVICE_ATTR(period, S_IRUGO, + show_spi_transport_period, + store_spi_transport_period); static ssize_t -show_spi_transport_min_period(struct class_device *cdev, char *buf) +show_spi_transport_min_period(struct device *cdev, + struct device_attribute *attr, char *buf) { struct scsi_target *starget = transport_class_to_starget(cdev); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); @@ -507,8 +547,9 @@ show_spi_transport_min_period(struct class_device *cdev, char *buf) } static ssize_t -store_spi_transport_min_period(struct class_device *cdev, const char *buf, - size_t count) +store_spi_transport_min_period(struct device *cdev, + struct device_attribute *attr, + const char *buf, size_t count) { struct scsi_target *starget = transport_class_to_starget(cdev); struct spi_transport_attrs *tp = @@ -519,12 +560,14 @@ store_spi_transport_min_period(struct class_device *cdev, const char *buf, } -static CLASS_DEVICE_ATTR(min_period, S_IRUGO, - show_spi_transport_min_period, - store_spi_transport_min_period); +static DEVICE_ATTR(min_period, S_IRUGO, + show_spi_transport_min_period, + store_spi_transport_min_period); -static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf) +static ssize_t show_spi_host_signalling(struct device *cdev, + struct device_attribute *attr, + char *buf) { struct Scsi_Host *shost = transport_class_to_shost(cdev); struct spi_internal *i = to_spi_internal(shost->transportt); @@ -534,10 +577,11 @@ static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf) return sprintf(buf, "%s\n", spi_signal_to_string(spi_signalling(shost))); } -static ssize_t store_spi_host_signalling(struct class_device *cdev, +static ssize_t store_spi_host_signalling(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { - struct Scsi_Host *shost = transport_class_to_shost(cdev); + struct Scsi_Host *shost = transport_class_to_shost(dev); struct spi_internal *i = to_spi_internal(shost->transportt); enum spi_signal_type type = spi_signal_to_value(buf); @@ -549,9 +593,31 @@ static ssize_t store_spi_host_signalling(struct class_device *cdev, return count; } -static CLASS_DEVICE_ATTR(signalling, S_IRUGO, - show_spi_host_signalling, - store_spi_host_signalling); +static DEVICE_ATTR(signalling, S_IRUGO, + show_spi_host_signalling, + store_spi_host_signalling); + +static ssize_t show_spi_host_width(struct device *cdev, + struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = transport_class_to_shost(cdev); + + return sprintf(buf, "%s\n", shost->max_id == 16 ? "wide" : "narrow"); +} +static DEVICE_ATTR(host_width, S_IRUGO, + show_spi_host_width, NULL); + +static ssize_t show_spi_host_hba_id(struct device *cdev, + struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = transport_class_to_shost(cdev); + + return sprintf(buf, "%d\n", shost->this_id); +} +static DEVICE_ATTR(hba_id, S_IRUGO, + show_spi_host_hba_id, NULL); #define DV_SET(x, y) \ if(i->f->set_##x) \ @@ -813,7 +879,7 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) return; } - if (!scsi_device_wide(sdev)) { + if (!spi_support_wide(starget)) { spi_max_width(starget) = 0; max_width = 0; } @@ -840,7 +906,7 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) return; /* device can't handle synchronous */ - if (!scsi_device_sync(sdev) && !scsi_device_dt(sdev)) + if (!spi_support_sync(starget) && !spi_support_dt(starget)) return; /* len == -1 is the signal that we need to ascertain the @@ -856,13 +922,14 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) /* try QAS requests; this should be harmless to set if the * target supports it */ - if (scsi_device_qas(sdev)) { + if (spi_support_qas(starget) && spi_max_qas(starget)) { DV_SET(qas, 1); } else { DV_SET(qas, 0); } - if (scsi_device_ius(sdev) && min_period < 9) { + if (spi_support_ius(starget) && spi_max_iu(starget) && + min_period < 9) { /* This u320 (or u640). Set IU transfers */ DV_SET(iu, 1); /* Then set the optional parameters */ @@ -882,7 +949,7 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) i->f->get_signalling(shost); if (spi_signalling(shost) == SPI_SIGNAL_SE || spi_signalling(shost) == SPI_SIGNAL_HVD || - !scsi_device_dt(sdev)) { + !spi_support_dt(starget)) { DV_SET(dt, 0); } else { DV_SET(dt, 1); @@ -943,10 +1010,10 @@ spi_dv_device(struct scsi_device *sdev) u8 *buffer; const int len = SPI_MAX_ECHO_BUFFER_SIZE*2; - if (unlikely(scsi_device_get(sdev))) + if (unlikely(spi_dv_in_progress(starget))) return; - if (unlikely(spi_dv_in_progress(starget))) + if (unlikely(scsi_device_get(sdev))) return; spi_dv_in_progress(starget) = 1; @@ -1334,7 +1401,9 @@ static DECLARE_ANON_TRANSPORT_CLASS(spi_device_class, spi_device_configure); static struct attribute *host_attributes[] = { - &class_device_attr_signalling.attr, + &dev_attr_signalling.attr, + &dev_attr_host_width.attr, + &dev_attr_hba_id.attr, NULL }; @@ -1344,12 +1413,12 @@ static struct attribute_group host_attribute_group = { static int spi_host_configure(struct transport_container *tc, struct device *dev, - struct class_device *cdev) + struct device *cdev) { struct kobject *kobj = &cdev->kobj; struct Scsi_Host *shost = transport_class_to_shost(cdev); struct spi_internal *si = to_spi_internal(shost->transportt); - struct attribute *attr = &class_device_attr_signalling.attr; + struct attribute *attr = &dev_attr_signalling.attr; int rc = 0; if (si->f->set_signalling) @@ -1362,82 +1431,89 @@ static int spi_host_configure(struct transport_container *tc, * overloads the return by setting 1<<1 if the attribute should * be writeable */ #define TARGET_ATTRIBUTE_HELPER(name) \ - (si->f->show_##name ? 1 : 0) + \ - (si->f->set_##name ? 2 : 0) + (si->f->show_##name ? S_IRUGO : 0) | \ + (si->f->set_##name ? S_IWUSR : 0) -static int target_attribute_is_visible(struct kobject *kobj, - struct attribute *attr, int i) +static umode_t target_attribute_is_visible(struct kobject *kobj, + struct attribute *attr, int i) { - struct class_device *cdev = - container_of(kobj, struct class_device, kobj); + struct device *cdev = container_of(kobj, struct device, kobj); struct scsi_target *starget = transport_class_to_starget(cdev); struct Scsi_Host *shost = transport_class_to_shost(cdev); struct spi_internal *si = to_spi_internal(shost->transportt); - if (attr == &class_device_attr_period.attr && + if (attr == &dev_attr_period.attr && spi_support_sync(starget)) return TARGET_ATTRIBUTE_HELPER(period); - else if (attr == &class_device_attr_min_period.attr && + else if (attr == &dev_attr_min_period.attr && spi_support_sync(starget)) return TARGET_ATTRIBUTE_HELPER(period); - else if (attr == &class_device_attr_offset.attr && + else if (attr == &dev_attr_offset.attr && spi_support_sync(starget)) return TARGET_ATTRIBUTE_HELPER(offset); - else if (attr == &class_device_attr_max_offset.attr && + else if (attr == &dev_attr_max_offset.attr && spi_support_sync(starget)) return TARGET_ATTRIBUTE_HELPER(offset); - else if (attr == &class_device_attr_width.attr && + else if (attr == &dev_attr_width.attr && spi_support_wide(starget)) return TARGET_ATTRIBUTE_HELPER(width); - else if (attr == &class_device_attr_max_width.attr && + else if (attr == &dev_attr_max_width.attr && spi_support_wide(starget)) return TARGET_ATTRIBUTE_HELPER(width); - else if (attr == &class_device_attr_iu.attr && + else if (attr == &dev_attr_iu.attr && spi_support_ius(starget)) return TARGET_ATTRIBUTE_HELPER(iu); - else if (attr == &class_device_attr_dt.attr && + else if (attr == &dev_attr_max_iu.attr && + spi_support_ius(starget)) + return TARGET_ATTRIBUTE_HELPER(iu); + else if (attr == &dev_attr_dt.attr && spi_support_dt(starget)) return TARGET_ATTRIBUTE_HELPER(dt); - else if (attr == &class_device_attr_qas.attr && + else if (attr == &dev_attr_qas.attr && spi_support_qas(starget)) return TARGET_ATTRIBUTE_HELPER(qas); - else if (attr == &class_device_attr_wr_flow.attr && + else if (attr == &dev_attr_max_qas.attr && + spi_support_qas(starget)) + return TARGET_ATTRIBUTE_HELPER(qas); + else if (attr == &dev_attr_wr_flow.attr && spi_support_ius(starget)) return TARGET_ATTRIBUTE_HELPER(wr_flow); - else if (attr == &class_device_attr_rd_strm.attr && + else if (attr == &dev_attr_rd_strm.attr && spi_support_ius(starget)) return TARGET_ATTRIBUTE_HELPER(rd_strm); - else if (attr == &class_device_attr_rti.attr && + else if (attr == &dev_attr_rti.attr && spi_support_ius(starget)) return TARGET_ATTRIBUTE_HELPER(rti); - else if (attr == &class_device_attr_pcomp_en.attr && + else if (attr == &dev_attr_pcomp_en.attr && spi_support_ius(starget)) return TARGET_ATTRIBUTE_HELPER(pcomp_en); - else if (attr == &class_device_attr_hold_mcs.attr && + else if (attr == &dev_attr_hold_mcs.attr && spi_support_ius(starget)) return TARGET_ATTRIBUTE_HELPER(hold_mcs); - else if (attr == &class_device_attr_revalidate.attr) - return 1; + else if (attr == &dev_attr_revalidate.attr) + return S_IWUSR; return 0; } static struct attribute *target_attributes[] = { - &class_device_attr_period.attr, - &class_device_attr_min_period.attr, - &class_device_attr_offset.attr, - &class_device_attr_max_offset.attr, - &class_device_attr_width.attr, - &class_device_attr_max_width.attr, - &class_device_attr_iu.attr, - &class_device_attr_dt.attr, - &class_device_attr_qas.attr, - &class_device_attr_wr_flow.attr, - &class_device_attr_rd_strm.attr, - &class_device_attr_rti.attr, - &class_device_attr_pcomp_en.attr, - &class_device_attr_hold_mcs.attr, - &class_device_attr_revalidate.attr, + &dev_attr_period.attr, + &dev_attr_min_period.attr, + &dev_attr_offset.attr, + &dev_attr_max_offset.attr, + &dev_attr_width.attr, + &dev_attr_max_width.attr, + &dev_attr_iu.attr, + &dev_attr_max_iu.attr, + &dev_attr_dt.attr, + &dev_attr_qas.attr, + &dev_attr_max_qas.attr, + &dev_attr_wr_flow.attr, + &dev_attr_rd_strm.attr, + &dev_attr_rti.attr, + &dev_attr_pcomp_en.attr, + &dev_attr_hold_mcs.attr, + &dev_attr_revalidate.attr, NULL }; @@ -1448,28 +1524,12 @@ static struct attribute_group target_attribute_group = { static int spi_target_configure(struct transport_container *tc, struct device *dev, - struct class_device *cdev) + struct device *cdev) { struct kobject *kobj = &cdev->kobj; - int i; - struct attribute *attr; - int rc; - - for (i = 0; (attr = target_attributes[i]) != NULL; i++) { - int j = target_attribute_group.is_visible(kobj, attr, i); - - /* FIXME: as well as returning -EEXIST, which we'd like - * to ignore, sysfs also does a WARN_ON and dumps a trace, - * which is bad, so temporarily, skip attributes that are - * already visible (the revalidate one) */ - if (j && attr != &class_device_attr_revalidate.attr) - rc = sysfs_add_file_to_group(kobj, attr, - target_attribute_group.name); - /* and make the attribute writeable if we have a set - * function */ - if ((j & 1)) - rc = sysfs_chmod_file(kobj, attr, attr->mode | S_IWUSR); - } + + /* force an update based on parameters read from the device */ + sysfs_update_group(kobj, &target_attribute_group); return 0; } @@ -1512,7 +1572,21 @@ EXPORT_SYMBOL(spi_release_transport); static __init int spi_transport_init(void) { - int error = transport_class_register(&spi_transport_class); + int error = scsi_dev_info_add_list(SCSI_DEVINFO_SPI, + "SCSI Parallel Transport Class"); + if (!error) { + int i; + + for (i = 0; spi_static_device_list[i].vendor; i++) + scsi_dev_info_list_add_keyed(1, /* compatible */ + spi_static_device_list[i].vendor, + spi_static_device_list[i].model, + NULL, + spi_static_device_list[i].flags, + SCSI_DEVINFO_SPI); + } + + error = transport_class_register(&spi_transport_class); if (error) return error; error = anon_transport_class_register(&spi_device_class); @@ -1524,6 +1598,7 @@ static void __exit spi_transport_exit(void) transport_class_unregister(&spi_transport_class); anon_transport_class_unregister(&spi_device_class); transport_class_unregister(&spi_host_class); + scsi_dev_info_remove_list(SCSI_DEVINFO_SPI); } MODULE_AUTHOR("Martin Hicks"); |
