ChangeSet 1.985.10.13, 2003/03/25 13:29:44-08:00, oliver@neukum.name [PATCH] USB: storage device reset cleanup > In the absence of far-reaching changes to the API, my suggestion is to > have the emulated SCSI bus reset code in usb-storage do nothing but log an > error message and return an error code. For the time being, considering > how infrequently these resets occur, we can simply rely on the user > unplugging the USB cable and putting it back in or cycling the power to > the drive. (Yes, there are situations where these resets crop up > regularly -- but they are the result of some other incompatibility that a > device reset won't fix anyway.) OK, as the consensus seems to be that in the short run changing things for a full reset implementation is not worth it, here's an implementation that does the best we can do without. It issues a reset only if we can be sure that there are no other users of the device in question. As the version currently in the storage driver is broken anyway, this is a definite improvement. And it addresses the need of exporting the probe/remove functions for storage's sake. drivers/usb/storage/scsiglue.c | 40 ++++++++++++++-------------------------- 1 files changed, 14 insertions(+), 26 deletions(-) diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c --- a/drivers/usb/storage/scsiglue.c Tue Mar 25 16:45:30 2003 +++ b/drivers/usb/storage/scsiglue.c Tue Mar 25 16:45:30 2003 @@ -231,36 +231,24 @@ scsi_unlock(srb->device->host); us = (struct us_data *)srb->device->host->hostdata[0]; - /* attempt to reset the port */ - result = usb_reset_device(us->pusb_dev); - US_DEBUGP("usb_reset_device returns %d\n", result); - if (result < 0) { - scsi_lock(srb->device->host); - return FAILED; + /* The USB subsystem doesn't handle synchronisation between + a device's several drivers. Therefore we reset only devices + with one interface which we of course own. + */ + + //FIXME: needs locking against config changes + + if ( us->pusb_dev->actconfig->desc.bNumInterfaces == 1) { + /* attempt to reset the port */ + result = usb_reset_device(us->pusb_dev); + US_DEBUGP("usb_reset_device returns %d\n", result); + } else { + result = -EBUSY; } - /* FIXME: This needs to lock out driver probing while it's working - * or we can have race conditions */ - /* This functionality really should be provided by the khubd thread */ - for (i = 0; i < us->pusb_dev->actconfig->desc.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("Examining driver %s...", intf->driver->name); - - /* simulate a disconnect and reconnect for all interfaces */ - US_DEBUGPX("simulating disconnect/reconnect.\n"); - usb_device_remove (&intf->dev); - usb_device_probe (&intf->dev); - } US_DEBUGP("bus_reset() complete\n"); scsi_lock(srb->device->host); - return SUCCESS; + return result < 0 ? FAILED : SUCCESS; } /***********************************************************************