Commit 933d87fc authored by Alan Stern's avatar Alan Stern Committed by Deepak Saxena

[PATCH] USB Storage: Handle excess 0-length data packets

This patch is an attempt to cope with Genesys Logic's, shall we say,
creative approach to implementing the USB protocols.  Their high-speed
mass storage devices sometimes add an excess 0-length packet to the end of
a data phase transmission.  Of course we don't read that packet as part of
the data phase; we see it as a 0-length CSW message.  The real CSW follows
immediately after.  (Or sometimes a STALL follows immediately after, with
the real CSW coming after that!)

The patch checks the results of the first attempt to read the CSW.  If it
sees a normal packet (not a STALL) with length 0, it retries the read.
Reports from two users indicate that it improves the performance of their
USB-2 DVD drives.
parent 77d9c334
...@@ -929,6 +929,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -929,6 +929,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
unsigned int residue; unsigned int residue;
int result; int result;
int fake_sense = 0; int fake_sense = 0;
unsigned int cswlen;
/* set up the command wrapper */ /* set up the command wrapper */
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
...@@ -985,7 +986,17 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -985,7 +986,17 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* get CSW for device status */ /* get CSW for device status */
US_DEBUGP("Attempting to get CSW...\n"); US_DEBUGP("Attempting to get CSW...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
bcs, US_BULK_CS_WRAP_LEN, NULL); bcs, US_BULK_CS_WRAP_LEN, &cswlen);
/* Some broken devices add unnecessary zero-length packets to the
* end of their data transfers. Such packets show up as 0-length
* CSWs. If we encounter such a thing, try to read the CSW again.
*/
if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
US_DEBUGP("Received 0-length CSW; retrying...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
bcs, US_BULK_CS_WRAP_LEN, &cswlen);
}
/* did the attempt to read the CSW fail? */ /* did the attempt to read the CSW fail? */
if (result == USB_STOR_XFER_STALLED) { if (result == USB_STOR_XFER_STALLED) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment