ChangeSet 1.855.9.13, 2002/11/05 11:17:41-08:00, stern@rowland.harvard.edu

[PATCH] USB storage: use the new transfer_buf() routine

This patch switches from using usb_stor_bulk_msg() to
usb_stor_bulk_transfer_buf(), which includes a great deal more logic.  This
allows for elimination of all sorts of duplicate code (clearing STALLs,
etc.).

This also eliminates the (now) redundant functions from the ISD-200 driver.


diff -Nru a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
--- a/drivers/usb/storage/isd200.c	Tue Nov  5 16:10:14 2002
+++ b/drivers/usb/storage/isd200.c	Tue Nov  5 16:10:14 2002
@@ -31,6 +31,8 @@
  *
  * History:
  *
+ *  2002-10-19: Removed the specialized transfer routines.
+ *		(Alan Stern <stern@rowland.harvard.edu>)
  *  2001-02-24: Removed lots of duplicate code and simplified the structure.
  *              (bjorn@haxx.se)
  *  2002-01-16: Fixed endianness bug so it works on the ppc arch.
@@ -386,147 +388,6 @@
         }
 }
 
-/***********************************************************************
- * Data transfer routines
- ***********************************************************************/
-
-
-/**************************************************************************
- * Transfer one SCSI scatter-gather buffer via bulk transfer
- *
- * Note that this function is necessary because we want the ability to
- * use scatter-gather memory.  Good performance is achieved by a combination
- * of scatter-gather and clustering (which makes each chunk bigger).
- *
- * Note that the lower layer will always retry when a NAK occurs, up to the
- * timeout limit.  Thus we don't have to worry about it for individual
- * packets.
- */
-static int isd200_transfer_partial( struct us_data *us, 
-				    unsigned char dataDirection,
-				    char *buf, int length )
-{
-        int result;
-        int partial;
-        unsigned int pipe;
-
-        /* calculate the appropriate pipe information */
-	if (dataDirection == SCSI_DATA_READ)
-                pipe = us->recv_bulk_pipe;
-        else
-                pipe = us->send_bulk_pipe;
-
-        /* transfer the data */
-        US_DEBUGP("isd200_transfer_partial(): xfer %d bytes\n", length);
-        result = usb_stor_bulk_msg(us, buf, pipe, length, &partial);
-        US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n",
-                  result, partial, length);
-
-        /* if we stall, we need to clear it before we go on */
-        if (result == -EPIPE) {
-                US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
-                if (usb_stor_clear_halt(us, pipe) < 0)
-			return ISD200_TRANSPORT_FAILED;
-        }
-    
-        /* did we send all the data? */
-        if (partial == length) {
-                US_DEBUGP("isd200_transfer_partial(): transfer complete\n");
-                return ISD200_TRANSPORT_GOOD;
-        }
-
-	/* did we abort this command? */
-	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-                US_DEBUGP("isd200_transfer_partial(): transfer aborted\n");
-		return ISD200_TRANSPORT_ABORTED;
-	}
-
-        /* uh oh... we have an error code, so something went wrong. */
-        if (result) {
-                /* NAK - that means we've retried a few times already */
-                if (result == -ETIMEDOUT) {
-                        US_DEBUGP("isd200_transfer_partial(): device NAKed\n");
-                        return ISD200_TRANSPORT_FAILED;
-                }
-
-                /* the catch-all case */
-                US_DEBUGP("isd200_transfer_partial(): unknown error\n");
-                return ISD200_TRANSPORT_FAILED;
-        }
-
-        /* no error code, so we must have transferred some data, 
-         * just not all of it */
-        return ISD200_TRANSPORT_SHORT;
-}
-
-
-/**************************************************************************
- * Transfer an entire SCSI command's worth of data payload over the bulk
- * pipe.
- *
- * Note that this uses us_transfer_partial to achieve it's goals -- this
- * function simply determines if we're going to use scatter-gather or not,
- * and acts appropriately.  For now, it also re-interprets the error codes.
- */
-static void isd200_transfer( struct us_data *us, Scsi_Cmnd *srb )
-{
-        int i;
-        int result = -1;
-        struct scatterlist *sg;
-        unsigned int total_transferred = 0;
-        unsigned int transfer_amount;
-
-        /* calculate how much we want to transfer */
-	int dir = srb->sc_data_direction;
-	srb->sc_data_direction = SCSI_DATA_WRITE;
-        transfer_amount = usb_stor_transfer_length(srb);
-	srb->sc_data_direction = dir;
-
-        /* was someone foolish enough to request more data than available
-         * buffer space? */
-        if (transfer_amount > srb->request_bufflen)
-                transfer_amount = srb->request_bufflen;
-
-        /* are we scatter-gathering? */
-        if (srb->use_sg) {
-
-                /* loop over all the scatter gather structures and 
-                 * make the appropriate requests for each, until done
-                 */
-                sg = (struct scatterlist *) srb->request_buffer;
-                for (i = 0; i < srb->use_sg; i++) {
-
-                        /* transfer the lesser of the next buffer or the
-                         * remaining data */
-                        if (transfer_amount - total_transferred >= 
-                            sg[i].length) {
-                                result = isd200_transfer_partial(us, 
-                                                                 srb->sc_data_direction,
-                                                                 sg_address(sg[i]), 
-                                                                 sg[i].length);
-                                total_transferred += sg[i].length;
-                        } else
-                                result = isd200_transfer_partial(us, 
-                                                                 srb->sc_data_direction,                            
-                                                                 sg_address(sg[i]), 
-                                                                 transfer_amount - total_transferred);
-
-                        /* if we get an error, end the loop here */
-                        if (result)
-                                break;
-                }
-        }
-        else
-                /* no scatter-gather, just make the request */
-                result = isd200_transfer_partial(us, 
-                                                 srb->sc_data_direction,
-                                                 srb->request_buffer, 
-                                                 transfer_amount);
-
-        /* return the result in the data structure itself */
-        srb->result = result;
-}
-
 
 /***********************************************************************
  * Transport routines
@@ -546,23 +407,21 @@
         struct bulk_cb_wrap bcb;
         struct bulk_cs_wrap bcs;
         int result;
-        int partial;
-        unsigned int transfer_amount;
+        unsigned int transfer_length;
 
 	int dir = srb->sc_data_direction;
 	srb->sc_data_direction = SCSI_DATA_WRITE;
-        transfer_amount = usb_stor_transfer_length(srb);
+        transfer_length = usb_stor_transfer_length(srb);
 	srb->sc_data_direction = dir;
     
         /* set up the command wrapper */
         bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
