diff options
-rw-r--r-- | drivers/scsi/scsi_transport_spi.c | 30 | ||||
-rw-r--r-- | include/scsi/scsi_transport_spi.h | 3 |
2 files changed, 25 insertions, 8 deletions
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 29a9a53cdd1a..9f070f0d0f2b 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c | |||
@@ -47,6 +47,7 @@ | |||
47 | 47 | ||
48 | /* Private data accessors (keep these out of the header file) */ | 48 | /* Private data accessors (keep these out of the header file) */ |
49 | #define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) | 49 | #define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) |
50 | #define spi_dv_in_progress(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_in_progress) | ||
50 | #define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex) | 51 | #define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex) |
51 | 52 | ||
52 | struct spi_internal { | 53 | struct spi_internal { |
@@ -240,6 +241,7 @@ static int spi_setup_transport_attrs(struct transport_container *tc, | |||
240 | spi_pcomp_en(starget) = 0; | 241 | spi_pcomp_en(starget) = 0; |
241 | spi_hold_mcs(starget) = 0; | 242 | spi_hold_mcs(starget) = 0; |
242 | spi_dv_pending(starget) = 0; | 243 | spi_dv_pending(starget) = 0; |
244 | spi_dv_in_progress(starget) = 0; | ||
243 | spi_initial_dv(starget) = 0; | 245 | spi_initial_dv(starget) = 0; |
244 | mutex_init(&spi_dv_mutex(starget)); | 246 | mutex_init(&spi_dv_mutex(starget)); |
245 | 247 | ||
@@ -830,28 +832,37 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) | |||
830 | DV_SET(period, spi_min_period(starget)); | 832 | DV_SET(period, spi_min_period(starget)); |
831 | /* try QAS requests; this should be harmless to set if the | 833 | /* try QAS requests; this should be harmless to set if the |
832 | * target supports it */ | 834 | * target supports it */ |
833 | if (scsi_device_qas(sdev)) | 835 | if (scsi_device_qas(sdev)) { |
834 | DV_SET(qas, 1); | 836 | DV_SET(qas, 1); |
835 | /* Also try IU transfers */ | 837 | } else { |
836 | if (scsi_device_ius(sdev)) | 838 | DV_SET(qas, 0); |
839 | } | ||
840 | |||
841 | if (scsi_device_ius(sdev) && spi_min_period(starget) < 9) { | ||
842 | /* This u320 (or u640). Set IU transfers */ | ||
837 | DV_SET(iu, 1); | 843 | DV_SET(iu, 1); |
838 | if (spi_min_period(starget) < 9) { | 844 | /* Then set the optional parameters */ |
839 | /* This u320 (or u640). Ignore the coupled parameters | ||
840 | * like DT and IU, but set the optional ones */ | ||
841 | DV_SET(rd_strm, 1); | 845 | DV_SET(rd_strm, 1); |
842 | DV_SET(wr_flow, 1); | 846 | DV_SET(wr_flow, 1); |
843 | DV_SET(rti, 1); | 847 | DV_SET(rti, 1); |
844 | if (spi_min_period(starget) == 8) | 848 | if (spi_min_period(starget) == 8) |
845 | DV_SET(pcomp_en, 1); | 849 | DV_SET(pcomp_en, 1); |
850 | } else { | ||
851 | DV_SET(iu, 0); | ||
846 | } | 852 | } |
853 | |||
847 | /* now that we've done all this, actually check the bus | 854 | /* now that we've done all this, actually check the bus |
848 | * signal type (if known). Some devices are stupid on | 855 | * signal type (if known). Some devices are stupid on |
849 | * a SE bus and still claim they can try LVD only settings */ | 856 | * a SE bus and still claim they can try LVD only settings */ |
850 | if (i->f->get_signalling) | 857 | if (i->f->get_signalling) |
851 | i->f->get_signalling(shost); | 858 | i->f->get_signalling(shost); |
852 | if (spi_signalling(shost) == SPI_SIGNAL_SE || | 859 | if (spi_signalling(shost) == SPI_SIGNAL_SE || |
853 | spi_signalling(shost) == SPI_SIGNAL_HVD) | 860 | spi_signalling(shost) == SPI_SIGNAL_HVD || |
861 | !scsi_device_dt(sdev)) { | ||
854 | DV_SET(dt, 0); | 862 | DV_SET(dt, 0); |
863 | } else { | ||
864 | DV_SET(dt, 1); | ||
865 | } | ||
855 | /* Do the read only INQUIRY tests */ | 866 | /* Do the read only INQUIRY tests */ |
856 | spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len, | 867 | spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len, |
857 | spi_dv_device_compare_inquiry); | 868 | spi_dv_device_compare_inquiry); |
@@ -907,6 +918,10 @@ spi_dv_device(struct scsi_device *sdev) | |||
907 | if (unlikely(scsi_device_get(sdev))) | 918 | if (unlikely(scsi_device_get(sdev))) |
908 | return; | 919 | return; |
909 | 920 | ||
921 | if (unlikely(spi_dv_in_progress(starget))) | ||
922 | return; | ||
923 | spi_dv_in_progress(starget) = 1; | ||
924 | |||
910 | buffer = kzalloc(len, GFP_KERNEL); | 925 | buffer = kzalloc(len, GFP_KERNEL); |
911 | 926 | ||
912 | if (unlikely(!buffer)) | 927 | if (unlikely(!buffer)) |
@@ -938,6 +953,7 @@ spi_dv_device(struct scsi_device *sdev) | |||
938 | out_free: | 953 | out_free: |
939 | kfree(buffer); | 954 | kfree(buffer); |
940 | out_put: | 955 | out_put: |
956 | spi_dv_in_progress(starget) = 0; | ||
941 | scsi_device_put(sdev); | 957 | scsi_device_put(sdev); |
942 | } | 958 | } |
943 | EXPORT_SYMBOL(spi_dv_device); | 959 | EXPORT_SYMBOL(spi_dv_device); |
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h index 302680c0c0de..da180f738477 100644 --- a/include/scsi/scsi_transport_spi.h +++ b/include/scsi/scsi_transport_spi.h | |||
@@ -53,7 +53,8 @@ struct spi_transport_attrs { | |||
53 | unsigned int support_ius; /* support Information Units */ | 53 | unsigned int support_ius; /* support Information Units */ |
54 | unsigned int support_qas; /* supports quick arbitration and selection */ | 54 | unsigned int support_qas; /* supports quick arbitration and selection */ |
55 | /* Private Fields */ | 55 | /* Private Fields */ |
56 | unsigned int dv_pending:1; /* Internal flag */ | 56 | unsigned int dv_pending:1; /* Internal flag: DV Requested */ |
57 | unsigned int dv_in_progress:1; /* Internal: DV started */ | ||
57 | struct mutex dv_mutex; /* semaphore to serialise dv */ | 58 | struct mutex dv_mutex; /* semaphore to serialise dv */ |
58 | }; | 59 | }; |
59 | 60 | ||