diff options
Diffstat (limited to 'drivers/usb/storage/transport.c')
-rw-r--r-- | drivers/usb/storage/transport.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 22c7d4360fa2..b1d815eb6d0b 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c | |||
@@ -1118,6 +1118,31 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
1118 | */ | 1118 | */ |
1119 | if (result == USB_STOR_XFER_LONG) | 1119 | if (result == USB_STOR_XFER_LONG) |
1120 | fake_sense = 1; | 1120 | fake_sense = 1; |
1121 | |||
1122 | /* | ||
1123 | * Sometimes a device will mistakenly skip the data phase | ||
1124 | * and go directly to the status phase without sending a | ||
1125 | * zero-length packet. If we get a 13-byte response here, | ||
1126 | * check whether it really is a CSW. | ||
1127 | */ | ||
1128 | if (result == USB_STOR_XFER_SHORT && | ||
1129 | srb->sc_data_direction == DMA_FROM_DEVICE && | ||
1130 | transfer_length - scsi_get_resid(srb) == | ||
1131 | US_BULK_CS_WRAP_LEN) { | ||
1132 | struct scatterlist *sg = NULL; | ||
1133 | unsigned int offset = 0; | ||
1134 | |||
1135 | if (usb_stor_access_xfer_buf((unsigned char *) bcs, | ||
1136 | US_BULK_CS_WRAP_LEN, srb, &sg, | ||
1137 | &offset, FROM_XFER_BUF) == | ||
1138 | US_BULK_CS_WRAP_LEN && | ||
1139 | bcs->Signature == | ||
1140 | cpu_to_le32(US_BULK_CS_SIGN)) { | ||
1141 | usb_stor_dbg(us, "Device skipped data phase\n"); | ||
1142 | scsi_set_resid(srb, transfer_length); | ||
1143 | goto skipped_data_phase; | ||
1144 | } | ||
1145 | } | ||
1121 | } | 1146 | } |
1122 | 1147 | ||
1123 | /* See flow chart on pg 15 of the Bulk Only Transport spec for | 1148 | /* See flow chart on pg 15 of the Bulk Only Transport spec for |
@@ -1153,6 +1178,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
1153 | if (result != USB_STOR_XFER_GOOD) | 1178 | if (result != USB_STOR_XFER_GOOD) |
1154 | return USB_STOR_TRANSPORT_ERROR; | 1179 | return USB_STOR_TRANSPORT_ERROR; |
1155 | 1180 | ||
1181 | skipped_data_phase: | ||
1156 | /* check bulk status */ | 1182 | /* check bulk status */ |
1157 | residue = le32_to_cpu(bcs->Residue); | 1183 | residue = le32_to_cpu(bcs->Residue); |
1158 | usb_stor_dbg(us, "Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", | 1184 | usb_stor_dbg(us, "Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", |