[PATCH] usb-storage: use usb_reset_composite_device
This patch (as701) modifies usb-storage to take advantage of the new usb_reset_composite_device() API. Now we will be able to safely request port resets even if other drivers are bound to a mass-storage device. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
7de18d8bf4
commit
47104b0dd3
@@ -286,11 +286,7 @@ static int bus_reset(struct scsi_cmnd *srb)
|
|||||||
int result;
|
int result;
|
||||||
|
|
||||||
US_DEBUGP("%s called\n", __FUNCTION__);
|
US_DEBUGP("%s called\n", __FUNCTION__);
|
||||||
|
|
||||||
mutex_lock(&(us->dev_mutex));
|
|
||||||
result = usb_stor_port_reset(us);
|
result = usb_stor_port_reset(us);
|
||||||
mutex_unlock(&us->dev_mutex);
|
|
||||||
|
|
||||||
return result < 0 ? FAILED : SUCCESS;
|
return result < 0 ? FAILED : SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -703,16 +703,19 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
|
|||||||
* device reset. */
|
* device reset. */
|
||||||
Handle_Errors:
|
Handle_Errors:
|
||||||
|
|
||||||
/* Let the SCSI layer know we are doing a reset, set the
|
/* Set the RESETTING bit, and clear the ABORTING bit so that
|
||||||
* RESETTING bit, and clear the ABORTING bit so that the reset
|
* the reset may proceed. */
|
||||||
* may proceed. */
|
|
||||||
scsi_lock(us_to_host(us));
|
scsi_lock(us_to_host(us));
|
||||||
usb_stor_report_bus_reset(us);
|
|
||||||
set_bit(US_FLIDX_RESETTING, &us->flags);
|
set_bit(US_FLIDX_RESETTING, &us->flags);
|
||||||
clear_bit(US_FLIDX_ABORTING, &us->flags);
|
clear_bit(US_FLIDX_ABORTING, &us->flags);
|
||||||
scsi_unlock(us_to_host(us));
|
scsi_unlock(us_to_host(us));
|
||||||
|
|
||||||
|
/* We must release the device lock because the pre_reset routine
|
||||||
|
* will want to acquire it. */
|
||||||
|
mutex_unlock(&us->dev_mutex);
|
||||||
result = usb_stor_port_reset(us);
|
result = usb_stor_port_reset(us);
|
||||||
|
mutex_lock(&us->dev_mutex);
|
||||||
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
scsi_lock(us_to_host(us));
|
scsi_lock(us_to_host(us));
|
||||||
usb_stor_report_device_reset(us);
|
usb_stor_report_device_reset(us);
|
||||||
@@ -1196,31 +1199,30 @@ int usb_stor_Bulk_reset(struct us_data *us)
|
|||||||
0, us->ifnum, NULL, 0);
|
0, us->ifnum, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Issue a USB port reset to the device. But don't do anything if
|
/* Issue a USB port reset to the device. The caller must not hold
|
||||||
* there's more than one interface in the device, so that other users
|
* us->dev_mutex.
|
||||||
* are not affected. */
|
*/
|
||||||
int usb_stor_port_reset(struct us_data *us)
|
int usb_stor_port_reset(struct us_data *us)
|
||||||
{
|
{
|
||||||
int result, rc;
|
int result, rc_lock;
|
||||||
|
|
||||||
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
|
result = rc_lock =
|
||||||
result = -EIO;
|
usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
|
||||||
US_DEBUGP("No reset during disconnect\n");
|
if (result < 0)
|
||||||
} else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) {
|
US_DEBUGP("unable to lock device for reset: %d\n", result);
|
||||||
result = -EBUSY;
|
else {
|
||||||
US_DEBUGP("Refusing to reset a multi-interface device\n");
|
/* Were we disconnected while waiting for the lock? */
|
||||||
} else {
|
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
|
||||||
result = rc =
|
result = -EIO;
|
||||||
usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
|
US_DEBUGP("No reset during disconnect\n");
|
||||||
if (result < 0) {
|
|
||||||
US_DEBUGP("unable to lock device for reset: %d\n",
|
|
||||||
result);
|
|
||||||
} else {
|
} else {
|
||||||
result = usb_reset_device(us->pusb_dev);
|
result = usb_reset_composite_device(
|
||||||
if (rc)
|
us->pusb_dev, us->pusb_intf);
|
||||||
usb_unlock_device(us->pusb_dev);
|
US_DEBUGP("usb_reset_composite_device returns %d\n",
|
||||||
US_DEBUGP("usb_reset_device returns %d\n", result);
|
result);
|
||||||
}
|
}
|
||||||
|
if (rc_lock)
|
||||||
|
usb_unlock_device(us->pusb_dev);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@@ -220,6 +220,37 @@ static int storage_resume(struct usb_interface *iface)
|
|||||||
|
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The next two routines get called just before and just after
|
||||||
|
* a USB port reset, whether from this driver or a different one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void storage_pre_reset(struct usb_interface *iface)
|
||||||
|
{
|
||||||
|
struct us_data *us = usb_get_intfdata(iface);
|
||||||
|
|
||||||
|
US_DEBUGP("%s\n", __FUNCTION__);
|
||||||
|
|
||||||
|
/* Make sure no command runs during the reset */
|
||||||
|
mutex_lock(&us->dev_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void storage_post_reset(struct usb_interface *iface)
|
||||||
|
{
|
||||||
|
struct us_data *us = usb_get_intfdata(iface);
|
||||||
|
|
||||||
|
US_DEBUGP("%s\n", __FUNCTION__);
|
||||||
|
|
||||||
|
/* Report the reset to the SCSI core */
|
||||||
|
scsi_lock(us_to_host(us));
|
||||||
|
usb_stor_report_bus_reset(us);
|
||||||
|
scsi_unlock(us_to_host(us));
|
||||||
|
|
||||||
|
/* FIXME: Notify the subdrivers that they need to reinitialize
|
||||||
|
* the device */
|
||||||
|
mutex_unlock(&us->dev_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fill_inquiry_response takes an unsigned char array (which must
|
* fill_inquiry_response takes an unsigned char array (which must
|
||||||
* be at least 36 characters) and populates the vendor name,
|
* be at least 36 characters) and populates the vendor name,
|
||||||
@@ -1002,6 +1033,8 @@ static struct usb_driver usb_storage_driver = {
|
|||||||
.suspend = storage_suspend,
|
.suspend = storage_suspend,
|
||||||
.resume = storage_resume,
|
.resume = storage_resume,
|
||||||
#endif
|
#endif
|
||||||
|
.pre_reset = storage_pre_reset,
|
||||||
|
.post_reset = storage_post_reset,
|
||||||
.id_table = storage_usb_ids,
|
.id_table = storage_usb_ids,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user