-        bcb.DataTransferLength = cpu_to_le32(transfer_amount);
+        bcb.DataTransferLength = cpu_to_le32(transfer_length);
         bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
         bcb.Tag = srb->serial_number;
         bcb.Lun = srb->cmnd[1] >> 5;
         if (us->flags & US_FL_SCM_MULT_TARG)
                 bcb.Lun |= srb->target << 4;
-
         bcb.Length = AtaCdbLength;
     
         /* copy the command payload */
@@ -572,33 +431,32 @@
         /* send it to out endpoint */
         US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
                   le32_to_cpu(bcb.Signature), bcb.Tag,
-                  (bcb.Lun >> 4), (bcb.Lun & 0xFF), 
+                  (bcb.Lun >> 4), (bcb.Lun & 0x0F), 
                   le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length);
-        result = usb_stor_bulk_msg(us, &bcb, us->send_bulk_pipe,
-				US_BULK_CB_WRAP_LEN, &partial);
+	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+				(char *) &bcb, US_BULK_CB_WRAP_LEN, NULL);
         US_DEBUGP("Bulk command transfer result=%d\n", result);
     
 	/* did we abort this command? */
 	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
 		return ISD200_TRANSPORT_ABORTED;
 	}
-
-	else if (result == -EPIPE) {
-		/* if we stall, we need to clear it before we go on */
-                US_DEBUGP("clearing endpoint halt for pipe 0x%x\n",
-				us->send_bulk_pipe);
-                if (usb_stor_clear_halt(us, us->send_bulk_pipe) < 0)
-			return ISD200_TRANSPORT_ERROR;
-	} else if (result)  
+	if (result != USB_STOR_XFER_GOOD)  
                 return ISD200_TRANSPORT_ERROR;
     
         /* if the command transfered well, then we go to the data stage */
