diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_spi.c')
-rw-r--r-- | drivers/scsi/scsi_transport_spi.c | 65 |
1 files changed, 57 insertions, 8 deletions
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index f49f55c6bfc8..c25bd9a34e02 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c | |||
@@ -46,6 +46,22 @@ | |||
46 | #define DV_RETRIES 3 /* should only need at most | 46 | #define DV_RETRIES 3 /* should only need at most |
47 | * two cc/ua clears */ | 47 | * two cc/ua clears */ |
48 | 48 | ||
49 | /* Our blacklist flags */ | ||
50 | enum { | ||
51 | SPI_BLIST_NOIUS = 0x1, | ||
52 | }; | ||
53 | |||
54 | /* blacklist table, modelled on scsi_devinfo.c */ | ||
55 | static struct { | ||
56 | char *vendor; | ||
57 | char *model; | ||
58 | unsigned flags; | ||
59 | } spi_static_device_list[] __initdata = { | ||
60 | {"HP", "Ultrium 3-SCSI", SPI_BLIST_NOIUS }, | ||
61 | {"IBM", "ULTRIUM-TD3", SPI_BLIST_NOIUS }, | ||
62 | {NULL, NULL, 0} | ||
63 | }; | ||
64 | |||
49 | /* Private data accessors (keep these out of the header file) */ | 65 | /* Private data accessors (keep these out of the header file) */ |
50 | #define spi_dv_in_progress(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_in_progress) | 66 | #define spi_dv_in_progress(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_in_progress) |
51 | #define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex) | 67 | #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, | |||
207 | { | 223 | { |
208 | struct scsi_device *sdev = to_scsi_device(dev); | 224 | struct scsi_device *sdev = to_scsi_device(dev); |
209 | struct scsi_target *starget = sdev->sdev_target; | 225 | struct scsi_target *starget = sdev->sdev_target; |
226 | unsigned bflags = scsi_get_device_flags_keyed(sdev, &sdev->inquiry[8], | ||
227 | &sdev->inquiry[16], | ||
228 | SCSI_DEVINFO_SPI); | ||
210 | 229 | ||
211 | /* Populate the target capability fields with the values | 230 | /* Populate the target capability fields with the values |
212 | * gleaned from the device inquiry */ | 231 | * gleaned from the device inquiry */ |
@@ -216,6 +235,10 @@ static int spi_device_configure(struct transport_container *tc, | |||
216 | spi_support_dt(starget) = scsi_device_dt(sdev); | 235 | spi_support_dt(starget) = scsi_device_dt(sdev); |
217 | spi_support_dt_only(starget) = scsi_device_dt_only(sdev); | 236 | spi_support_dt_only(starget) = scsi_device_dt_only(sdev); |
218 | spi_support_ius(starget) = scsi_device_ius(sdev); | 237 | spi_support_ius(starget) = scsi_device_ius(sdev); |
238 | if (bflags & SPI_BLIST_NOIUS) { | ||
239 | dev_info(dev, "Information Units disabled by blacklist\n"); | ||
240 | spi_support_ius(starget) = 0; | ||
241 | } | ||
219 | spi_support_qas(starget) = scsi_device_qas(sdev); | 242 | spi_support_qas(starget) = scsi_device_qas(sdev); |
220 | 243 | ||
221 | return 0; | 244 | return 0; |
@@ -234,8 +257,10 @@ static int spi_setup_transport_attrs(struct transport_container *tc, | |||
234 | spi_width(starget) = 0; /* narrow */ | 257 | spi_width(starget) = 0; /* narrow */ |
235 | spi_max_width(starget) = 1; | 258 | spi_max_width(starget) = 1; |
236 | spi_iu(starget) = 0; /* no IU */ | 259 | spi_iu(starget) = 0; /* no IU */ |
260 | spi_max_iu(starget) = 1; | ||
237 | spi_dt(starget) = 0; /* ST */ | 261 | spi_dt(starget) = 0; /* ST */ |
238 | spi_qas(starget) = 0; | 262 | spi_qas(starget) = 0; |
263 | spi_max_qas(starget) = 1; | ||
239 | spi_wr_flow(starget) = 0; | 264 | spi_wr_flow(starget) = 0; |
240 | spi_rd_strm(starget) = 0; | 265 | spi_rd_strm(starget) = 0; |
241 | spi_rti(starget) = 0; | 266 | spi_rti(starget) = 0; |
@@ -360,9 +385,9 @@ static DEVICE_ATTR(field, S_IRUGO, \ | |||
360 | /* The Parallel SCSI Tranport Attributes: */ | 385 | /* The Parallel SCSI Tranport Attributes: */ |
361 | spi_transport_max_attr(offset, "%d\n"); | 386 | spi_transport_max_attr(offset, "%d\n"); |
362 | spi_transport_max_attr(width, "%d\n"); | 387 | spi_transport_max_attr(width, "%d\n"); |
363 | spi_transport_rd_attr(iu, "%d\n"); | 388 | spi_transport_max_attr(iu, "%d\n"); |
364 | spi_transport_rd_attr(dt, "%d\n"); | 389 | spi_transport_rd_attr(dt, "%d\n"); |
365 | spi_transport_rd_attr(qas, "%d\n"); | 390 | spi_transport_max_attr(qas, "%d\n"); |
366 | spi_transport_rd_attr(wr_flow, "%d\n"); | 391 | spi_transport_rd_attr(wr_flow, "%d\n"); |
367 | spi_transport_rd_attr(rd_strm, "%d\n"); | 392 | spi_transport_rd_attr(rd_strm, "%d\n"); |
368 | spi_transport_rd_attr(rti, "%d\n"); | 393 | spi_transport_rd_attr(rti, "%d\n"); |
@@ -831,7 +856,7 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) | |||
831 | return; | 856 | return; |
832 | } | 857 | } |
833 | 858 | ||
834 | if (!scsi_device_wide(sdev)) { | 859 | if (!spi_support_wide(starget)) { |
835 | spi_max_width(starget) = 0; | 860 | spi_max_width(starget) = 0; |
836 | max_width = 0; | 861 | max_width = 0; |
837 | } | 862 | } |
@@ -858,7 +883,7 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) | |||
858 | return; | 883 | return; |
859 | 884 | ||
860 | /* device can't handle synchronous */ | 885 | /* device can't handle synchronous */ |
861 | if (!scsi_device_sync(sdev) && !scsi_device_dt(sdev)) | 886 | if (!spi_support_sync(starget) && !spi_support_dt(starget)) |
862 | return; | 887 | return; |
863 | 888 | ||
864 | /* len == -1 is the signal that we need to ascertain the | 889 | /* len == -1 is the signal that we need to ascertain the |
@@ -874,13 +899,14 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) | |||
874 | 899 | ||
875 | /* try QAS requests; this should be harmless to set if the | 900 | /* try QAS requests; this should be harmless to set if the |
876 | * target supports it */ | 901 | * target supports it */ |
877 | if (scsi_device_qas(sdev)) { | 902 | if (spi_support_qas(starget) && spi_max_qas(starget)) { |
878 | DV_SET(qas, 1); | 903 | DV_SET(qas, 1); |
879 | } else { | 904 | } else { |
880 | DV_SET(qas, 0); | 905 | DV_SET(qas, 0); |
881 | } | 906 | } |
882 | 907 | ||
883 | if (scsi_device_ius(sdev) && min_period < 9) { | 908 | if (spi_support_ius(starget) && spi_max_iu(starget) && |
909 | min_period < 9) { | ||
884 | /* This u320 (or u640). Set IU transfers */ | 910 | /* This u320 (or u640). Set IU transfers */ |
885 | DV_SET(iu, 1); | 911 | DV_SET(iu, 1); |
886 | /* Then set the optional parameters */ | 912 | /* Then set the optional parameters */ |
@@ -900,7 +926,7 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) | |||
900 | i->f->get_signalling(shost); | 926 | i->f->get_signalling(shost); |
901 | if (spi_signalling(shost) == SPI_SIGNAL_SE || | 927 | if (spi_signalling(shost) == SPI_SIGNAL_SE || |
902 | spi_signalling(shost) == SPI_SIGNAL_HVD || | 928 | spi_signalling(shost) == SPI_SIGNAL_HVD || |
903 | !scsi_device_dt(sdev)) { | 929 | !spi_support_dt(starget)) { |
904 | DV_SET(dt, 0); | 930 | DV_SET(dt, 0); |
905 | } else { | 931 | } else { |
906 | DV_SET(dt, 1); | 932 | DV_SET(dt, 1); |
@@ -1412,12 +1438,18 @@ static mode_t target_attribute_is_visible(struct kobject *kobj, | |||
1412 | else if (attr == &dev_attr_iu.attr && | 1438 | else if (attr == &dev_attr_iu.attr && |
1413 | spi_support_ius(starget)) | 1439 | spi_support_ius(starget)) |
1414 | return TARGET_ATTRIBUTE_HELPER(iu); | 1440 | return TARGET_ATTRIBUTE_HELPER(iu); |
1441 | else if (attr == &dev_attr_max_iu.attr && | ||
1442 | spi_support_ius(starget)) | ||
1443 | return TARGET_ATTRIBUTE_HELPER(iu); | ||
1415 | else if (attr == &dev_attr_dt.attr && | 1444 | else if (attr == &dev_attr_dt.attr && |
1416 | spi_support_dt(starget)) | 1445 | spi_support_dt(starget)) |
1417 | return TARGET_ATTRIBUTE_HELPER(dt); | 1446 | return TARGET_ATTRIBUTE_HELPER(dt); |
1418 | else if (attr == &dev_attr_qas.attr && | 1447 | else if (attr == &dev_attr_qas.attr && |
1419 | spi_support_qas(starget)) | 1448 | spi_support_qas(starget)) |
1420 | return TARGET_ATTRIBUTE_HELPER(qas); | 1449 | return TARGET_ATTRIBUTE_HELPER(qas); |
1450 | else if (attr == &dev_attr_max_qas.attr && | ||
1451 | spi_support_qas(starget)) | ||
1452 | return TARGET_ATTRIBUTE_HELPER(qas); | ||
1421 | else if (attr == &dev_attr_wr_flow.attr && | 1453 | else if (attr == &dev_attr_wr_flow.attr && |
1422 | spi_support_ius(starget)) | 1454 | spi_support_ius(starget)) |
1423 | return TARGET_ATTRIBUTE_HELPER(wr_flow); | 1455 | return TARGET_ATTRIBUTE_HELPER(wr_flow); |
@@ -1447,8 +1479,10 @@ static struct attribute *target_attributes[] = { | |||
1447 | &dev_attr_width.attr, | 1479 | &dev_attr_width.attr, |
1448 | &dev_attr_max_width.attr, | 1480 | &dev_attr_max_width.attr, |
1449 | &dev_attr_iu.attr, | 1481 | &dev_attr_iu.attr, |
1482 | &dev_attr_max_iu.attr, | ||
1450 | &dev_attr_dt.attr, | 1483 | &dev_attr_dt.attr, |
1451 | &dev_attr_qas.attr, | 1484 | &dev_attr_qas.attr, |
1485 | &dev_attr_max_qas.attr, | ||
1452 | &dev_attr_wr_flow.attr, | 1486 | &dev_attr_wr_flow.attr, |
1453 | &dev_attr_rd_strm.attr, | 1487 | &dev_attr_rd_strm.attr, |
1454 | &dev_attr_rti.attr, | 1488 | &dev_attr_rti.attr, |
@@ -1513,7 +1547,21 @@ EXPORT_SYMBOL(spi_release_transport); | |||
1513 | 1547 | ||
1514 | static __init int spi_transport_init(void) | 1548 | static __init int spi_transport_init(void) |
1515 | { | 1549 | { |
1516 | int error = transport_class_register(&spi_transport_class); | 1550 | int error = scsi_dev_info_add_list(SCSI_DEVINFO_SPI, |
1551 | "SCSI Parallel Transport Class"); | ||
1552 | if (!error) { | ||
1553 | int i; | ||
1554 | |||
1555 | for (i = 0; spi_static_device_list[i].vendor; i++) | ||
1556 | scsi_dev_info_list_add_keyed(1, /* compatible */ | ||
1557 | spi_static_device_list[i].vendor, | ||
1558 | spi_static_device_list[i].model, | ||
1559 | NULL, | ||
1560 | spi_static_device_list[i].flags, | ||
1561 | SCSI_DEVINFO_SPI); | ||
1562 | } | ||
1563 | |||
1564 | error = transport_class_register(&spi_transport_class); | ||
1517 | if (error) | 1565 | if (error) |
1518 | return error; | 1566 | return error; |
1519 | error = anon_transport_class_register(&spi_device_class); | 1567 | error = anon_transport_class_register(&spi_device_class); |
@@ -1525,6 +1573,7 @@ static void __exit spi_transport_exit(void) | |||
1525 | transport_class_unregister(&spi_transport_class); | 1573 | transport_class_unregister(&spi_transport_class); |
1526 | anon_transport_class_unregister(&spi_device_class); | 1574 | anon_transport_class_unregister(&spi_device_class); |
1527 | transport_class_unregister(&spi_host_class); | 1575 | transport_class_unregister(&spi_host_class); |
1576 | scsi_dev_info_remove_list(SCSI_DEVINFO_SPI); | ||
1528 | } | 1577 | } |
1529 | 1578 | ||
1530 | MODULE_AUTHOR("Martin Hicks"); | 1579 | MODULE_AUTHOR("Martin Hicks"); |