Commit d4da2538 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman

[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.
parent 4a0d16e8
...@@ -231,36 +231,24 @@ static int usb_storage_bus_reset( Scsi_Cmnd *srb ) ...@@ -231,36 +231,24 @@ static int usb_storage_bus_reset( Scsi_Cmnd *srb )
scsi_unlock(srb->device->host); scsi_unlock(srb->device->host);
us = (struct us_data *)srb->device->host->hostdata[0]; us = (struct us_data *)srb->device->host->hostdata[0];
/* attempt to reset the port */ /* The USB subsystem doesn't handle synchronisation between
result = usb_reset_device(us->pusb_dev); a device's several drivers. Therefore we reset only devices
US_DEBUGP("usb_reset_device returns %d\n", result); with one interface which we of course own.
if (result < 0) { */
scsi_lock(srb->device->host);
return FAILED; //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"); US_DEBUGP("bus_reset() complete\n");
scsi_lock(srb->device->host); scsi_lock(srb->device->host);
return SUCCESS; return result < 0 ? FAILED : SUCCESS;
} }
/*********************************************************************** /***********************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment