patch-2.4.27 linux-2.4.27/drivers/usb/storage/scsiglue.c
Next file: linux-2.4.27/drivers/usb/storage/unusual_devs.h
Previous file: linux-2.4.27/drivers/usb/storage/jumpshot.c
Back to the patch index
Back to the overall index
- Lines: 87
- Date:
2004-08-07 16:26:05.813394401 -0700
- Orig file:
linux-2.4.26/drivers/usb/storage/scsiglue.c
- Orig date:
2004-04-14 06:05:35.000000000 -0700
diff -urN linux-2.4.26/drivers/usb/storage/scsiglue.c linux-2.4.27/drivers/usb/storage/scsiglue.c
@@ -218,7 +218,14 @@
US_DEBUGP("device_reset() called\n" );
spin_unlock_irq(&io_request_lock);
+ down(&(us->dev_semaphore));
+ if (!us->pusb_dev) {
+ up(&(us->dev_semaphore));
+ spin_lock_irq(&io_request_lock);
+ return SUCCESS;
+ }
rc = us->transport_reset(us);
+ up(&(us->dev_semaphore));
spin_lock_irq(&io_request_lock);
return rc;
}
@@ -235,27 +242,44 @@
/* we use the usb_reset_device() function to handle this for us */
US_DEBUGP("bus_reset() called\n");
+ spin_unlock_irq(&io_request_lock);
+
+ down(&(us->dev_semaphore));
+
/* if the device has been removed, this worked */
if (!us->pusb_dev) {
US_DEBUGP("-- device removed already\n");
+ up(&(us->dev_semaphore));
+ spin_lock_irq(&io_request_lock);
return SUCCESS;
}
- spin_unlock_irq(&io_request_lock);
+ /* The USB subsystem doesn't handle synchronisation between
+ * a device's several drivers. Therefore we reset only devices
+ * with just one interface, which we of course own. */
+ if (us->pusb_dev->actconfig->bNumInterfaces != 1) {
+ printk(KERN_NOTICE "usb-storage: "
+ "Refusing to reset a multi-interface device\n");
+ up(&(us->dev_semaphore));
+ spin_lock_irq(&io_request_lock);
+ /* XXX Don't just return success, make sure current cmd fails */
+ return SUCCESS;
+ }
/* release the IRQ, if we have one */
- down(&(us->irq_urb_sem));
if (us->irq_urb) {
US_DEBUGP("-- releasing irq URB\n");
result = usb_unlink_urb(us->irq_urb);
US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
}
- up(&(us->irq_urb_sem));
/* attempt to reset the port */
if (usb_reset_device(us->pusb_dev) < 0) {
- spin_lock_irq(&io_request_lock);
- return FAILED;
+ /*
+ * Do not return errors, or else the error handler might
+ * invoke host_reset, which is not implemented.
+ */
+ goto bail_out;
}
/* FIXME: This needs to lock out driver probing while it's working
@@ -286,17 +310,18 @@
up(&intf->driver->serialize);
}
+bail_out:
/* re-allocate the IRQ URB and submit it to restore connectivity
* for CBI devices
*/
if (us->protocol == US_PR_CBI) {
- down(&(us->irq_urb_sem));
us->irq_urb->dev = us->pusb_dev;
result = usb_submit_urb(us->irq_urb);
US_DEBUGP("usb_submit_urb() returns %d\n", result);
- up(&(us->irq_urb_sem));
}
-
+
+ up(&(us->dev_semaphore));
+
spin_lock_irq(&io_request_lock);
US_DEBUGP("bus_reset() complete\n");
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)