diff options
Diffstat (limited to 'drivers/usb/core/message.c')
-rw-r--r-- | drivers/usb/core/message.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index f9fed34bf7d8..530e854961ce 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -404,8 +404,6 @@ int usb_sg_init ( io->urbs [i]->complete = sg_complete; io->urbs [i]->context = io; - io->urbs [i]->status = -EINPROGRESS; - io->urbs [i]->actual_length = 0; /* * Some systems need to revert to PIO when DMA is temporarily @@ -499,7 +497,8 @@ void usb_sg_wait (struct usb_sg_request *io) /* queue the urbs. */ spin_lock_irq (&io->lock); - for (i = 0; i < entries && !io->status; i++) { + i = 0; + while (i < entries && !io->status) { int retval; io->urbs [i]->dev = io->dev; @@ -516,7 +515,6 @@ void usb_sg_wait (struct usb_sg_request *io) case -ENOMEM: io->urbs[i]->dev = NULL; retval = 0; - i--; yield (); break; @@ -527,6 +525,7 @@ void usb_sg_wait (struct usb_sg_request *io) * URBs are queued at once; N milliseconds? */ case 0: + ++i; cpu_relax (); break; @@ -1385,6 +1384,36 @@ struct device_type usb_if_device_type = { .uevent = usb_if_uevent, }; +static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev, + struct usb_host_config *config, + u8 inum) +{ + struct usb_interface_assoc_descriptor *retval = NULL; + struct usb_interface_assoc_descriptor *intf_assoc; + int first_intf; + int last_intf; + int i; + + for (i = 0; (i < USB_MAXIADS && config->intf_assoc[i]); i++) { + intf_assoc = config->intf_assoc[i]; + if (intf_assoc->bInterfaceCount == 0) + continue; + + first_intf = intf_assoc->bFirstInterface; + last_intf = first_intf + (intf_assoc->bInterfaceCount - 1); + if (inum >= first_intf && inum <= last_intf) { + if (!retval) + retval = intf_assoc; + else + dev_err(&dev->dev, "Interface #%d referenced" + " by multiple IADs\n", inum); + } + } + + return retval; +} + + /* * usb_set_configuration - Makes a particular device setting be current * @dev: the device whose configuration is being updated @@ -1531,6 +1560,7 @@ free_interfaces: intfc = cp->intf_cache[i]; intf->altsetting = intfc->altsetting; intf->num_altsetting = intfc->num_altsetting; + intf->intf_assoc = find_iad(dev, cp, i); kref_get(&intfc->ref); alt = usb_altnum_to_altsetting(intf, 0); |