aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage/transport.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/storage/transport.c')
-rw-r--r--drivers/usb/storage/transport.c26
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",