-        if (!result && bcb.DataTransferLength) {
-		isd200_transfer(us, srb);
-		US_DEBUGP("Bulk data transfer result 0x%x\n", srb->result);
-		
-		if (srb->result == ISD200_TRANSPORT_ABORTED)
+	if (transfer_length) {
+		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+				us->recv_bulk_pipe : us->send_bulk_pipe;
+		result = usb_stor_bulk_transfer_srb(us, pipe, srb,
+					transfer_length);
+		US_DEBUGP("Bulk data transfer result 0x%x\n", result);
+
+		/* if it was aborted, we need to indicate that */
+		if (result == USB_STOR_XFER_ABORTED)
 			return ISD200_TRANSPORT_ABORTED;
+		if (result == USB_STOR_XFER_ERROR)
+			return ISD200_TRANSPORT_ERROR;
         }
     
         /* See flow chart on pg 15 of the Bulk Only Transport spec for
@@ -607,42 +465,31 @@
     
         /* get CSW for device status */
         US_DEBUGP("Attempting to get CSW...\n");
-        result = usb_stor_bulk_msg(us, &bcs, us->recv_bulk_pipe,
-				US_BULK_CS_WRAP_LEN, &partial);
+	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+				(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
+
 	/* did we abort this command? */
 	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
 		return ISD200_TRANSPORT_ABORTED;
 	}
 
         /* did the attempt to read the CSW fail? */
-        if (result == -EPIPE) {
-                US_DEBUGP("clearing endpoint halt for pipe 0x%x\n",
-				us->recv_bulk_pipe);
-                if (usb_stor_clear_halt(us, us->recv_bulk_pipe) < 0)
-			return ISD200_TRANSPORT_ERROR;
+	if (result == USB_STOR_XFER_STALLED) {
            
                 /* get the status again */
                 US_DEBUGP("Attempting to get CSW (2nd try)...\n");
-                result = usb_stor_bulk_msg(us, &bcs, us->recv_bulk_pipe,
-                                           US_BULK_CS_WRAP_LEN, &partial);
+		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+				(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
 
                 /* if the command was aborted, indicate that */
 		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
 			return ISD200_TRANSPORT_ABORTED;
 		}
-        
-                /* if it fails again, we need a reset and return an error*/
-                if (result == -EPIPE) {
-                        US_DEBUGP("clearing halt for pipe 0x%x\n",
-					us->recv_bulk_pipe);
-                        usb_stor_clear_halt(us, us->recv_bulk_pipe);
-                        return ISD200_TRANSPORT_ERROR;
-                }
         }
     
         /* if we still have a failure at this point, we're in trouble */
         US_DEBUGP("Bulk status result = %d\n", result);
-        if (result)
+        if (result != USB_STOR_XFER_GOOD)
                 return ISD200_TRANSPORT_ERROR;
     
         /* check bulk status */
@@ -651,7 +498,7 @@
                   bcs.Residue, bcs.Status);
         if (bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) || 
             bcs.Tag != bcb.Tag || 
-            bcs.Status > US_BULK_STAT_PHASE || partial != 13) {
+            bcs.Status > US_BULK_STAT_PHASE) {
                 US_DEBUGP("Bulk logical error\n");
                 return ISD200_TRANSPORT_ERROR;
         }
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	Tue Nov  5 16:10:14 2002
+++ b/drivers/usb/storage/transport.c	Tue Nov  5 16:10:14 2002
@@ -1296,7 +1296,6 @@
 	struct bulk_cs_wrap bcs;
 	unsigned int transfer_length = usb_stor_transfer_length(srb);
 	int result;
