ChangeSet 1.1557.49.10, 2004/02/17 16:43:54-08:00, stern@rowland.harvard.edu [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. drivers/usb/storage/transport.c | 13 ++++++++++++- 1 files changed, 12 insertions(+), 1 deletion(-) diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c --- a/drivers/usb/storage/transport.c Thu Feb 19 17:22:17 2004 +++ b/drivers/usb/storage/transport.c Thu Feb 19 17:22:17 2004 @@ -929,6 +929,7 @@ unsigned int residue; int result; int fake_sense = 0; + unsigned int cswlen; /* set up the command wrapper */ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); @@ -985,7 +986,17 @@ /* get CSW for device status */ US_DEBUGP("Attempting to get CSW...\n"); 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? */ if (result == USB_STOR_XFER_STALLED) {