From ea4431906d86686e541de527915ccbe556761b16 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 13 Jun 2009 12:19:05 -0500 Subject: [SCSI] aic79xx: make driver respect nvram for IU and QAS settings This patch allows the Adaptec firmware to pass on its values for Packetize and QAS. To do this, the settings max_iu and max_qas have been introduced into the SPI transport class and populated from the adaptec NVram tables. Domain validation in the SPI transport class will respect the max settings when configuring to the highest possible speed for testing. Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/scsi_transport_spi.c') diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index f49f55c6bfc..654a34fb04c 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -234,8 +234,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; @@ -360,9 +362,9 @@ static DEVICE_ATTR(field, S_IRUGO, \ /* 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"); @@ -874,13 +876,13 @@ 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 (scsi_device_qas(sdev) && spi_max_qas(starget)) { DV_SET(qas, 1); } else { DV_SET(qas, 0); } - if (scsi_device_ius(sdev) && min_period < 9) { + if (scsi_device_ius(sdev) && spi_max_iu(starget) && min_period < 9) { /* This u320 (or u640). Set IU transfers */ DV_SET(iu, 1); /* Then set the optional parameters */ @@ -1412,12 +1414,18 @@ static mode_t target_attribute_is_visible(struct kobject *kobj, else if (attr == &dev_attr_iu.attr && spi_support_ius(starget)) return TARGET_ATTRIBUTE_HELPER(iu); + 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 == &dev_attr_qas.attr && spi_support_qas(starget)) return TARGET_ATTRIBUTE_HELPER(qas); + 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); @@ -1447,8 +1455,10 @@ static struct attribute *target_attributes[] = { &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, -- cgit v1.2.3-70-g09d2 From 9872b81cf9f4b163e9c558d79e76b832c58a4814 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 17 Jun 2009 15:03:41 -0400 Subject: scsi_transport_spi: use spi target settings instead of inquiry data for DV Right at the moment, we carefully set up the spi_support_xx in the device configuration routines, but then we never actually use the results: we rely on the inquiry strings. If we're going to allow overrides to the inquiry data, we have to rely on our own internal settings. Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/scsi_transport_spi.c') diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 654a34fb04c..00cfb40b5ef 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -833,7 +833,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; } @@ -860,7 +860,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 @@ -876,13 +876,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) && spi_max_qas(starget)) { + if (spi_support_qas(starget) && spi_max_qas(starget)) { DV_SET(qas, 1); } else { DV_SET(qas, 0); } - if (scsi_device_ius(sdev) && spi_max_iu(starget) && 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 */ @@ -902,7 +903,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); -- cgit v1.2.3-70-g09d2 From a9e0edb687151617fe89cc5ab0086ebfc73ffccb Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 17 Jun 2009 19:05:05 +0000 Subject: scsi_transport_spi: Blacklist Ultrium-3 tape for IU transfers There have been several bug reports which identified the Ultrium-3 tape as just hanging up on the bus during certain types of IU transfer. The identified culpret is type 0x02 (MULTIPLE COMMAND) transfers. The only way to prevent this tape wedging is to prevent it from using IU transfers at all. So this patch uses the exported blacklist matching technology to recognise the drive and force it not to use IU transfers. Signed-off-by: James Bottomley --- drivers/scsi/scsi_priv.h | 1 + drivers/scsi/scsi_transport_spi.c | 40 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers/scsi/scsi_transport_spi.c') diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index b4e49cd6e75..00264aab8c8 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -43,6 +43,7 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) /* list of keys for the lists */ enum { SCSI_DEVINFO_GLOBAL = 0, + SCSI_DEVINFO_SPI, }; extern int scsi_get_device_flags(struct scsi_device *sdev, diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 00cfb40b5ef..c25bd9a34e0 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -46,6 +46,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) @@ -207,6 +223,9 @@ static int spi_device_configure(struct transport_container *tc, { 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 */ @@ -216,6 +235,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; @@ -1524,7 +1547,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); @@ -1536,6 +1573,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"); -- cgit v1.2.3-70-g09d2