-	int partial;
 
 	/* set up the command wrapper */
 	bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
@@ -1316,9 +1315,9 @@
 	US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
 		  le32_to_cpu(bcb.Signature), bcb.Tag,
 		  (bcb.Lun >> 4), (bcb.Lun & 0x0F), 
-		  bcb.DataTransferLength, bcb.Flags, bcb.Length);
-	result = usb_stor_bulk_msg(us, &bcb, us->send_bulk_pipe,
-				US_BULK_CB_WRAP_LEN, &partial);
+		  le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length);
+	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+				(char *) &bcb, US_BULK_CB_WRAP_LEN, NULL);
 	US_DEBUGP("Bulk command transfer result=%d\n", result);
 
 	/* did we abort this command? */
@@ -1326,23 +1325,8 @@
 		US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
 		return USB_STOR_TRANSPORT_ABORTED;
 	}
-
-	/* if we stall, we need to clear it before we go on */
-	if (result == -EPIPE) {
-		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n",
-				us->send_bulk_pipe);
-		result = usb_stor_clear_halt(us, us->send_bulk_pipe);
-
-		/* did we abort this command? */
-		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-			US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
-			return USB_STOR_TRANSPORT_ABORTED;
-		}
-		return USB_STOR_TRANSPORT_ERROR;
-	} else if (result) {
-		/* unknown error -- we've got a problem */
+	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
-	}
 
 	/* DATA STAGE */
 	/* send/receive data payload, if there is any */
@@ -1366,8 +1350,8 @@
 
 	/* get CSW for device status */
 	US_DEBUGP("Attempting to get CSW...\n");
-	result = usb_stor_bulk_msg(us, &bcs, us->recv_bulk_pipe,
-				US_BULK_CS_WRAP_LEN, &partial);
+	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+				(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
 
 	/* did we abort this command? */
 	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
@@ -1376,50 +1360,24 @@
 	}
 
 	/* did the attempt to read the CSW fail? */
-	if (result == -EPIPE) {
-		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n",
-				us->recv_bulk_pipe);
-		result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
-
-		/* did we abort this command? */
-		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-			US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
-			return USB_STOR_TRANSPORT_ABORTED;
-		}
-		if (result < 0)
-			return USB_STOR_TRANSPORT_ERROR;
+	if (result == USB_STOR_XFER_STALLED) {
 
 		/* get the status again */
 		US_DEBUGP("Attempting to get CSW (2nd try)...\n");
-		result = usb_stor_bulk_msg(us, &bcs, us->recv_bulk_pipe,
-					   US_BULK_CS_WRAP_LEN, &partial);
+		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+				(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
 
 		/* did we abort this command? */
 		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
 			US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
 			return USB_STOR_TRANSPORT_ABORTED;
 		}
-
-		/* if it fails again, we need a reset and return an error*/
-		if (result == -EPIPE) {
-			US_DEBUGP("clearing halt for pipe 0x%x\n",
-					us->recv_bulk_pipe);
-			result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
-
-			/* did we abort this command? */
-			if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-				US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
-				return USB_STOR_TRANSPORT_ABORTED;
-			}
-			return USB_STOR_TRANSPORT_ERROR;
-		}
 	}
 
 	/* if we still have a failure at this point, we're in trouble */
 	US_DEBUGP("Bulk status result = %d\n", result);
-	if (result) {
+	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
-	}
 
 	/* check bulk status */
 	US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
@@ -1427,7 +1385,7 @@
 		  bcs.Residue, bcs.Status);
 	if (bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) || 
 	    bcs.Tag != bcb.Tag || 
-	    bcs.Status > US_BULK_STAT_PHASE || partial != 13) {
+	    bcs.Status > US_BULK_STAT_PHASE) {
 		US_DEBUGP("Bulk logical error\n");
 		return USB_STOR_TRANSPORT_ERROR;
 	}
