Commit a98b28b1 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge bk://kernel.bkbits.net/acme/usb-2.5

into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents 832b5fae 25d1aa56
......@@ -59,3 +59,6 @@ obj-$(CONFIG_USB_TEST) += misc/
obj-$(CONFIG_USB_TIGL) += misc/
obj-$(CONFIG_USB_USS720) += misc/
obj-$(CONFIG_USB_NET2280) += gadget/
obj-$(CONFIG_USB_ZERO) += gadget/
obj-$(CONFIG_USB_ETH) += gadget/
......@@ -1199,12 +1199,18 @@ int usb_physical_reset_device(struct usb_device *dev)
if (port < 0)
return -ENOENT;
descriptor = kmalloc(sizeof *descriptor, GFP_NOIO);
if (!descriptor) {
return -ENOMEM;
}
down(&usb_address0_sem);
/* Send a reset to the device */
if (usb_hub_port_reset(parent, port, dev, HUB_SHORT_RESET_TIME)) {
usb_hub_port_disable(parent, port);
up(&usb_address0_sem);
kfree(descriptor);
return(-ENODEV);
}
......@@ -1214,6 +1220,7 @@ int usb_physical_reset_device(struct usb_device *dev)
err("USB device not accepting new address (error=%d)", ret);
usb_hub_port_disable(parent, port);
up(&usb_address0_sem);
kfree(descriptor);
return ret;
}
......@@ -1231,10 +1238,7 @@ int usb_physical_reset_device(struct usb_device *dev)
* If nothing changed, we reprogram the configuration and then
* the alternate settings.
*/
descriptor = kmalloc(sizeof *descriptor, GFP_NOIO);
if (!descriptor) {
return -ENOMEM;
}
ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, descriptor,
sizeof(*descriptor));
if (ret < 0) {
......@@ -1261,7 +1265,7 @@ int usb_physical_reset_device(struct usb_device *dev)
"(expected %Zi, got %i)",
dev->devpath,
sizeof(dev->descriptor), ret);
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
dev->devnum = -1;
return -EIO;
......
......@@ -22,65 +22,56 @@ static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATU
#define TRACE_STATE printk(KERN_DEBUG"hpusbscsi->state = %s at line %d\n", states[hpusbscsi->state], __LINE__)
/* global variables */
struct list_head hpusbscsi_devices;
//LIST_HEAD(hpusbscsi_devices);
/* USB related parts */
static Scsi_Host_Template hpusbscsi_scsi_host_template = {
.module = THIS_MODULE,
.name = "hpusbscsi",
.proc_name = "hpusbscsi",
.queuecommand = hpusbscsi_scsi_queuecommand,
.eh_abort_handler = hpusbscsi_scsi_abort,
.eh_host_reset_handler = hpusbscsi_scsi_host_reset,
.sg_tablesize = SG_ALL,
.can_queue = 1,
.this_id = -1,
.cmd_per_lun = 1,
.use_clustering = 1,
.emulated = 1,
};
static int
hpusbscsi_usb_probe (struct usb_interface *intf,
const struct usb_device_id *id)
hpusbscsi_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *altsetting = intf->altsetting;
struct hpusbscsi *new;
struct usb_device *dev = interface_to_usbdev (intf);
struct usb_host_interface *altsetting =
&(intf->altsetting[0]);
int error = -ENOMEM;
int i, result;
/* basic check */
if (altsetting->desc.bNumEndpoints != 3) {
printk (KERN_ERR "Wrong number of endpoints\n");
return -ENODEV;
}
/* descriptor allocation */
new =
(struct hpusbscsi *) kmalloc (sizeof (struct hpusbscsi),
GFP_KERNEL);
if (new == NULL)
new = kmalloc(sizeof(struct hpusbscsi), GFP_KERNEL);
if (!new)
return -ENOMEM;
DEBUG ("Allocated memory\n");
memset (new, 0, sizeof (struct hpusbscsi));
memset(new, 0, sizeof(struct hpusbscsi));
new->dataurb = usb_alloc_urb(0, GFP_KERNEL);
if (!new->dataurb) {
kfree (new);
return -ENOMEM;
}
if (!new->dataurb)
goto out_kfree;
new->controlurb = usb_alloc_urb(0, GFP_KERNEL);
if (!new->controlurb) {
usb_free_urb (new->dataurb);
kfree (new);
return -ENOMEM;
}
new->dev = dev;
init_waitqueue_head (&new->pending);
init_waitqueue_head (&new->deathrow);
INIT_LIST_HEAD (&new->lh);
if (!new->controlurb)
goto out_free_dataurb;
/* finding endpoints */
new->dev = dev;
init_waitqueue_head(&new->pending);
init_waitqueue_head(&new->deathrow);
error = -ENODEV;
for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
if (
(altsetting->endpoint[i].desc.
if ((altsetting->endpoint[i].desc.
bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK) {
USB_ENDPOINT_XFER_BULK) {
if (altsetting->endpoint[i].desc.
bEndpointAddress & USB_DIR_IN) {
new->ep_in =
......@@ -97,57 +88,71 @@ hpusbscsi_usb_probe (struct usb_interface *intf,
new->ep_int =
altsetting->endpoint[i].desc.
bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
new->interrupt_interval= altsetting->endpoint[i].desc.bInterval;
new->interrupt_interval= altsetting->endpoint[i].desc.
bInterval;
}
}
/* USB initialisation magic for the simple case */
result = usb_set_interface (dev, altsetting->desc.bInterfaceNumber, 0);
result = usb_set_interface(dev, altsetting->desc.bInterfaceNumber, 0);
switch (result) {
case 0: /* no error */
break;
default:
printk (KERN_ERR "unknown error %d from usb_set_interface\n",
printk(KERN_ERR "unknown error %d from usb_set_interface\n",
result);
goto err_out;
goto out_free_controlurb;
}
/* making a template for the scsi layer to fake detection of a scsi device */
/* build and submit an interrupt URB for status byte handling */
usb_fill_int_urb(new->controlurb, new->dev,
usb_rcvintpipe(new->dev, new->ep_int),
&new->scsi_state_byte, 1,
control_interrupt_callback,new,
new->interrupt_interval);
memcpy (&(new->ctempl), &hpusbscsi_scsi_host_template,
sizeof (hpusbscsi_scsi_host_template));
(struct hpusbscsi *) new->ctempl.proc_dir = new;
new->ctempl.module = THIS_MODULE;
if (usb_submit_urb(new->controlurb, GFP_KERNEL) < 0)
goto out_free_controlurb;
if (scsi_register_host(&new->ctempl))
goto err_out;
/* In host->hostdata we store a pointer to desc */
new->host = scsi_register(&hpusbscsi_scsi_host_template, sizeof(new));
if (!new->host)
goto out_unlink_controlurb;
new->host->hostdata[0] = (unsigned long)new;
scsi_add_host(new->host, &intf->dev);
new->sense_command[0] = REQUEST_SENSE;
new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH;
/* adding to list for module unload */
list_add (&hpusbscsi_devices, &new->lh);
usb_set_intfdata(intf, new);
return 0;
err_out:
usb_free_urb (new->controlurb);
usb_free_urb (new->dataurb);
kfree (new);
return -ENODEV;
out_unlink_controlurb:
usb_unlink_urb(new->controlurb);
out_free_controlurb:
usb_free_urb(new->controlurb);
out_free_dataurb:
usb_free_urb(new->dataurb);
out_kfree:
kfree(new);
return error;
}
static void
hpusbscsi_usb_disconnect (struct usb_interface *intf)
hpusbscsi_usb_disconnect(struct usb_interface *intf)
{
struct hpusbscsi *desc = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
if (desc)
usb_unlink_urb(desc->controlurb);
scsi_remove_host(desc->host);
usb_unlink_urb(desc->controlurb);
scsi_unregister(desc->host);
usb_free_urb(desc->controlurb);
usb_free_urb(desc->dataurb);
kfree(desc);
}
static struct usb_device_id hpusbscsi_usb_ids[] = {
......@@ -178,101 +183,21 @@ static struct usb_driver hpusbscsi_usb_driver = {
/* module initialisation */
int __init
static int __init
hpusbscsi_init (void)
{
int result;
INIT_LIST_HEAD (&hpusbscsi_devices);
DEBUG ("Driver loaded\n");
if ((result = usb_register (&hpusbscsi_usb_driver)) < 0) {
printk (KERN_ERR "hpusbscsi: driver registration failed\n");
return -1;
} else {
return 0;
}
return usb_register(&hpusbscsi_usb_driver);
}
void __exit
static void __exit
hpusbscsi_exit (void)
{
struct list_head *tmp;
struct list_head *old;
struct hpusbscsi * o;
for (tmp = hpusbscsi_devices.next; tmp != &hpusbscsi_devices;/*nothing */) {
old = tmp;
tmp = tmp->next;
o = (struct hpusbscsi *)old;
usb_unlink_urb(o->controlurb);
scsi_unregister_host(&o->ctempl);
usb_free_urb(o->controlurb);
usb_free_urb(o->dataurb);
kfree(old);
}
usb_deregister (&hpusbscsi_usb_driver);
usb_deregister(&hpusbscsi_usb_driver);
}
module_init (hpusbscsi_init);
module_exit (hpusbscsi_exit);
/* interface to the scsi layer */
static int
hpusbscsi_scsi_detect (struct SHT *sht)
{
/* Whole function stolen from usb-storage */
struct hpusbscsi *desc = (struct hpusbscsi *) sht->proc_dir;
/* What a hideous hack! */
char local_name[48];
/* set up the name of our subdirectory under /proc/scsi/ */
sprintf (local_name, "hpusbscsi-%d", desc->number);
sht->proc_name = kmalloc (strlen (local_name) + 1, GFP_KERNEL);
/* FIXME: where is this freed ? */
if (!sht->proc_name) {
return 0;
}
strcpy (sht->proc_name, local_name);
sht->proc_dir = NULL;
/* build and submit an interrupt URB for status byte handling */
usb_fill_int_urb(desc->controlurb,
desc->dev,
usb_rcvintpipe(desc->dev,desc->ep_int),
&desc->scsi_state_byte,
1,
control_interrupt_callback,
desc,
desc->interrupt_interval
);
if ( 0 > usb_submit_urb(desc->controlurb, GFP_KERNEL)) {
kfree(sht->proc_name);
return 0;
}
/* In host->hostdata we store a pointer to desc */
desc->host = scsi_register (sht, sizeof (desc));
if (desc->host == NULL) {
kfree (sht->proc_name);
usb_unlink_urb(desc->controlurb);
return 0;
}
desc->host->hostdata[0] = (unsigned long) desc;
return 1;
}
static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
{
struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]);
......
......@@ -13,7 +13,6 @@ typedef void (*scsi_callback)(Scsi_Cmnd *);
struct hpusbscsi
{
struct list_head lh;
struct usb_device *dev; /* NULL indicates unplugged device */
int ep_out;
int ep_in;
......@@ -36,7 +35,6 @@ struct hpusbscsi
int state;
int current_data_pipe;
Scsi_Host_Template ctempl;
u8 sense_command[SENSE_COMMAND_SIZE];
u8 scsi_state_byte;
};
......@@ -52,7 +50,6 @@ static const unsigned char scsi_command_direction[256/8] = {
#define DIRECTION_IS_IN(x) ((scsi_command_direction[x>>3] >> (x & 7)) & 1)
static int hpusbscsi_scsi_detect (struct SHT * sht);
static void simple_command_callback(struct urb *u, struct pt_regs *regs);
static void scatter_gather_callback(struct urb *u, struct pt_regs *regs);
static void simple_payload_callback (struct urb *u, struct pt_regs *regs);
......@@ -64,25 +61,6 @@ static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb);
static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb);
static void issue_request_sense (struct hpusbscsi *hpusbscsi);
static Scsi_Host_Template hpusbscsi_scsi_host_template = {
.name = "hpusbscsi",
.detect = hpusbscsi_scsi_detect,
// .release = hpusbscsi_scsi_release,
.queuecommand = hpusbscsi_scsi_queuecommand,
.eh_abort_handler = hpusbscsi_scsi_abort,
.eh_host_reset_handler = hpusbscsi_scsi_host_reset,
.sg_tablesize = SG_ALL,
.can_queue = 1,
.this_id = -1,
.cmd_per_lun = 1,
.present = 0,
.unchecked_isa_dma = FALSE,
.use_clustering = TRUE,
.emulated = TRUE
};
/* defines for internal driver state */
#define HP_STATE_FREE 0 /*ready for next request */
#define HP_STATE_BEGINNING 1 /*command being transferred */
......
......@@ -327,76 +327,6 @@ static inline void mts_urb_abort(struct mts_desc* desc) {
usb_unlink_urb( desc->urb );
}
static struct mts_desc * mts_list; /* list of active scanners */
struct semaphore mts_list_semaphore;
/* Internal list operations */
static
void mts_remove_nolock( struct mts_desc* to_remove )
{
MTS_DEBUG( "removing 0x%x from list\n",
(int)to_remove );
lock_kernel();
mts_urb_abort(to_remove);
MTS_DEBUG_GOT_HERE();
if ( to_remove != mts_list ) {
MTS_DEBUG_GOT_HERE();
if (to_remove->prev && to_remove->next)
to_remove->prev->next = to_remove->next;
} else {
MTS_DEBUG_GOT_HERE();
mts_list = to_remove->next;
if (mts_list) {
MTS_DEBUG_GOT_HERE();
mts_list->prev = 0;
}
}
if ( to_remove->next ) {
MTS_DEBUG_GOT_HERE();
to_remove->next->prev = to_remove->prev;
}
MTS_DEBUG_GOT_HERE();
scsi_unregister_host(&to_remove->ctempl);
unlock_kernel();
usb_free_urb(to_remove->urb);
kfree( to_remove );
}
static
void mts_add_nolock( struct mts_desc* to_add )
{
MTS_DEBUG( "adding 0x%x to list\n", (int)to_add );
to_add->prev = 0;
to_add->next = mts_list;
if ( mts_list ) {
mts_list->prev = to_add;
}
mts_list = to_add;
}
/* SCSI driver interface */
/* scsi related functions - dummies for now mostly */
static int mts_scsi_release(struct Scsi_Host *psh)
{
MTS_DEBUG_GOT_HERE();
return 0;
}
static int mts_scsi_abort (Scsi_Cmnd *srb)
{
struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
......@@ -419,54 +349,6 @@ static int mts_scsi_host_reset (Scsi_Cmnd *srb)
return 0; /* RANT why here 0 and not SUCCESS */
}
/* the core of the scsi part */
/* faking a detection - which can't fail :-) */
static int mts_scsi_detect (struct SHT * sht)
{
/* Whole function stolen from usb-storage */
struct mts_desc * desc = (struct mts_desc *)sht->proc_dir;
/* What a hideous hack! */
char local_name[48];
MTS_DEBUG_GOT_HERE();
/* set up the name of our subdirectory under /proc/scsi/ */
sprintf(local_name, "microtek-%d", desc->host_number);
sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL);
/* FIXME: where is this freed ? */
if (!sht->proc_name) {
MTS_ERROR( "unable to allocate memory for proc interface!!\n" );
return 0;
}
strcpy(sht->proc_name, local_name);
sht->proc_dir = NULL;
/* In host->hostdata we store a pointer to desc */
desc->host = scsi_register(sht, sizeof(desc));
if (desc->host == NULL) {
MTS_ERROR("Cannot register due to low memory");
kfree(sht->proc_name);
return 0;
}
desc->host->hostdata[0] = (unsigned long)desc;
/* FIXME: what if sizeof(void*) != sizeof(unsigned long)? */
return 1;
}
/* Main entrypoint: SCSI commands are dispatched to here */
static
int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback );
......@@ -744,52 +626,22 @@ int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
out:
return err;
}
/*
* this defines our 'host'
*/
/* NOTE: This is taken from usb-storage, should be right. */
static Scsi_Host_Template mts_scsi_host_template = {
.name = "microtekX6",
.detect = mts_scsi_detect,
.release = mts_scsi_release,
.queuecommand = mts_scsi_queuecommand,
.eh_abort_handler = mts_scsi_abort,
.eh_host_reset_handler =mts_scsi_host_reset,
.module = THIS_MODULE,
.name = "microtekX6",
.proc_name = "microtekX6",
.queuecommand = mts_scsi_queuecommand,
.eh_abort_handler = mts_scsi_abort,
.eh_host_reset_handler = mts_scsi_host_reset,
.sg_tablesize = SG_ALL,
.can_queue = 1,
.this_id = -1,
.cmd_per_lun = 1,
.present = 0,
.unchecked_isa_dma = FALSE,
.use_clustering = TRUE,
.emulated = TRUE
.use_clustering = 1,
.emulated = 1,
};
/* USB layer driver interface implementation */
static void mts_usb_disconnect (struct usb_interface *intf)
{
struct mts_desc* to_remove = usb_get_intfdata(intf);
MTS_DEBUG_GOT_HERE();
usb_set_intfdata(intf, NULL);
if (to_remove) {
/* leave the list - lock it */
down(&mts_list_semaphore);
mts_remove_nolock(to_remove);
up(&mts_list_semaphore);
}
}
struct vendor_product
{
char* name;
......@@ -837,8 +689,8 @@ static struct usb_device_id mts_usb_ids [] =
MODULE_DEVICE_TABLE (usb, mts_usb_ids);
static int mts_usb_probe (struct usb_interface *intf,
const struct usb_device_id *id)
static int mts_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
int i;
int result;
......@@ -930,39 +782,23 @@ static int mts_usb_probe (struct usb_interface *intf,
}
/* allocating a new descriptor */
new_desc = (struct mts_desc *)kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
if (new_desc == NULL)
{
MTS_ERROR("couldn't allocate scanner desc, bailing out!\n");
return -ENOMEM;
}
new_desc = kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
if (!new_desc)
goto out;
memset( new_desc, 0, sizeof(*new_desc) );
memset(new_desc, 0, sizeof(*new_desc));
new_desc->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!new_desc->urb) {
kfree(new_desc);
return -ENOMEM;
}
/* initialising that descriptor */
new_desc->usb_dev = dev;
if (!new_desc->urb)
goto out_kfree;
new_desc->usb_dev = dev;
init_MUTEX(&new_desc->lock);
if(mts_list){
new_desc->host_number = mts_list->host_number+1;
} else {
new_desc->host_number = 0;
}
/* endpoints */
new_desc->ep_out = ep_out;
new_desc->ep_response = ep_in_set[0];
new_desc->ep_image = ep_in_set[1];
if ( new_desc->ep_out != MTS_EP_OUT )
MTS_WARNING( "will this work? Command EP is not usually %d\n",
(int)new_desc->ep_out );
......@@ -975,87 +811,48 @@ static int mts_usb_probe (struct usb_interface *intf,
MTS_WARNING( "will this work? Image data EP is not usually %d\n",
(int)new_desc->ep_image );
new_desc->host = scsi_register(&mts_scsi_host_template,
sizeof(new_desc));
if (!new_desc->host)
goto out_free_urb;
/* Initialize the host template based on the default one */
memcpy(&(new_desc->ctempl), &mts_scsi_host_template, sizeof(mts_scsi_host_template));
/* HACK from usb-storage - this is needed for scsi detection */
(struct mts_desc *)new_desc->ctempl.proc_dir = new_desc; /* FIXME */
MTS_DEBUG("registering SCSI module\n");
new_desc->ctempl.module = THIS_MODULE;
result = scsi_register_host(&new_desc->ctempl);
/* Will get hit back in microtek_detect by this func */
if ( result )
{
MTS_ERROR( "error %d from scsi_register_host! Help!\n",
(int)result );
/* FIXME: need more cleanup? */
kfree( new_desc );
return -ENOMEM;
}
MTS_DEBUG_GOT_HERE();
/* FIXME: the bomb is armed, must the host be registered under lock ? */
/* join the list - lock it */
down(&mts_list_semaphore);
mts_add_nolock( new_desc );
up(&mts_list_semaphore);
MTS_DEBUG("completed probe and exiting happily\n");
new_desc->host->hostdata[0] = (unsigned long)new_desc;
scsi_add_host(new_desc->host, NULL);
usb_set_intfdata(intf, new_desc);
return 0;
}
out_free_urb:
usb_free_urb(new_desc->urb);
out_kfree:
kfree(new_desc);
out:
return -ENOMEM;
}
/* get us noticed by the rest of the kernel */
int __init microtek_drv_init(void)
static void mts_usb_disconnect (struct usb_interface *intf)
{
int result;
MTS_DEBUG_GOT_HERE();
init_MUTEX(&mts_list_semaphore);
struct mts_desc *desc = usb_get_intfdata(intf);
if ((result = usb_register(&mts_usb_driver)) < 0) {
MTS_DEBUG("usb_register returned %d\n", result );
return -1;
} else {
MTS_DEBUG("driver registered.\n");
}
usb_set_intfdata(intf, NULL);
info(DRIVER_VERSION ":" DRIVER_DESC);
scsi_remove_host(desc->host);
usb_unlink_urb(desc->urb);
scsi_unregister(desc->host);
return 0;
usb_free_urb(desc->urb);
kfree(desc);
}
void __exit microtek_drv_exit(void)
{
struct mts_desc* next;
MTS_DEBUG_GOT_HERE();
static int __init microtek_drv_init(void)
{
return usb_register(&mts_usb_driver);
}
static void __exit microtek_drv_exit(void)
{
usb_deregister(&mts_usb_driver);
down(&mts_list_semaphore);
while (mts_list) {
/* keep track of where the next one is */
next = mts_list->next;
mts_remove_nolock( mts_list );
/* advance the list pointer */
mts_list = next;
}
up(&mts_list_semaphore);
}
module_init(microtek_drv_init);
......
......@@ -38,9 +38,6 @@ struct mts_desc {
u8 ep_image;
struct Scsi_Host * host;
Scsi_Host_Template ctempl;
int host_number;
struct semaphore lock;
struct urb *urb;
......
......@@ -171,9 +171,11 @@ static int usb_storage_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
/* This is always called with scsi_lock(srb->host) held */
static int usb_storage_command_abort( Scsi_Cmnd *srb )
{
struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
struct Scsi_Host *host = srb->device->host;
struct us_data *us = (struct us_data *) host->hostdata[0];
int state = atomic_read(&us->sm_state);
US_DEBUGP("command_abort() called\n");
US_DEBUGP("%s called\n", __FUNCTION__);
/* Is this command still active? */
if (us->srb != srb) {
......@@ -181,7 +183,31 @@ static int usb_storage_command_abort( Scsi_Cmnd *srb )
return FAILED;
}
return usb_stor_abort_transport(us);
/* Normally the current state is RUNNING. If the control thread
* hasn't even started processing this command, the state will be
* IDLE. Anything else is a bug. */
if (state != US_STATE_RUNNING && state != US_STATE_IDLE) {
printk(KERN_ERR USB_STORAGE "Error in %s: "
"invalid state %d\n", __FUNCTION__, state);
return FAILED;
}
/* Set state to ABORTING, set the ABORTING bit, and release the lock */
atomic_set(&us->sm_state, US_STATE_ABORTING);
set_bit(US_FLIDX_ABORTING, &us->flags);
scsi_unlock(host);
/* If the state was RUNNING, stop an ongoing USB transfer */
if (state == US_STATE_RUNNING)
usb_stor_stop_transport(us);
/* Wait for the aborted command to finish */
wait_for_completion(&us->notify);
/* Reacquire the lock and allow USB transfers to resume */
scsi_lock(host);
clear_bit(US_FLIDX_ABORTING, &us->flags);
return SUCCESS;
}
/* This invokes the transport reset mechanism to reset the state of the
......
......@@ -69,32 +69,35 @@
* as those occurring during device-specific initialization, must be handled
* by a separate code path.)
*
* The abort function first sets the machine state, then atomically
* tests-and-clears the CAN_CANCEL bit in us->flags to see if the current_urb
* needs to be aborted.
* The abort function (usb_storage_command_abort() in scsiglue.c) first
* sets the machine state and the ABORTING bit in us->flags to prevent
* new URBs from being submitted. It then calls usb_stor_stop_transport()
* below, which atomically tests-and-clears the URB_ACTIVE bit in us->flags
* to see if the current_urb needs to be stopped. Likewise, the SG_ACTIVE
* bit is tested to see if the current_sg scatter-gather request needs to be
* stopped.
*
* The submit function first verifies that the submission completed without
* errors, and only then sets the CAN_CANCEL bit. This prevents the abort
* function from trying to cancel the URB while the submit call is underway.
* Next, the submit function must test the state to see if we got aborted
* before the submission or before setting the CAN_CANCEL bit. If so, it's
* essential to abort the URB if it hasn't been cancelled already (i.e.,
* if the CAN_CANCEL bit is still set). Either way, the function must then
* wait for the URB to finish. Note that because the URB_ASYNC_UNLINK flag
* is set, the URB can still be in progress even after a call to
* usb_unlink_urb() returns.
* When a disconnect occurs, the DISCONNECTING bit in us->flags is set to
* prevent new URBs from being submitted, and usb_stor_stop_transport() is
* called to stop any ongoing requests.
*
* (It's also permissible, but not necessary, to test the state -before-
* submitting the URB. Doing so would prevent an unnecessary submission if
* the transaction had already been aborted, but this is very unlikely to
* happen, because the abort would have to have been requested during actual
* kernel processing rather than during an I/O delay.)
* The submit function first verifies that the submitting is allowed
* (neither ABORTING nor DISCONNECTING bits are set) and that the submit
* completes without errors, and only then sets the URB_ACTIVE bit. This
* prevents the stop_transport() function from trying to cancel the URB
* while the submit call is underway. Next, the submit function must test
* the flags to see if an abort or disconnect occurred during the submission
* or before the URB_ACTIVE bit was set. If so, it's essential to cancel
* the URB if it hasn't been cancelled already (i.e., if the URB_ACTIVE bit
* is still set). Either way, the function must then wait for the URB to
* finish. Note that because the URB_ASYNC_UNLINK flag is set, the URB can
* still be in progress even after a call to usb_unlink_urb() returns.
*
* The idea is that (1) once the state is changed to ABORTING, either the
* aborting function or the submitting function is guaranteed to call
* usb_unlink_urb() for an active URB, and (2) test_and_clear_bit() prevents
* usb_unlink_urb() from being called more than once or from being called
* during usb_submit_urb().
* The idea is that (1) once the ABORTING or DISCONNECTING bit is set,
* either the stop_transport() function or the submitting function
* is guaranteed to call usb_unlink_urb() for an active URB,
* and (2) test_and_clear_bit() prevents usb_unlink_urb() from being
* called more than once or from being called during usb_submit_urb().
*/
/* This is the completion handler which will wake us up when an URB
......@@ -118,6 +121,10 @@ static int usb_stor_msg_common(struct us_data *us)
struct completion urb_done;
int status;
/* don't submit URBS during abort/disconnect processing */
if (us->flags & DONT_SUBMIT)
return -ECONNRESET;
/* set up data structures for the wakeup system */
init_completion(&urb_done);
......@@ -137,13 +144,13 @@ static int usb_stor_msg_common(struct us_data *us)
/* since the URB has been submitted successfully, it's now okay
* to cancel it */
set_bit(US_FLIDX_CAN_CANCEL, &us->flags);
set_bit(US_FLIDX_URB_ACTIVE, &us->flags);
/* has the current command been aborted? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
/* did an abort/disconnect occur during the submission? */
if (us->flags & DONT_SUBMIT) {
/* cancel the URB, if it hasn't been cancelled already */
if (test_and_clear_bit(US_FLIDX_CAN_CANCEL, &us->flags)) {
if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {
US_DEBUGP("-- cancelling URB\n");
usb_unlink_urb(us->current_urb);
}
......@@ -151,7 +158,7 @@ static int usb_stor_msg_common(struct us_data *us)
/* wait for the completion of the URB */
wait_for_completion(&urb_done);
clear_bit(US_FLIDX_CAN_CANCEL, &us->flags);
clear_bit(US_FLIDX_URB_ACTIVE, &us->flags);
/* return the URB status */
return us->current_urb->status;
......@@ -185,53 +192,6 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
return status;
}
/* This is our function to emulate usb_bulk_msg() with enough control
* to make aborts/resets/timeouts work
*/
int usb_stor_bulk_msg(struct us_data *us, void *data, unsigned int pipe,
unsigned int len, unsigned int *act_len)
{
int status;
/* fill and submit the URB */
usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, data, len,
usb_stor_blocking_completion, NULL);
status = usb_stor_msg_common(us);
/* store the actual length of the data transferred */
*act_len = us->current_urb->actual_length;
return status;
}
/* This is our function to submit interrupt URBs with enough control
* to make aborts/resets/timeouts work
*
* This routine always uses us->recv_intr_pipe as the pipe and
* us->ep_bInterval as the interrupt interval.
*/
int usb_stor_interrupt_msg(struct us_data *us, void *data,
unsigned int len, unsigned int *act_len)
{
unsigned int pipe = us->recv_intr_pipe;
unsigned int maxp;
int status;
/* calculate the max packet size */
maxp = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe));
if (maxp > len)
maxp = len;
/* fill and submit the URB */
usb_fill_int_urb(us->current_urb, us->pusb_dev, pipe, data,
maxp, usb_stor_blocking_completion, NULL,
us->ep_bInterval);
status = usb_stor_msg_common(us);
/* store the actual length of the data transferred */
*act_len = us->current_urb->actual_length;
return status;
}
/* This is a version of usb_clear_halt() that doesn't read the status from
* the device -- this is because some devices crash their internal firmware
* when the status is requested after a halt.
......@@ -275,12 +235,12 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
* Interpret the results of a URB transfer
*
* This function prints appropriate debugging messages, clears halts on
* bulk endpoints, and translates the status to the corresponding
* non-control endpoints, and translates the status to the corresponding
* USB_STOR_XFER_xxx return code.
*/
static int interpret_urb_result(struct us_data *us, unsigned int pipe,
unsigned int length, int result, unsigned int partial) {
unsigned int length, int result, unsigned int partial)
{
US_DEBUGP("Status code %d; transferred %u/%u\n",
result, partial, length);
switch (result) {
......@@ -333,95 +293,109 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe,
}
/*
* Transfer one control message
*
* This function does basically the same thing as usb_stor_control_msg()
* above, except that return codes are USB_STOR_XFER_xxx rather than the
* urb status or transfer length.
* Transfer one control message, without timeouts, but allowing early
* termination. Return codes are USB_STOR_XFER_xxx.
*/
int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size) {
void *data, u16 size)
{
int result;
unsigned int partial = 0;
US_DEBUGP("usb_stor_ctrl_transfer(): rq=%02x rqtype=%02x "
"value=%04x index=%02x len=%u\n",
request, requesttype, value, index, size);
result = usb_stor_control_msg(us, pipe, request, requesttype,
value, index, data, size);
US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
__FUNCTION__, request, requesttype,
value, index, size);
if (result > 0) { /* Separate out the amount transferred */
partial = result;
result = 0;
}
return interpret_urb_result(us, pipe, size, result, partial);
/* fill in the devrequest structure */
us->dr->bRequestType = requesttype;
us->dr->bRequest = request;
us->dr->wValue = cpu_to_le16(value);
us->dr->wIndex = cpu_to_le16(index);
us->dr->wLength = cpu_to_le16(size);
/* fill and submit the URB */
usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe,
(unsigned char*) us->dr, data, size,
usb_stor_blocking_completion, NULL);
result = usb_stor_msg_common(us);
return interpret_urb_result(us, pipe, size, result,
us->current_urb->actual_length);
}
/*
* Receive one buffer via interrupt transfer
* Receive one interrupt buffer, without timeouts, but allowing early
* termination. Return codes are USB_STOR_XFER_xxx.
*
* This function does basically the same thing as usb_stor_interrupt_msg()
* above, except that return codes are USB_STOR_XFER_xxx rather than the
* urb status.
* This routine always uses us->recv_intr_pipe as the pipe and
* us->ep_bInterval as the interrupt interval.
*/
int usb_stor_intr_transfer(struct us_data *us, void *buf,
unsigned int length, unsigned int *act_len)
int usb_stor_intr_transfer(struct us_data *us, void *buf, unsigned int length)
{
int result;
unsigned int partial;
unsigned int pipe = us->recv_intr_pipe;
unsigned int maxp;
/* transfer the data */
US_DEBUGP("usb_stor_intr_transfer(): xfer %u bytes\n", length);
result = usb_stor_interrupt_msg(us, buf, length, &partial);
if (act_len)
*act_len = partial;
US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
/* calculate the max packet size */
maxp = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe));
if (maxp > length)
maxp = length;
/* fill and submit the URB */
usb_fill_int_urb(us->current_urb, us->pusb_dev, pipe, buf,
maxp, usb_stor_blocking_completion, NULL,
us->ep_bInterval);
result = usb_stor_msg_common(us);
return interpret_urb_result(us, us->recv_intr_pipe,
length, result, partial);
return interpret_urb_result(us, pipe, length, result,
us->current_urb->actual_length);
}
/*
* Transfer one buffer via bulk transfer
*
* This function does basically the same thing as usb_stor_bulk_msg()
* above, except that:
*
* 1. If the bulk pipe stalls during the transfer, the halt is
* automatically cleared;
* 2. Return codes are USB_STOR_XFER_xxx rather than the
* urb status or transfer length.
* Transfer one buffer via bulk pipe, without timeouts, but allowing early
* termination. Return codes are USB_STOR_XFER_xxx. If the bulk pipe
* stalls during the transfer, the halt is automatically cleared.
*/
int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
void *buf, unsigned int length, unsigned int *act_len)
{
int result;
unsigned int partial;
/* transfer the data */
US_DEBUGP("usb_stor_bulk_transfer_buf(): xfer %u bytes\n", length);
result = usb_stor_bulk_msg(us, buf, pipe, length, &partial);
US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
/* fill and submit the URB */
usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length,
usb_stor_blocking_completion, NULL);
result = usb_stor_msg_common(us);
/* store the actual length of the data transferred */
if (act_len)
*act_len = partial;
return interpret_urb_result(us, pipe, length, result, partial);
*act_len = us->current_urb->actual_length;
return interpret_urb_result(us, pipe, length, result,
us->current_urb->actual_length);
}
/*
* Transfer a scatter-gather list via bulk transfer
*
* This function does basically the same thing as usb_stor_bulk_transfer_buf()
* above, but it uses the usbcore scatter-gather primitives
* above, but it uses the usbcore scatter-gather library.
*/
int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
struct scatterlist *sg, int num_sg, unsigned int length,
unsigned int *act_len)
{
int result;
unsigned int partial;
/* don't submit s-g requests during abort/disconnect processing */
if (us->flags & DONT_SUBMIT)
return USB_STOR_XFER_ERROR;
/* initialize the scatter-gather request block */
US_DEBUGP("usb_stor_bulk_transfer_sglist(): xfer %u bytes, "
"%d entries\n", length, num_sg);
US_DEBUGP("%s: xfer %u bytes, %d entries\n", __FUNCTION__,
length, num_sg);
result = usb_sg_init(us->current_sg, us->pusb_dev, pipe, 0,
sg, num_sg, length, SLAB_NOIO);
if (result) {
......@@ -431,13 +405,13 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
/* since the block has been initialized successfully, it's now
* okay to cancel it */
set_bit(US_FLIDX_CANCEL_SG, &us->flags);
set_bit(US_FLIDX_SG_ACTIVE, &us->flags);
/* has the current command been aborted? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
/* did an abort/disconnect occur during the submission? */
if (us->flags & DONT_SUBMIT) {
/* cancel the request, if it hasn't been cancelled already */
if (test_and_clear_bit(US_FLIDX_CANCEL_SG, &us->flags)) {
if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {
US_DEBUGP("-- cancelling sg request\n");
usb_sg_cancel(us->current_sg);
}
......@@ -445,13 +419,13 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
/* wait for the completion of the transfer */
usb_sg_wait(us->current_sg);
clear_bit(US_FLIDX_CANCEL_SG, &us->flags);
clear_bit(US_FLIDX_SG_ACTIVE, &us->flags);
result = us->current_sg->status;
partial = us->current_sg->bytes;
if (act_len)
*act_len = partial;
return interpret_urb_result(us, pipe, length, result, partial);
*act_len = us->current_sg->bytes;
return interpret_urb_result(us, pipe, length, result,
us->current_sg->bytes);
}
/*
......@@ -693,56 +667,32 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
Handle_Abort:
srb->result = DID_ABORT << 16;
if (us->protocol == US_PR_BULK) {
/* permit the reset transfer to take place */
clear_bit(US_FLIDX_ABORTING, &us->flags);
us->transport_reset(us);
}
}
/* Abort the currently running scsi command or device reset.
* This must be called with scsi_lock(us->srb->host) held */
int usb_stor_abort_transport(struct us_data *us)
/* Stop the current URB transfer */
void usb_stor_stop_transport(struct us_data *us)
{
struct Scsi_Host *host;
int state = atomic_read(&us->sm_state);
US_DEBUGP("usb_stor_abort_transport called\n");
/* Normally the current state is RUNNING. If the control thread
* hasn't even started processing this command, the state will be
* IDLE. Anything else is a bug. */
if (state != US_STATE_RUNNING && state != US_STATE_IDLE) {
printk(KERN_ERR USB_STORAGE "Error in %s: "
"invalid state %d\n", __FUNCTION__, state);
return FAILED;
}
/* set state to abort and release the lock */
atomic_set(&us->sm_state, US_STATE_ABORTING);
host = us->srb->device->host;
scsi_unlock(host);
US_DEBUGP("%s called\n", __FUNCTION__);
/* If the state machine is blocked waiting for an URB,
* let's wake it up */
/* If we have an URB pending, cancel it. The test_and_clear_bit()
* call guarantees that if a URB has just been submitted, it
* won't be cancelled more than once. */
if (test_and_clear_bit(US_FLIDX_CAN_CANCEL, &us->flags)) {
* let's wake it up. The test_and_clear_bit() call
* guarantees that if a URB has just been submitted,
* it won't be cancelled more than once. */
if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {
US_DEBUGP("-- cancelling URB\n");
usb_unlink_urb(us->current_urb);
}
/* If we are waiting for a scatter-gather operation, cancel it. */
if (test_and_clear_bit(US_FLIDX_CANCEL_SG, &us->flags)) {
if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {
US_DEBUGP("-- cancelling sg request\n");
usb_sg_cancel(us->current_sg);
}
/* Wait for the aborted command to finish */
wait_for_completion(&us->notify);
/* Reacquire the lock: note that us->srb is now NULL */
scsi_lock(host);
return SUCCESS;
}
/*
......@@ -788,8 +738,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
}
/* STATUS STAGE */
result = usb_stor_intr_transfer(us, us->irqdata,
sizeof(us->irqdata), NULL);
result = usb_stor_intr_transfer(us, us->irqdata, sizeof(us->irqdata));
US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n",
us->irqdata[0], us->irqdata[1]);
if (result != USB_STOR_XFER_GOOD)
......
......@@ -156,22 +156,18 @@ extern int usb_stor_Bulk_max_lun(struct us_data*);
extern int usb_stor_Bulk_reset(struct us_data*);
extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
extern int usb_stor_abort_transport(struct us_data*);
extern void usb_stor_stop_transport(struct us_data*);
extern int usb_stor_bulk_msg(struct us_data *us, void *data,
unsigned int pipe, unsigned int len, unsigned int *act_len);
extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size);
extern int usb_stor_interrupt_msg(struct us_data *us, void *data,
unsigned int len, unsigned int *act_len);
extern int usb_stor_clear_halt(struct us_data*, unsigned int pipe);
extern int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size);
extern int usb_stor_intr_transfer(struct us_data *us, void *buf,
unsigned int length, unsigned int *act_len);
unsigned int length);
extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
void *buf, unsigned int length, unsigned int *act_len);
extern int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
......
......@@ -314,33 +314,18 @@ UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200,
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
*/
UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
"ASAHI PENTAX",
"PENTAX OPTIO 430",
"Pentax",
"Optio 2/3/400",
US_SC_8070, US_PR_CBI, NULL,
US_FL_FIX_INQUIRY ),
/* This Pentax still camera is not conformant
* to the USB storage specification: -
* - It does not like the INQUIRY command. So we must handle this command
* of the SCSI layer ourselves.
* Tested on Rev. 10.00 (0x1000)
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
*/
UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
"ASAHI PENTAX",
"PENTAX OPTIO 430",
/* Submitted by Per Winkvist <per.winkvist@uk.com> */
UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
"Pentax",
"Optio S",
US_SC_8070, US_PR_CBI, NULL,
US_FL_FIX_INQUIRY ),
/* Pentax Optio S digital camera
* submitted by Stefan M. Brandl <smb@smbnet.de>
*/
UNUSUAL_DEV( 0x0a17, 0x0006, 0x0000, 0xffff,
"Pentax",
"Optio S",
US_SC_8070, US_PR_CB, NULL,
US_FL_MODE_XLATE|US_FL_FIX_INQUIRY),
#ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110,
"In-System",
......@@ -639,26 +624,6 @@ UNUSUAL_DEV( 0x1065, 0x2136, 0x0000, 0x0001,
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_MODE_XLATE | US_FL_START_STOP | US_FL_FIX_INQUIRY ),
/* This Pentax still camera is not conformant
* to the USB storage specification: -
* - It does not like the INQUIRY command. So we must handle this command
* of the SCSI layer ourselves.
* Tested on Rev. 10.00 (0x1000)
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
*/
UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
"Pentax",
"Optio 2/3/400",
US_SC_8070, US_PR_CBI, NULL,
US_FL_FIX_INQUIRY ),
/* Submitted by Per Winkvist <per.winkvist@uk.com> */
UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
"Pentax",
"Optio S",
US_SC_8070, US_PR_CBI, NULL,
US_FL_FIX_INQUIRY ),
/* Submitted by Brian Hall <brihall@pcisys.net>
* Needed for START_STOP flag */
UNUSUAL_DEV( 0x0c76, 0x0003, 0x0100, 0x0100,
......
......@@ -887,11 +887,8 @@ static int storage_probe(struct usb_interface *intf,
/* set the hostdata to prepare for scanning */
us->host->hostdata[0] = (unsigned long)us;
/* associate this host with our interface */
scsi_set_device(us->host, &intf->dev);
/* now add the host */
result = scsi_add_host(us->host, NULL);
result = scsi_add_host(us->host, &intf->dev);
if (result) {
printk(KERN_WARNING USB_STORAGE
"Unable to add the scsi host\n");
......@@ -942,16 +939,13 @@ static void storage_disconnect(struct usb_interface *intf)
sdev->online = 0;
scsi_unlock(us->host);
/* prevent new USB transfers and stop the current command */
set_bit(US_FLIDX_DISCONNECTING, &us->flags);
usb_stor_stop_transport(us);
/* lock device access -- no need to unlock, as we're going away */
down(&(us->dev_semaphore));
/* Complete all pending commands with * cmd->result = DID_ERROR << 16.
* Since we only queue one command at a time, this is pretty easy. */
if (us->srb) {
us->srb->result = DID_ERROR << 16;
us->srb->scsi_done(us->srb);
}
/* TODO: somehow, wait for the device to
* be 'idle' (tasklet completion) */
......
......@@ -67,7 +67,7 @@ struct us_unusual_dev {
unsigned int flags;
};
/* Flag definitions */
/* Flag definitions: these entries are static */
#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */
#define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 commands for
Win/MacOS compatibility */
......@@ -77,8 +77,13 @@ struct us_unusual_dev {
#define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */
#define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */
#define US_FLIDX_CAN_CANCEL 18 /* 0x00040000 okay to cancel current_urb? */
#define US_FLIDX_CANCEL_SG 19 /* 0x00080000 okay to cancel current_sg? */
/* Dynamic flag definitions: used in set_bit() etc. */
#define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */
#define US_FLIDX_SG_ACTIVE 19 /* 0x00080000 current_sg is in use */
#define US_FLIDX_ABORTING 20 /* 0x00100000 abort is in progress */
#define US_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect in progress */
#define DONT_SUBMIT ((1UL << US_FLIDX_ABORTING) || \
(1UL << US_FLIDX_DISCONNECTING))
/* processing state machine states */
......
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