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) {
