patch-2.4.0-test9 linux/drivers/usb/storage/transport.c

Next file: linux/drivers/usb/storage/transport.h
Previous file: linux/drivers/usb/storage/shuttle_usbat.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test8/linux/drivers/usb/storage/transport.c linux/drivers/usb/storage/transport.c
@@ -1,6 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  *
- * $Id: transport.c,v 1.18 2000/08/25 00:13:51 mdharm Exp $
+ * $Id: transport.c,v 1.27 2000/09/28 21:54:30 mdharm Exp $
  *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -43,6 +43,8 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
+
+#include <linux/config.h>
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
@@ -680,7 +682,7 @@
 		need_auto_sense = 1;
 	}
 	if (result == USB_STOR_TRANSPORT_ERROR) {
-		/* FIXME: we need to invoke a transport reset here */
+		us->transport_reset(us);
 		US_DEBUGP("-- transport indicates transport failure\n");
 		need_auto_sense = 0;
 		srb->result = DID_ERROR << 16;
@@ -742,8 +744,15 @@
 		/* issue the auto-sense command */
 		temp_result = us->transport(us->srb, us);
 		if (temp_result != USB_STOR_TRANSPORT_GOOD) {
-			/* FIXME: we need to invoke a transport reset here */
 			US_DEBUGP("-- auto-sense failure\n");
+
+			/* we skip the reset if this happens to be a
+			 * multi-target device, since failure of an
+			 * auto-sense is perfectly valid
+			 */
+			if (!(us->flags & US_FL_SCM_MULT_TARG)) {
+				us->transport_reset(us);
+			}
 			srb->result = DID_ERROR << 16;
 			return;
 		}
@@ -754,9 +763,15 @@
 			  srb->sense_buffer[2] & 0xf,
 			  srb->sense_buffer[12], 
 			  srb->sense_buffer[13]);
+#ifdef CONFIG_USB_STORAGE_DEBUG
+		usb_stor_show_sense(
+			  srb->sense_buffer[2] & 0xf,
+			  srb->sense_buffer[12], 
+			  srb->sense_buffer[13]);
+#endif
 
 		/* set the result so the higher layers expect this data */
-		srb->result = CHECK_CONDITION;
+		srb->result = CHECK_CONDITION << 1;
 
 		/* we're done here, let's clean up */
 		srb->request_buffer = old_request_buffer;
@@ -767,15 +782,15 @@
 
 		/* If things are really okay, then let's show that */
 		if ((srb->sense_buffer[2] & 0xf) == 0x0)
-			srb->result = GOOD;
+			srb->result = GOOD << 1;
 	} else /* if (need_auto_sense) */
-		srb->result = GOOD;
+		srb->result = GOOD << 1;
 
 	/* Regardless of auto-sense, if we _know_ we have an error
 	 * condition, show that in the result code
 	 */
 	if (result == USB_STOR_TRANSPORT_FAILED)
-		srb->result = CHECK_CONDITION;
+		srb->result = CHECK_CONDITION << 1;
 
 	/* If we think we're good, then make sure the sense data shows it.
 	 * This is necessary because the auto-sense for some devices always
@@ -822,6 +837,9 @@
 {
 	int result;
 
+	/* Set up for status notification */
+	us->ip_wanted = 1;
+
 	/* COMMAND STAGE */
 	/* let's send the command via the control pipe */
 	result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0),
@@ -832,6 +850,9 @@
 	/* check the return code for the command */
 	US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);
 	if (result < 0) {
+		/* Reset flag for status notification */
+		us->ip_wanted = 0;
+
 		/* if the command was aborted, indicate that */
 		if (result == -ENOENT)
 			return USB_STOR_TRANSPORT_ABORTED;
@@ -850,9 +871,6 @@
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
-	/* Set up for status notification */
-	us->ip_wanted = 1;
-
 	/* DATA STAGE */
 	/* transfer the data payload for this command, if one exists*/
 	if (us_transfer_length(srb)) {
@@ -860,8 +878,12 @@
 		US_DEBUGP("CBI data stage result is 0x%x\n", srb->result);
 
 		/* if it was aborted, we need to indicate that */
-		if (srb->result == USB_STOR_TRANSPORT_ABORTED)
+		if (srb->result == USB_STOR_TRANSPORT_ABORTED) {
+			/* we need to reset the state of this semaphore */
+			down(&(us->ip_waitq));
+
 			return USB_STOR_TRANSPORT_ABORTED;
+		}
 	}
 
 	/* STATUS STAGE */
@@ -1038,7 +1060,7 @@
 	/* 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), 
 		  bcb.DataTransferLength, bcb.Flags, bcb.Length);
 	result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN, 
 				   &partial);
@@ -1137,8 +1159,9 @@
 		return USB_STOR_TRANSPORT_FAILED;
 		
 	case US_BULK_STAT_PHASE:
-		/* phase error */
-		usb_stor_Bulk_reset(us);
+		/* phase error -- note that a transport reset will be
+		 * invoked by the invoke_transport() function
+		 */
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 	
@@ -1167,8 +1190,15 @@
 				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 				 0, us->ifnum, cmd, sizeof(cmd), HZ*5);
 
+	if (result < 0) {
+		US_DEBUGP("CB[I] soft reset failed %d\n", result);
+		return FAILED;
+	}
+
 	/* long wait for reset */
+	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(HZ*6);
+	set_current_state(TASK_RUNNING);
 
 	US_DEBUGP("CB_reset: clearing endpoint halt\n");
 	clear_halt(us->pusb_dev, 
@@ -1177,7 +1207,8 @@
 		   usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
 
 	US_DEBUGP("CB_reset done\n");
-	return 0;
+	/* return a result code based on the result of the control message */
+	return SUCCESS;
 }
 
 /* This issues a Bulk-only Reset to the device in question, including
@@ -1195,16 +1226,20 @@
 				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 				 0, us->ifnum, NULL, 0, HZ*5);
 
-	if (result < 0)
-		US_DEBUGP("Bulk hard reset failed %d\n", result);
+	if (result < 0) {
+		US_DEBUGP("Bulk soft reset failed %d\n", result);
+		return FAILED;
+	}
+
+	/* long wait for reset */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ*6);
+	set_current_state(TASK_RUNNING);
 
 	clear_halt(us->pusb_dev, 
 		   usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
 	clear_halt(us->pusb_dev, 
 		   usb_sndbulkpipe(us->pusb_dev, us->ep_out));
-
-	/* long wait for reset */
-	schedule_timeout(HZ*6);
-
-	return result;
+	US_DEBUGP("Bulk soft reset completed\n");
+	return SUCCESS;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)