Commit ac01ad71 authored by Matthew Dharm's avatar Matthew Dharm Committed by Greg Kroah-Hartman

[PATCH] USB: usb-storage: usb_stor_control_msg() and stuff

This patch replaces usb_control_msg() with usb_stor_control_msg() everywhere,
which allows better abort/disconnect processing.

Some comments are fixed-up.

The GetMaxLUN function is moved later so URBs are initialized (now that it
uses the new control_msg() ).

There is also some locking cleanup during reset.
parent 08c85f44
......@@ -399,7 +399,7 @@ freecom_init (struct us_data *us)
}
}
result = usb_control_msg(us->pusb_dev, us->recv_ctrl_pipe,
result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);
buffer[32] = '\0';
US_DEBUGP("String returned from FC init is: %s\n", buffer);
......@@ -411,7 +411,7 @@ freecom_init (struct us_data *us)
*/
/* send reset */
result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe,
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ);
US_DEBUGP("result from activate reset is %d\n", result);
......@@ -419,7 +419,7 @@ freecom_init (struct us_data *us)
mdelay(250);
/* clear reset */
result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe,
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ);
US_DEBUGP("result from clear reset is %d\n", result);
......
......@@ -50,7 +50,7 @@ int usb_stor_euscsi_init(struct us_data *us)
int result;
US_DEBUGP("Attempting to init eUSCSI bridge...\n");
result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe,
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR,
0x01, 0x0, &data, 0x1, 5*HZ);
US_DEBUGP("-- result is %d\n", result);
......
......@@ -39,6 +39,7 @@
#include <linux/config.h>
#include "usb.h"
#include "transport.h"
/* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target
* mode */
......
......@@ -219,7 +219,7 @@ static int usb_storage_device_reset( Scsi_Cmnd *srb )
int state = atomic_read(&us->sm_state);
int result;
US_DEBUGP("device_reset() called\n" );
US_DEBUGP("%s called\n", __FUNCTION__);
if (state != US_STATE_IDLE) {
printk(KERN_ERR USB_STORAGE "Error in %s: "
"invalid state %d\n", __FUNCTION__, state);
......@@ -245,39 +245,49 @@ static int usb_storage_device_reset( Scsi_Cmnd *srb )
return result;
}
/* This resets the device port */
/* This resets the device's USB port. */
/* It refuses to work if there's more than one interface in
this device, so that other users are not affected. */
* the device, so that other users are not affected. */
/* This is always called with scsi_lock(srb->host) held */
static int usb_storage_bus_reset( Scsi_Cmnd *srb )
{
struct us_data *us;
struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
int state = atomic_read(&us->sm_state);
int result;
/* we use the usb_reset_device() function to handle this for us */
US_DEBUGP("bus_reset() called\n");
US_DEBUGP("%s called\n", __FUNCTION__);
if (state != US_STATE_IDLE) {
printk(KERN_ERR USB_STORAGE "Error in %s: "
"invalid state %d\n", __FUNCTION__, state);
return FAILED;
}
/* set the state and release the lock */
atomic_set(&us->sm_state, US_STATE_RESETTING);
scsi_unlock(srb->device->host);
us = (struct us_data *)srb->device->host->hostdata[0];
/* 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.
with just 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 */
if (us->pusb_dev->actconfig->desc.bNumInterfaces == 1) {
/* lock the device and attempt to reset the port */
down(&(us->dev_semaphore));
result = usb_reset_device(us->pusb_dev);
up(&(us->dev_semaphore));
US_DEBUGP("usb_reset_device returns %d\n", result);
} else {
result = -EBUSY;
US_DEBUGP("cannot reset a multiinterface device. failing to reset.\n");
US_DEBUGP("Refusing to reset a multi-interface device\n");
}
US_DEBUGP("bus_reset() complete\n");
/* lock access to the state and clear it */
scsi_lock(srb->device->host);
atomic_set(&us->sm_state, US_STATE_IDLE);
return result < 0 ? FAILED : SUCCESS;
}
......
......@@ -875,11 +875,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
unsigned char data;
int result;
/* Issue the command -- use usb_control_msg() because this is
* not a scsi queued-command. Also note that at this point the
* cached pipe values have not yet been stored. */
result = usb_control_msg(us->pusb_dev,
usb_rcvctrlpipe(us->pusb_dev, 0),
/* issue the command */
result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
US_BULK_GET_MAX_LUN,
USB_DIR_IN | USB_TYPE_CLASS |
USB_RECIP_INTERFACE,
......@@ -1027,10 +1024,12 @@ static int usb_stor_reset_common(struct us_data *us,
return FAILED;
}
/* long wait for reset */
/* long wait for reset, so unlock to allow disconnects */
up(&us->dev_semaphore);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ*6);
set_current_state(TASK_RUNNING);
down(&us->dev_semaphore);
US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");
result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
......
......@@ -412,9 +412,11 @@ static int usb_stor_control_thread(void * __us)
US_DEBUGP("scsi command aborted\n");
}
/* in case an abort request was received after the command
* completed, we must use a separate test to see whether
* we need to signal that the abort has finished */
/* If an abort request was received we need to signal that
* the abort has finished. The proper test for this is
* sm_state == US_STATE_ABORTING, not srb->result == DID_ABORT,
* because an abort request might be received after all the
* USB processing was complete. */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING)
complete(&(us->notify));
......@@ -715,7 +717,6 @@ static int storage_probe(struct usb_interface *intf,
us->transport_name = "Bulk";
us->transport = usb_stor_Bulk_transport;
us->transport_reset = usb_stor_Bulk_reset;
us->max_lun = usb_stor_Bulk_max_lun(us);
break;
#ifdef CONFIG_USB_STORAGE_HP8200e
......@@ -842,6 +843,10 @@ static int storage_probe(struct usb_interface *intf,
if (usb_stor_allocate_urbs(us))
goto BadDevice;
/* For bulk-only devices, determine the max LUN value */
if (us->protocol == US_PR_BULK)
us->max_lun = usb_stor_Bulk_max_lun(us);
/*
* Since this is a new device, we need to generate a scsi
* host definition, and register with the higher SCSI layers
......
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