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

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

diff -u --recursive --new-file v2.4.0-test8/linux/drivers/usb/storage/scsiglue.c linux/drivers/usb/storage/scsiglue.c
@@ -1,7 +1,7 @@
 /* Driver for USB Mass Storage compliant devices
  * SCSI layer glue code
  *
- * $Id: scsiglue.c,v 1.9 2000/08/25 00:13:51 mdharm Exp $
+ * $Id: scsiglue.c,v 1.13 2000/09/28 21:54:30 mdharm Exp $
  *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -112,7 +112,7 @@
 {
 	struct us_data *us = (struct us_data *)psh->hostdata[0];
 
-	US_DEBUGP("us_release() called for host %s\n", us->htmplt.name);
+	US_DEBUGP("release() called for host %s\n", us->htmplt.name);
 
 	/* Kill the control threads
 	 *
@@ -124,9 +124,7 @@
 	wake_up(&(us->wqh));
 	down(&(us->notify));
 	
-	/* free the data structure we were using */
-	US_DEBUGP("-- freeing URB\n");
-	kfree(us->current_urb);
+	/* remove the pointer to the data structure we were using */
 	(struct us_data*)psh->hostdata[0] = NULL;
 
 	/* we always have a successful release */
@@ -189,12 +187,6 @@
 		return SUCCESS;
 	}
 
-	/* This is a sanity check that we should never hit */
-	if (in_interrupt()) {
-		printk(KERN_ERR "usb-storage: command_abort() called from an interrupt!!! BAD!!! BAD!! BAD!!\n");
-		return FAILED;
-	}
-
 	/* if we have an urb pending, let's wake the control thread up */
 	if (us->current_urb->status == -EINPROGRESS) {
 		/* cancel the URB */
@@ -213,18 +205,62 @@
 	return FAILED;
 }
 
-/* FIXME: this doesn't do anything right now */
+/* This invokes the transport reset mechanism to reset the state of the
+ * device */
+static int device_reset( Scsi_Cmnd *srb )
+{
+	struct us_data *us = (struct us_data *)srb->host->hostdata[0];
+
+	US_DEBUGP("device_reset() called\n" );
+	return us->transport_reset(us);
+}
+
+/* This resets the device port, and simulates the device
+ * disconnect/reconnect for all drivers which have claimed other
+ * interfaces. */
 static int bus_reset( Scsi_Cmnd *srb )
 {
-	// struct us_data *us = (struct us_data *)srb->host->hostdata[0];
+	struct us_data *us = (struct us_data *)srb->host->hostdata[0];
+	int i;
 
-	printk(KERN_CRIT "usb-storage: bus_reset() requested but not implemented\n" );
-	US_DEBUGP("Bus reset requested\n");
-	//  us->transport_reset(us);
-	return FAILED;
+	/* we use the usb_reset_device() function to handle this for us */
+	US_DEBUGP("bus_reset() called\n");
+
+	/* attempt to reset the port */
+	if (usb_reset_device(us->pusb_dev) < 0)
+		return FAILED;
+
+	/* FIXME: This needs to lock out driver probing while it's working
+	 * or we can have race conditions */
+        for (i = 0; i < us->pusb_dev->actconfig->bNumInterfaces; i++) {
+ 		struct usb_interface *intf =
+			&us->pusb_dev->actconfig->interface[i];
+
+		/* if this is an unclaimed interface, skip it */
+		if (!intf->driver) {
+			continue;
+		}
+
+		US_DEBUGP("Examinging driver %s...", intf->driver->name);
+		/* skip interfaces which we've claimed */
+		if (intf->driver == &usb_storage_driver) {
+			US_DEBUGPX("skipping ourselves.\n");
+			continue;
+		}
+		
+		/* simulate a disconnect and reconnect for all interfaces */
+		US_DEBUGPX("simulating disconnect/reconnect.\n");
+		down(&intf->driver->serialize);
+		intf->driver->disconnect(us->pusb_dev, intf->private_data);
+		intf->driver->probe(us->pusb_dev, i);
+		up(&intf->driver->serialize);
+	}
+
+	US_DEBUGP("bus_reset() complete\n");
+	return SUCCESS;
 }
 
-/* FIXME: This doesn't actually reset anything */
+/* FIXME: This doesn't do anything right now */
 static int host_reset( Scsi_Cmnd *srb )
 {
 	printk(KERN_CRIT "usb-storage: host_reset() requested but not implemented\n" );
@@ -261,9 +297,11 @@
 		us = us->next;
 	}
 
+	/* release our lock on the data structures */
+	up(&us_list_semaphore);
+
 	/* if we couldn't find it, we return an error */
 	if (!us) {
-		up(&us_list_semaphore);
 		return -ESRCH;
 	}
 	
@@ -282,9 +320,6 @@
 	/* show the GUID of the device */
 	SPRINTF("         GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid));
 
-	/* release our lock on the data structures */
-	up(&us_list_semaphore);
-
 	/*
 	 * Calculate start of next buffer, and return value.
 	 */
@@ -313,7 +348,7 @@
 	queuecommand:		queuecommand,
 
 	eh_abort_handler:	command_abort,
-	eh_device_reset_handler:bus_reset,
+	eh_device_reset_handler:device_reset,
 	eh_bus_reset_handler:	bus_reset,
 	eh_host_reset_handler:	host_reset,
 

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