[PATCH 2/11] drivers/watchdog: Eliminate a NULL pointer dereference
[safe/jmp/linux-2.6] / drivers / usb / core / message.c
index 0d61864..a73e08f 100644 (file)
 #include <linux/mm.h>
 #include <linux/timer.h>
 #include <linux/ctype.h>
+#include <linux/nls.h>
 #include <linux/device.h>
+#include <linux/scatterlist.h>
 #include <linux/usb/quirks.h>
+#include <linux/usb/hcd.h>     /* for usbcore internals */
 #include <asm/byteorder.h>
-#include <asm/scatterlist.h>
 
-#include "hcd.h"       /* for usbcore internals */
 #include "usb.h"
 
+static void cancel_async_set_config(struct usb_device *udev);
+
 struct api_context {
        struct completion       done;
        int                     status;
@@ -39,7 +42,7 @@ static void usb_api_blocking_completion(struct urb *urb)
  * own interruptible routines.
  */
 static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
-{ 
+{
        struct api_context ctx;
        unsigned long expire;
        int retval;
@@ -57,10 +60,10 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
                retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status);
 
                dev_dbg(&urb->dev->dev,
-                       "%s timed out on ep%d%s len=%d/%d\n",
+                       "%s timed out on ep%d%s len=%u/%u\n",
                        current->comm,
-                       usb_pipeendpoint(urb->pipe),
-                       usb_pipein(urb->pipe) ? "in" : "out",
+                       usb_endpoint_num(&urb->ep->desc),
+                       usb_urb_dir_in(urb) ? "in" : "out",
                        urb->actual_length,
                        urb->transfer_buffer_length);
        } else
@@ -74,9 +77,9 @@ out:
 }
 
 /*-------------------------------------------------------------------*/
-// returns status (negative) or length (positive)
+/* returns status (negative) or length (positive) */
 static int usb_internal_control_msg(struct usb_device *usb_dev,
-                                   unsigned int pipe, 
+                                   unsigned int pipe,
                                    struct usb_ctrlrequest *cmd,
                                    void *data, int len, int timeout)
 {
@@ -87,7 +90,7 @@ static int usb_internal_control_msg(struct usb_device *usb_dev,
        urb = usb_alloc_urb(0, GFP_NOIO);
        if (!urb)
                return -ENOMEM;
-  
+
        usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,
                             len, usb_api_blocking_completion, NULL);
 
@@ -99,47 +102,51 @@ static int usb_internal_control_msg(struct usb_device *usb_dev,
 }
 
 /**
- *     usb_control_msg - Builds a control urb, sends it off and waits for completion
- *     @dev: pointer to the usb device to send the message to
- *     @pipe: endpoint "pipe" to send the message to
- *     @request: USB message request value
- *     @requesttype: USB message request type value
- *     @value: USB message value
- *     @index: USB message index value
- *     @data: pointer to the data to send
- *     @size: length in bytes of the data to send
- *     @timeout: time in msecs to wait for the message to complete before
- *             timing out (if 0 the wait is forever)
- *     Context: !in_interrupt ()
- *
- *     This function sends a simple control message to a specified endpoint
- *     and waits for the message to complete, or timeout.
- *     
- *     If successful, it returns the number of bytes transferred, otherwise a negative error number.
- *
- *     Don't use this function from within an interrupt context, like a
- *     bottom half handler.  If you need an asynchronous message, or need to send
- *     a message from within interrupt context, use usb_submit_urb()
- *      If a thread in your driver uses this call, make sure your disconnect()
- *      method can wait for it to complete.  Since you don't have a handle on
- *      the URB used, you can't cancel the request.
+ * usb_control_msg - Builds a control urb, sends it off and waits for completion
+ * @dev: pointer to the usb device to send the message to
+ * @pipe: endpoint "pipe" to send the message to
+ * @request: USB message request value
+ * @requesttype: USB message request type value
+ * @value: USB message value
+ * @index: USB message index value
+ * @data: pointer to the data to send
+ * @size: length in bytes of the data to send
+ * @timeout: time in msecs to wait for the message to complete before timing
+ *     out (if 0 the wait is forever)
+ *
+ * Context: !in_interrupt ()
+ *
+ * This function sends a simple control message to a specified endpoint and
+ * waits for the message to complete, or timeout.
+ *
+ * If successful, it returns the number of bytes transferred, otherwise a
+ * negative error number.
+ *
+ * Don't use this function from within an interrupt context, like a bottom half
+ * handler.  If you need an asynchronous message, or need to send a message
+ * from within interrupt context, use usb_submit_urb().
+ * If a thread in your driver uses this call, make sure your disconnect()
+ * method can wait for it to complete.  Since you don't have a handle on the
+ * URB used, you can't cancel the request.
  */
-int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
-                        __u16 value, __u16 index, void *data, __u16 size, int timeout)
+int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
+                   __u8 requesttype, __u16 value, __u16 index, void *data,
+                   __u16 size, int timeout)
 {
-       struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
+       struct usb_ctrlrequest *dr;
        int ret;
-       
+
+       dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
        if (!dr)
                return -ENOMEM;
 
-       dr->bRequestType= requesttype;
+       dr->bRequestType = requesttype;
        dr->bRequest = request;
-       dr->wValue = cpu_to_le16p(&value);
-       dr->wIndex = cpu_to_le16p(&index);
-       dr->wLength = cpu_to_le16p(&size);
+       dr->wValue = cpu_to_le16(value);
+       dr->wIndex = cpu_to_le16(index);
+       dr->wLength = cpu_to_le16(size);
 
-       //dbg("usb_control_msg");       
+       /* dbg("usb_control_msg"); */
 
        ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
 
@@ -147,7 +154,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
 
        return ret;
 }
-
+EXPORT_SYMBOL_GPL(usb_control_msg);
 
 /**
  * usb_interrupt_msg - Builds an interrupt urb, sends it off and waits for completion
@@ -155,9 +162,11 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
  * @pipe: endpoint "pipe" to send the message to
  * @data: pointer to the data to send
  * @len: length in bytes of the data to send
- * @actual_length: pointer to a location to put the actual length transferred in bytes
+ * @actual_length: pointer to a location to put the actual length transferred
+ *     in bytes
  * @timeout: time in msecs to wait for the message to complete before
  *     timing out (if 0 the wait is forever)
+ *
  * Context: !in_interrupt ()
  *
  * This function sends a simple interrupt message to a specified endpoint and
@@ -181,44 +190,43 @@ int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
 EXPORT_SYMBOL_GPL(usb_interrupt_msg);
 
 /**
- *     usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
- *     @usb_dev: pointer to the usb device to send the message to
- *     @pipe: endpoint "pipe" to send the message to
- *     @data: pointer to the data to send
- *     @len: length in bytes of the data to send
- *     @actual_length: pointer to a location to put the actual length transferred in bytes
- *     @timeout: time in msecs to wait for the message to complete before
- *             timing out (if 0 the wait is forever)
- *     Context: !in_interrupt ()
- *
- *     This function sends a simple bulk message to a specified endpoint
- *     and waits for the message to complete, or timeout.
- *     
- *     If successful, it returns 0, otherwise a negative error number.
- *     The number of actual bytes transferred will be stored in the 
- *     actual_length paramater.
- *
- *     Don't use this function from within an interrupt context, like a
- *     bottom half handler.  If you need an asynchronous message, or need to
- *     send a message from within interrupt context, use usb_submit_urb()
- *      If a thread in your driver uses this call, make sure your disconnect()
- *      method can wait for it to complete.  Since you don't have a handle on
- *      the URB used, you can't cancel the request.
- *
- *     Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT
- *     ioctl, users are forced to abuse this routine by using it to submit
- *     URBs for interrupt endpoints.  We will take the liberty of creating
- *     an interrupt URB (with the default interval) if the target is an
- *     interrupt endpoint.
+ * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
+ * @usb_dev: pointer to the usb device to send the message to
+ * @pipe: endpoint "pipe" to send the message to
+ * @data: pointer to the data to send
+ * @len: length in bytes of the data to send
+ * @actual_length: pointer to a location to put the actual length transferred
+ *     in bytes
+ * @timeout: time in msecs to wait for the message to complete before
+ *     timing out (if 0 the wait is forever)
+ *
+ * Context: !in_interrupt ()
+ *
+ * This function sends a simple bulk message to a specified endpoint
+ * and waits for the message to complete, or timeout.
+ *
+ * If successful, it returns 0, otherwise a negative error number.  The number
+ * of actual bytes transferred will be stored in the actual_length paramater.
+ *
+ * Don't use this function from within an interrupt context, like a bottom half
+ * handler.  If you need an asynchronous message, or need to send a message
+ * from within interrupt context, use usb_submit_urb() If a thread in your
+ * driver uses this call, make sure your disconnect() method can wait for it to
+ * complete.  Since you don't have a handle on the URB used, you can't cancel
+ * the request.
+ *
+ * Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT ioctl,
+ * users are forced to abuse this routine by using it to submit URBs for
+ * interrupt endpoints.  We will take the liberty of creating an interrupt URB
+ * (with the default interval) if the target is an interrupt endpoint.
  */
-int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, 
-                       void *data, int len, int *actual_length, int timeout)
+int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
+                void *data, int len, int *actual_length, int timeout)
 {
        struct urb *urb;
        struct usb_host_endpoint *ep;
 
-       ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)
-                       [usb_pipeendpoint(pipe)];
+       ep = usb_pipe_endpoint(usb_dev, pipe);
        if (!ep || len < 0)
                return -EINVAL;
 
@@ -238,28 +246,27 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
 
        return usb_start_wait_urb(urb, timeout, actual_length);
 }
+EXPORT_SYMBOL_GPL(usb_bulk_msg);
 
 /*-------------------------------------------------------------------*/
 
-static void sg_clean (struct usb_sg_request *io)
+static void sg_clean(struct usb_sg_request *io)
 {
        if (io->urbs) {
                while (io->entries--)
-                       usb_free_urb (io->urbs [io->entries]);
-               kfree (io->urbs);
+                       usb_free_urb(io->urbs [io->entries]);
+               kfree(io->urbs);
                io->urbs = NULL;
        }
-       if (io->dev->dev.dma_mask != NULL)
-               usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents);
        io->dev = NULL;
 }
 
-static void sg_complete (struct urb *urb)
+static void sg_complete(struct urb *urb)
 {
-       struct usb_sg_request   *io = urb->context;
+       struct usb_sg_request *io = urb->context;
        int status = urb->status;
 
-       spin_lock (&io->lock);
+       spin_lock(&io->lock);
 
        /* In 2.5 we require hcds' endpoint queues not to progress after fault
         * reports, until the completion callback (this!) returns.  That lets
@@ -275,13 +282,13 @@ static void sg_complete (struct urb *urb)
                        && (io->status != -ECONNRESET
                                || status != -ECONNRESET)
                        && urb->actual_length) {
-               dev_err (io->dev->bus->controller,
+               dev_err(io->dev->bus->controller,
                        "dev %s ep%d%s scatterlist error %d/%d\n",
                        io->dev->devpath,
-                       usb_pipeendpoint (urb->pipe),
-                       usb_pipein (urb->pipe) ? "in" : "out",
+                       usb_endpoint_num(&urb->ep->desc),
+                       usb_urb_dir_in(urb) ? "in" : "out",
                        status, io->status);
-               // BUG ();
+               /* BUG (); */
        }
 
        if (io->status == 0 && status && status != -ECONNRESET) {
@@ -293,22 +300,22 @@ static void sg_complete (struct urb *urb)
                 * unlink pending urbs so they won't rx/tx bad data.
                 * careful: unlink can sometimes be synchronous...
                 */
-               spin_unlock (&io->lock);
+               spin_unlock(&io->lock);
                for (i = 0, found = 0; i < io->entries; i++) {
                        if (!io->urbs [i] || !io->urbs [i]->dev)
                                continue;
                        if (found) {
-                               retval = usb_unlink_urb (io->urbs [i]);
+                               retval = usb_unlink_urb(io->urbs [i]);
                                if (retval != -EINPROGRESS &&
                                    retval != -ENODEV &&
                                    retval != -EBUSY)
-                                       dev_err (&io->dev->dev,
+                                       dev_err(&io->dev->dev,
                                                "%s, unlink --> %d\n",
-                                               __FUNCTION__, retval);
+                                               __func__, retval);
                        } else if (urb == io->urbs [i])
                                found = 1;
                }
-               spin_lock (&io->lock);
+               spin_lock(&io->lock);
        }
        urb->dev = NULL;
 
@@ -316,9 +323,9 @@ static void sg_complete (struct urb *urb)
        io->bytes += urb->actual_length;
        io->count--;
        if (!io->count)
-               complete (&io->complete);
+               complete(&io->complete);
 
-       spin_unlock (&io->lock);
+       spin_unlock(&io->lock);
 }
 
 
@@ -347,125 +354,106 @@ static void sg_complete (struct urb *urb)
  * The request may be canceled with usb_sg_cancel(), either before or after
  * usb_sg_wait() is called.
  */
-int usb_sg_init (
-       struct usb_sg_request   *io,
-       struct usb_device       *dev,
-       unsigned                pipe, 
-       unsigned                period,
-       struct scatterlist      *sg,
-       int                     nents,
-       size_t                  length,
-       gfp_t                   mem_flags
-)
+int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+               unsigned pipe, unsigned period, struct scatterlist *sg,
+               int nents, size_t length, gfp_t mem_flags)
 {
-       int                     i;
-       int                     urb_flags;
-       int                     dma;
+       int i;
+       int urb_flags;
+       int use_sg;
 
        if (!io || !dev || !sg
-                       || usb_pipecontrol (pipe)
-                       || usb_pipeisoc (pipe)
+                       || usb_pipecontrol(pipe)
+                       || usb_pipeisoc(pipe)
                        || nents <= 0)
                return -EINVAL;
 
-       spin_lock_init (&io->lock);
+       spin_lock_init(&io->lock);
        io->dev = dev;
        io->pipe = pipe;
-       io->sg = sg;
-       io->nents = nents;
 
-       /* not all host controllers use DMA (like the mainstream pci ones);
-        * they can use PIO (sl811) or be software over another transport.
-        */
-       dma = (dev->dev.dma_mask != NULL);
-       if (dma)
-               io->entries = usb_buffer_map_sg (dev, pipe, sg, nents);
-       else
+       if (dev->bus->sg_tablesize > 0) {
+               use_sg = true;
+               io->entries = 1;
+       } else {
+               use_sg = false;
                io->entries = nents;
+       }
 
        /* initialize all the urbs we'll use */
-       if (io->entries <= 0)
-               return io->entries;
-
-       io->count = io->entries;
-       io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags);
+       io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags);
        if (!io->urbs)
                goto nomem;
 
-       urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
-       if (usb_pipein (pipe))
+       urb_flags = URB_NO_INTERRUPT;
+       if (usb_pipein(pipe))
                urb_flags |= URB_SHORT_NOT_OK;
 
-       for (i = 0; i < io->entries; i++) {
-               unsigned                len;
+       for_each_sg(sg, sg, io->entries, i) {
+               struct urb *urb;
+               unsigned len;
 
-               io->urbs [i] = usb_alloc_urb (0, mem_flags);
-               if (!io->urbs [i]) {
+               urb = usb_alloc_urb(0, mem_flags);
+               if (!urb) {
                        io->entries = i;
                        goto nomem;
                }
-
-               io->urbs [i]->dev = NULL;
-               io->urbs [i]->pipe = pipe;
-               io->urbs [i]->interval = period;
-               io->urbs [i]->transfer_flags = urb_flags;
-
-               io->urbs [i]->complete = sg_complete;
-               io->urbs [i]->context = io;
-
-               /*
-                * Some systems need to revert to PIO when DMA is temporarily
-                * unavailable.  For their sakes, both transfer_buffer and
-                * transfer_dma are set when possible.  However this can only
-                * work on systems without:
-                *
-                *  - HIGHMEM, since DMA buffers located in high memory are
-                *    not directly addressable by the CPU for PIO;
-                *
-                *  - IOMMU, since dma_map_sg() is allowed to use an IOMMU to
-                *    make virtually discontiguous buffers be "dma-contiguous"
-                *    so that PIO and DMA need diferent numbers of URBs.
-                *
-                * So when HIGHMEM or IOMMU are in use, transfer_buffer is NULL
-                * to prevent stale pointers and to help spot bugs.
-                */
-               if (dma) {
-                       io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
-                       len = sg_dma_len (sg + i);
-#if defined(CONFIG_HIGHMEM) || defined(CONFIG_IOMMU)
-                       io->urbs[i]->transfer_buffer = NULL;
-#else
-                       io->urbs[i]->transfer_buffer =
-                               page_address(sg[i].page) + sg[i].offset;
-#endif
+               io->urbs[i] = urb;
+
+               urb->dev = NULL;
+               urb->pipe = pipe;
+               urb->interval = period;
+               urb->transfer_flags = urb_flags;
+               urb->complete = sg_complete;
+               urb->context = io;
+               urb->sg = sg;
+
+               if (use_sg) {
+                       /* There is no single transfer buffer */
+                       urb->transfer_buffer = NULL;
+                       urb->num_sgs = nents;
+
+                       /* A length of zero means transfer the whole sg list */
+                       len = length;
+                       if (len == 0) {
+                               for_each_sg(sg, sg, nents, i)
+                                       len += sg->length;
+                       }
                } else {
-                       /* hc may use _only_ transfer_buffer */
-                       io->urbs [i]->transfer_buffer =
-                               page_address (sg [i].page) + sg [i].offset;
-                       len = sg [i].length;
-               }
-
-               if (length) {
-                       len = min_t (unsigned, len, length);
-                       length -= len;
-                       if (length == 0)
-                               io->entries = i + 1;
+                       /*
+                        * Some systems can't use DMA; they use PIO instead.
+                        * For their sakes, transfer_buffer is set whenever
+                        * possible.
+                        */
+                       if (!PageHighMem(sg_page(sg)))
+                               urb->transfer_buffer = sg_virt(sg);
+                       else
+                               urb->transfer_buffer = NULL;
+
+                       len = sg->length;
+                       if (length) {
+                               len = min_t(unsigned, len, length);
+                               length -= len;
+                               if (length == 0)
+                                       io->entries = i + 1;
+                       }
                }
-               io->urbs [i]->transfer_buffer_length = len;
+               urb->transfer_buffer_length = len;
        }
-       io->urbs [--i]->transfer_flags &= ~URB_NO_INTERRUPT;
+       io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
 
        /* transaction state */
+       io->count = io->entries;
        io->status = 0;
        io->bytes = 0;
-       init_completion (&io->complete);
+       init_completion(&io->complete);
        return 0;
 
 nomem:
-       sg_clean (io);
+       sg_clean(io);
        return -ENOMEM;
 }
-
+EXPORT_SYMBOL_GPL(usb_sg_init);
 
 /**
  * usb_sg_wait - synchronously execute scatter/gather request
@@ -505,32 +493,37 @@ nomem:
  * could be transferred.  That capability is less useful for low or full
  * speed interrupt endpoints, which allow at most one packet per millisecond,
  * of at most 8 or 64 bytes (respectively).
+ *
+ * It is not necessary to call this function to reserve bandwidth for devices
+ * under an xHCI host controller, as the bandwidth is reserved when the
+ * configuration or interface alt setting is selected.
  */
-void usb_sg_wait (struct usb_sg_request *io)
+void usb_sg_wait(struct usb_sg_request *io)
 {
-       int             i, entries = io->entries;
+       int i;
+       int entries = io->entries;
 
        /* queue the urbs.  */
-       spin_lock_irq (&io->lock);
+       spin_lock_irq(&io->lock);
        i = 0;
        while (i < entries && !io->status) {
-               int     retval;
+               int retval;
 
-               io->urbs [i]->dev = io->dev;
-               retval = usb_submit_urb (io->urbs [i], GFP_ATOMIC);
+               io->urbs[i]->dev = io->dev;
+               retval = usb_submit_urb(io->urbs [i], GFP_ATOMIC);
 
                /* after we submit, let completions or cancelations fire;
                 * we handshake using io->status.
                 */
-               spin_unlock_irq (&io->lock);
+               spin_unlock_irq(&io->lock);
                switch (retval) {
                        /* maybe we retrying will recover */
-               case -ENXIO:    // hc didn't queue this one
+               case -ENXIO:    /* hc didn't queue this one */
                case -EAGAIN:
                case -ENOMEM:
                        io->urbs[i]->dev = NULL;
                        retval = 0;
-                       yield ();
+                       yield();
                        break;
 
                        /* no error? continue immediately.
@@ -541,34 +534,35 @@ void usb_sg_wait (struct usb_sg_request *io)
                         */
                case 0:
                        ++i;
-                       cpu_relax ();
+                       cpu_relax();
                        break;
 
                        /* fail any uncompleted urbs */
                default:
-                       io->urbs [i]->dev = NULL;
-                       io->urbs [i]->status = retval;
-                       dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
-                               __FUNCTION__, retval);
-                       usb_sg_cancel (io);
+                       io->urbs[i]->dev = NULL;
+                       io->urbs[i]->status = retval;
+                       dev_dbg(&io->dev->dev, "%s, submit --> %d\n",
+                               __func__, retval);
+                       usb_sg_cancel(io);
                }
-               spin_lock_irq (&io->lock);
+               spin_lock_irq(&io->lock);
                if (retval && (io->status == 0 || io->status == -ECONNRESET))
                        io->status = retval;
        }
        io->count -= entries - i;
        if (io->count == 0)
-               complete (&io->complete);
-       spin_unlock_irq (&io->lock);
+               complete(&io->complete);
+       spin_unlock_irq(&io->lock);
 
        /* OK, yes, this could be packaged as non-blocking.
         * So could the submit loop above ... but it's easier to
         * solve neither problem than to solve both!
         */
-       wait_for_completion (&io->complete);
+       wait_for_completion(&io->complete);
 
-       sg_clean (io);
+       sg_clean(io);
 }
+EXPORT_SYMBOL_GPL(usb_sg_wait);
 
 /**
  * usb_sg_cancel - stop scatter/gather i/o issued by usb_sg_wait()
@@ -578,32 +572,33 @@ void usb_sg_wait (struct usb_sg_request *io)
  * It can also prevents one initialized by usb_sg_init() from starting,
  * so that call just frees resources allocated to the request.
  */
-void usb_sg_cancel (struct usb_sg_request *io)
+void usb_sg_cancel(struct usb_sg_request *io)
 {
-       unsigned long   flags;
+       unsigned long flags;
 
-       spin_lock_irqsave (&io->lock, flags);
+       spin_lock_irqsave(&io->lock, flags);
 
        /* shut everything down, if it didn't already */
        if (!io->status) {
-               int     i;
+               int i;
 
                io->status = -ECONNRESET;
-               spin_unlock (&io->lock);
+               spin_unlock(&io->lock);
                for (i = 0; i < io->entries; i++) {
-                       int     retval;
+                       int retval;
 
                        if (!io->urbs [i]->dev)
                                continue;
-                       retval = usb_unlink_urb (io->urbs [i]);
+                       retval = usb_unlink_urb(io->urbs [i]);
                        if (retval != -EINPROGRESS && retval != -EBUSY)
-                               dev_warn (&io->dev->dev, "%s, unlink --> %d\n",
-                                       __FUNCTION__, retval);
+                               dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
+                                       __func__, retval);
                }
-               spin_lock (&io->lock);
+               spin_lock(&io->lock);
        }
-       spin_unlock_irqrestore (&io->lock, flags);
+       spin_unlock_irqrestore(&io->lock, flags);
 }
+EXPORT_SYMBOL_GPL(usb_sg_cancel);
 
 /*-------------------------------------------------------------------*/
 
@@ -629,12 +624,13 @@ void usb_sg_cancel (struct usb_sg_request *io)
  * Returns the number of bytes received on success, or else the status code
  * returned by the underlying usb_control_msg() call.
  */
-int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
+int usb_get_descriptor(struct usb_device *dev, unsigned char type,
+                      unsigned char index, void *buf, int size)
 {
        int i;
        int result;
-       
-       memset(buf,0,size);     // Make sure we parse really received data
+
+       memset(buf, 0, size);   /* Make sure we parse really received data */
 
        for (i = 0; i < 3; ++i) {
                /* retry on length 0 or error; some devices are flakey */
@@ -645,13 +641,14 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
                if (result <= 0 && result != -ETIMEDOUT)
                        continue;
                if (result > 1 && ((u8 *)buf)[1] != type) {
-                       result = -EPROTO;
+                       result = -ENODATA;
                        continue;
                }
                break;
        }
        return result;
 }
+EXPORT_SYMBOL_GPL(usb_get_descriptor);
 
 /**
  * usb_get_string - gets a string descriptor
@@ -687,8 +684,13 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid,
                        USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
                        (USB_DT_STRING << 8) + index, langid, buf, size,
                        USB_CTRL_GET_TIMEOUT);
-               if (!(result == 0 || result == -EPIPE))
-                       break;
+               if (result == 0 || result == -EPIPE)
+                       continue;
+               if (result > 1 && ((u8 *) buf)[1] != USB_DT_STRING) {
+                       result = -ENODATA;
+                       continue;
+               }
+               break;
        }
        return result;
 }
@@ -708,7 +710,7 @@ static void usb_try_string_workarounds(unsigned char *buf, int *length)
 }
 
 static int usb_string_sub(struct usb_device *dev, unsigned int langid,
-               unsigned int index, unsigned char *buf)
+                         unsigned int index, unsigned char *buf)
 {
        int rc;
 
@@ -744,26 +746,61 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,
        return rc;
 }
 
+static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf)
+{
+       int err;
+
+       if (dev->have_langid)
+               return 0;
+
+       if (dev->string_langid < 0)
+               return -EPIPE;
+
+       err = usb_string_sub(dev, 0, 0, tbuf);
+
+       /* If the string was reported but is malformed, default to english
+        * (0x0409) */
+       if (err == -ENODATA || (err > 0 && err < 4)) {
+               dev->string_langid = 0x0409;
+               dev->have_langid = 1;
+               dev_err(&dev->dev,
+                       "string descriptor 0 malformed (err = %d), "
+                       "defaulting to 0x%04x\n",
+                               err, dev->string_langid);
+               return 0;
+       }
+
+       /* In case of all other errors, we assume the device is not able to
+        * deal with strings at all. Set string_langid to -1 in order to
+        * prevent any string to be retrieved from the device */
+       if (err < 0) {
+               dev_err(&dev->dev, "string descriptor 0 read error: %d\n",
+                                       err);
+               dev->string_langid = -1;
+               return -EPIPE;
+       }
+
+       /* always use the first langid listed */
+       dev->string_langid = tbuf[2] | (tbuf[3] << 8);
+       dev->have_langid = 1;
+       dev_dbg(&dev->dev, "default language 0x%04x\n",
+                               dev->string_langid);
+       return 0;
+}
+
 /**
- * usb_string - returns ISO 8859-1 version of a string descriptor
+ * usb_string - returns UTF-8 version of a string descriptor
  * @dev: the device whose string descriptor is being retrieved
  * @index: the number of the descriptor
  * @buf: where to put the string
  * @size: how big is "buf"?
  * Context: !in_interrupt ()
- * 
+ *
  * This converts the UTF-16LE encoded strings returned by devices, from
- * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones
- * that are more usable in most kernel contexts.  Note that all characters
- * in the chosen descriptor that can't be encoded using ISO-8859-1
- * are converted to the question mark ("?") character, and this function
+ * usb_get_string_descriptor(), to null-terminated UTF-8 encoded ones
+ * that are more usable in most kernel contexts.  Note that this function
  * chooses strings in the first language supported by the device.
  *
- * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit
- * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode,
- * and is appropriate for use many uses of English and several other
- * Western European languages.  (But it doesn't include the "Euro" symbol.)
- *
  * This call is synchronous, and may not be used in an interrupt context.
  *
  * Returns length of the string (>= 0) or usb_control_msg status (< 0).
@@ -772,61 +809,42 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
 {
        unsigned char *tbuf;
        int err;
-       unsigned int u, idx;
 
        if (dev->state == USB_STATE_SUSPENDED)
                return -EHOSTUNREACH;
        if (size <= 0 || !buf || !index)
                return -EINVAL;
        buf[0] = 0;
-       tbuf = kmalloc(256, GFP_KERNEL);
+       tbuf = kmalloc(256, GFP_NOIO);
        if (!tbuf)
                return -ENOMEM;
 
-       /* get langid for strings if it's not yet known */
-       if (!dev->have_langid) {
-               err = usb_string_sub(dev, 0, 0, tbuf);
-               if (err < 0) {
-                       dev_err (&dev->dev,
-                               "string descriptor 0 read error: %d\n",
-                               err);
-                       goto errout;
-               } else if (err < 4) {
-                       dev_err (&dev->dev, "string descriptor 0 too short\n");
-                       err = -EINVAL;
-                       goto errout;
-               } else {
-                       dev->have_langid = 1;
-                       dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
-                               /* always use the first langid listed */
-                       dev_dbg (&dev->dev, "default language 0x%04x\n",
-                               dev->string_langid);
-               }
-       }
-       
+       err = usb_get_langid(dev, tbuf);
+       if (err < 0)
+               goto errout;
+
        err = usb_string_sub(dev, dev->string_langid, index, tbuf);
        if (err < 0)
                goto errout;
 
        size--;         /* leave room for trailing NULL char in output buffer */
-       for (idx = 0, u = 2; u < err; u += 2) {
-               if (idx >= size)
-                       break;
-               if (tbuf[u+1])                  /* high byte */
-                       buf[idx++] = '?';  /* non ISO-8859-1 character */
-               else
-                       buf[idx++] = tbuf[u];
-       }
-       buf[idx] = 0;
-       err = idx;
+       err = utf16s_to_utf8s((wchar_t *) &tbuf[2], (err - 2) / 2,
+                       UTF16_LITTLE_ENDIAN, buf, size);
+       buf[err] = 0;
 
        if (tbuf[1] != USB_DT_STRING)
-               dev_dbg(&dev->dev, "wrong descriptor type %02x for string %d (\"%s\")\n", tbuf[1], index, buf);
+               dev_dbg(&dev->dev,
+                       "wrong descriptor type %02x for string %d (\"%s\")\n",
+                       tbuf[1], index, buf);
 
  errout:
        kfree(tbuf);
        return err;
 }
+EXPORT_SYMBOL_GPL(usb_string);
+
+/* one UTF-8-encoded 16-bit character has at most three bytes */
+#define MAX_USB_STRING_SIZE (127 * 3 + 1)
 
 /**
  * usb_cache_string - read a string descriptor and cache it for later use
@@ -842,9 +860,15 @@ char *usb_cache_string(struct usb_device *udev, int index)
        char *smallbuf = NULL;
        int len;
 
-       if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) {
-               if ((len = usb_string(udev, index, buf, 256)) > 0) {
-                       if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL)
+       if (index <= 0)
+               return NULL;
+
+       buf = kmalloc(MAX_USB_STRING_SIZE, GFP_NOIO);
+       if (buf) {
+               len = usb_string(udev, index, buf, MAX_USB_STRING_SIZE);
+               if (len > 0) {
+                       smallbuf = kmalloc(++len, GFP_NOIO);
+                       if (!smallbuf)
                                return buf;
                        memcpy(smallbuf, buf, len);
                }
@@ -883,7 +907,7 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
                return -ENOMEM;
 
        ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
-       if (ret >= 0) 
+       if (ret >= 0)
                memcpy(&dev->descriptor, desc, size);
        kfree(desc);
        return ret;
@@ -927,6 +951,7 @@ int usb_get_status(struct usb_device *dev, int type, int target, void *data)
        kfree(status);
        return ret;
 }
+EXPORT_SYMBOL_GPL(usb_get_status);
 
 /**
  * usb_clear_halt - tells device to clear endpoint halt/stall condition
@@ -955,8 +980,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
 {
        int result;
        int endp = usb_pipeendpoint(pipe);
-       
-       if (usb_pipein (pipe))
+
+       if (usb_pipein(pipe))
                endp |= USB_DIR_IN;
 
        /* we don't care if it wasn't halted first. in fact some devices
@@ -980,25 +1005,54 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
         * the copy in usb-storage, for as long as we need two copies.
         */
 
-       /* toggle was reset by the clear */
-       usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
+       usb_reset_endpoint(dev, endp);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(usb_clear_halt);
+
+static int create_intf_ep_devs(struct usb_interface *intf)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct usb_host_interface *alt = intf->cur_altsetting;
+       int i;
+
+       if (intf->ep_devs_created || intf->unregistering)
+               return 0;
 
+       for (i = 0; i < alt->desc.bNumEndpoints; ++i)
+               (void) usb_create_ep_devs(&intf->dev, &alt->endpoint[i], udev);
+       intf->ep_devs_created = 1;
        return 0;
 }
 
+static void remove_intf_ep_devs(struct usb_interface *intf)
+{
+       struct usb_host_interface *alt = intf->cur_altsetting;
+       int i;
+
+       if (!intf->ep_devs_created)
+               return;
+
+       for (i = 0; i < alt->desc.bNumEndpoints; ++i)
+               usb_remove_ep_devs(&alt->endpoint[i]);
+       intf->ep_devs_created = 0;
+}
+
 /**
  * usb_disable_endpoint -- Disable an endpoint by address
  * @dev: the device whose endpoint is being disabled
  * @epaddr: the endpoint's address.  Endpoint number for output,
  *     endpoint number + USB_DIR_IN for input
+ * @reset_hardware: flag to erase any endpoint state stored in the
+ *     controller hardware
  *
- * Deallocates hcd/hardware state for this endpoint ... and nukes all
- * pending urbs.
- *
- * If the HCD hasn't registered a disable() function, this sets the
- * endpoint's maxpacket size to 0 to prevent further submissions.
+ * Disables the endpoint for URB submission and nukes all pending URBs.
+ * If @reset_hardware is set then also deallocates hcd/hardware state
+ * for the endpoint.
  */
-void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
+void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
+               bool reset_hardware)
 {
        unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
        struct usb_host_endpoint *ep;
@@ -1008,36 +1062,68 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
 
        if (usb_endpoint_out(epaddr)) {
                ep = dev->ep_out[epnum];
-               dev->ep_out[epnum] = NULL;
+               if (reset_hardware)
+                       dev->ep_out[epnum] = NULL;
        } else {
                ep = dev->ep_in[epnum];
-               dev->ep_in[epnum] = NULL;
+               if (reset_hardware)
+                       dev->ep_in[epnum] = NULL;
        }
        if (ep) {
                ep->enabled = 0;
-               usb_hcd_endpoint_disable(dev, ep);
+               usb_hcd_flush_endpoint(dev, ep);
+               if (reset_hardware)
+                       usb_hcd_disable_endpoint(dev, ep);
        }
 }
 
 /**
+ * usb_reset_endpoint - Reset an endpoint's state.
+ * @dev: the device whose endpoint is to be reset
+ * @epaddr: the endpoint's address.  Endpoint number for output,
+ *     endpoint number + USB_DIR_IN for input
+ *
+ * Resets any host-side endpoint state such as the toggle bit,
+ * sequence number or current window.
+ */
+void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr)
+{
+       unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
+       struct usb_host_endpoint *ep;
+
+       if (usb_endpoint_out(epaddr))
+               ep = dev->ep_out[epnum];
+       else
+               ep = dev->ep_in[epnum];
+       if (ep)
+               usb_hcd_reset_endpoint(dev, ep);
+}
+EXPORT_SYMBOL_GPL(usb_reset_endpoint);
+
+
+/**
  * usb_disable_interface -- Disable all endpoints for an interface
  * @dev: the device whose interface is being disabled
  * @intf: pointer to the interface descriptor
+ * @reset_hardware: flag to erase any endpoint state stored in the
+ *     controller hardware
  *
  * Disables all the endpoints for the interface's current altsetting.
  */
-void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf)
+void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
+               bool reset_hardware)
 {
        struct usb_host_interface *alt = intf->cur_altsetting;
        int i;
 
        for (i = 0; i < alt->desc.bNumEndpoints; ++i) {
                usb_disable_endpoint(dev,
-                               alt->endpoint[i].desc.bEndpointAddress);
+                               alt->endpoint[i].desc.bEndpointAddress,
+                               reset_hardware);
        }
 }
 
-/*
+/**
  * usb_disable_device - Disable all the endpoints for a USB device
  * @dev: the device whose endpoints are being disabled
  * @skip_ep0: 0 to disable endpoint 0, 1 to skip it.
@@ -1051,13 +1137,12 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
 {
        int i;
 
-       dev_dbg(&dev->dev, "%s nuking %s URBs\n", __FUNCTION__,
-                       skip_ep0 ? "non-ep0" : "all");
+       dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
+               skip_ep0 ? "non-ep0" : "all");
        for (i = skip_ep0; i < 16; ++i) {
-               usb_disable_endpoint(dev, i);
-               usb_disable_endpoint(dev, i + USB_DIR_IN);
+               usb_disable_endpoint(dev, i, true);
+               usb_disable_endpoint(dev, i + USB_DIR_IN, true);
        }
-       dev->toggle[0] = dev->toggle[1] = 0;
 
        /* getting rid of interfaces will disconnect
         * any drivers bound to them (a key side effect)
@@ -1070,17 +1155,18 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
                        interface = dev->actconfig->interface[i];
                        if (!device_is_registered(&interface->dev))
                                continue;
-                       dev_dbg (&dev->dev, "unregistering interface %s\n",
-                               interface->dev.bus_id);
-                       usb_remove_sysfs_intf_files(interface);
-                       device_del (&interface->dev);
+                       dev_dbg(&dev->dev, "unregistering interface %s\n",
+                               dev_name(&interface->dev));
+                       interface->unregistering = 1;
+                       remove_intf_ep_devs(interface);
+                       device_del(&interface->dev);
                }
 
                /* Now that the interfaces are unbound, nobody should
                 * try to access them.
                 */
                for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
-                       put_device (&dev->actconfig->interface[i]->dev);
+                       put_device(&dev->actconfig->interface[i]->dev);
                        dev->actconfig->interface[i] = NULL;
                }
                dev->actconfig = NULL;
@@ -1089,47 +1175,47 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
        }
 }
 
-
-/*
+/**
  * usb_enable_endpoint - Enable an endpoint for USB communications
  * @dev: the device whose interface is being enabled
  * @ep: the endpoint
+ * @reset_ep: flag to reset the endpoint state
  *
- * Resets the endpoint toggle, and sets dev->ep_{in,out} pointers.
+ * Resets the endpoint state if asked, and sets dev->ep_{in,out} pointers.
  * For control endpoints, both the input and output sides are handled.
  */
-void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
+void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep,
+               bool reset_ep)
 {
        int epnum = usb_endpoint_num(&ep->desc);
        int is_out = usb_endpoint_dir_out(&ep->desc);
        int is_control = usb_endpoint_xfer_control(&ep->desc);
 
-       if (is_out || is_control) {
-               usb_settoggle(dev, epnum, 1, 0);
+       if (reset_ep)
+               usb_hcd_reset_endpoint(dev, ep);
+       if (is_out || is_control)
                dev->ep_out[epnum] = ep;
-       }
-       if (!is_out || is_control) {
-               usb_settoggle(dev, epnum, 0, 0);
+       if (!is_out || is_control)
                dev->ep_in[epnum] = ep;
-       }
        ep->enabled = 1;
 }
 
-/*
+/**
  * usb_enable_interface - Enable all the endpoints for an interface
  * @dev: the device whose interface is being enabled
  * @intf: pointer to the interface descriptor
+ * @reset_eps: flag to reset the endpoints' state
  *
  * Enables all the endpoints for the interface's current altsetting.
  */
-static void usb_enable_interface(struct usb_device *dev,
-                                struct usb_interface *intf)
+void usb_enable_interface(struct usb_device *dev,
+               struct usb_interface *intf, bool reset_eps)
 {
        struct usb_host_interface *alt = intf->cur_altsetting;
        int i;
 
        for (i = 0; i < alt->desc.bNumEndpoints; ++i)
-               usb_enable_endpoint(dev, &alt->endpoint[i]);
+               usb_enable_endpoint(dev, &alt->endpoint[i], reset_eps);
 }
 
 /**
@@ -1169,8 +1255,11 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
 {
        struct usb_interface *iface;
        struct usb_host_interface *alt;
+       struct usb_hcd *hcd = bus_to_hcd(dev->bus);
        int ret;
        int manual = 0;
+       unsigned int epaddr;
+       unsigned int pipe;
 
        if (dev->state == USB_STATE_SUSPENDED)
                return -EHOSTUNREACH;
@@ -1184,11 +1273,27 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
 
        alt = usb_altnum_to_altsetting(iface, alternate);
        if (!alt) {
-               warn("selecting invalid altsetting %d", alternate);
+               dev_warn(&dev->dev, "selecting invalid altsetting %d\n",
+                        alternate);
                return -EINVAL;
        }
 
-       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+       /* Make sure we have enough bandwidth for this alternate interface.
+        * Remove the current alt setting and add the new alt setting.
+        */
+       mutex_lock(&hcd->bandwidth_mutex);
+       ret = usb_hcd_alloc_bandwidth(dev, NULL, iface->cur_altsetting, alt);
+       if (ret < 0) {
+               dev_info(&dev->dev, "Not enough bandwidth for altsetting %d\n",
+                               alternate);
+               mutex_unlock(&hcd->bandwidth_mutex);
+               return ret;
+       }
+
+       if (dev->quirks & USB_QUIRK_NO_SET_INTF)
+               ret = -EPIPE;
+       else
+               ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                   USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
                                   alternate, interface, NULL, 0, 5000);
 
@@ -1200,8 +1305,13 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
                        "manual set_interface for iface %d, alt %d\n",
                        interface, alternate);
                manual = 1;
-       } else if (ret < 0)
+       } else if (ret < 0) {
+               /* Re-instate the old alt setting */
+               usb_hcd_alloc_bandwidth(dev, NULL, alt, iface->cur_altsetting);
+               mutex_unlock(&hcd->bandwidth_mutex);
                return ret;
+       }
+       mutex_unlock(&hcd->bandwidth_mutex);
 
        /* FIXME drivers shouldn't need to replicate/bugfix the logic here
         * when they implement async or easily-killable versions of this or
@@ -1210,9 +1320,11 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
         */
 
        /* prevent submissions using previous endpoint settings */
-       if (device_is_registered(&iface->dev))
+       if (iface->cur_altsetting != alt) {
+               remove_intf_ep_devs(iface);
                usb_remove_sysfs_intf_files(iface);
-       usb_disable_interface(dev, iface);
+       }
+       usb_disable_interface(dev, iface, true);
 
        iface->cur_altsetting = alt;
 
@@ -1225,11 +1337,11 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
                int i;
 
                for (i = 0; i < alt->desc.bNumEndpoints; i++) {
-                       unsigned int epaddr =
-                               alt->endpoint[i].desc.bEndpointAddress;
-                       unsigned int pipe =
-       __create_pipe(dev, USB_ENDPOINT_NUMBER_MASK & epaddr)
-       | (usb_endpoint_out(epaddr) ? USB_DIR_OUT : USB_DIR_IN);
+                       epaddr = alt->endpoint[i].desc.bEndpointAddress;
+                       pipe = __create_pipe(dev,
+                                       USB_ENDPOINT_NUMBER_MASK & epaddr) |
+                                       (usb_endpoint_out(epaddr) ?
+                                       USB_DIR_OUT : USB_DIR_IN);
 
                        usb_clear_halt(dev, pipe);
                }
@@ -1246,12 +1358,14 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
         * during the SETUP stage - hence EP0 toggles are "don't care" here.
         * (Likewise, EP0 never "halts" on well designed devices.)
         */
-       usb_enable_interface(dev, iface);
-       if (device_is_registered(&iface->dev))
+       usb_enable_interface(dev, iface, true);
+       if (device_is_registered(&iface->dev)) {
                usb_create_sysfs_intf_files(iface);
-
+               create_intf_ep_devs(iface);
+       }
        return 0;
 }
+EXPORT_SYMBOL_GPL(usb_set_interface);
 
 /**
  * usb_reset_configuration - lightweight device reset
@@ -1260,7 +1374,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
  * This issues a standard SET_CONFIGURATION request to the device using
  * the current configuration.  The effect is to reset most USB-related
  * state in the device, including interface altsettings (reset to zero),
- * endpoint halts (cleared), and data toggle (only for bulk and interrupt
+ * endpoint halts (cleared), and endpoint state (only for bulk and interrupt
  * endpoints).  Other usbcore state is unchanged, including bindings of
  * usb device drivers to interfaces.
  *
@@ -1268,7 +1382,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
  * (multi-interface) devices.  Instead, the driver for each interface may
  * use usb_set_interface() on the interfaces it claims.  Be careful though;
  * some devices don't support the SET_INTERFACE request, and others won't
- * reset all the interface state (notably data toggles).  Resetting the whole
+ * reset all the interface state (notably endpoint state).  Resetting the whole
  * configuration would affect other drivers' interfaces.
  *
  * The caller must own the device lock.
@@ -1279,6 +1393,7 @@ int usb_reset_configuration(struct usb_device *dev)
 {
        int                     i, retval;
        struct usb_host_config  *config;
+       struct usb_hcd *hcd = bus_to_hcd(dev->bus);
 
        if (dev->state == USB_STATE_SUSPENDED)
                return -EHOSTUNREACH;
@@ -1289,27 +1404,57 @@ int usb_reset_configuration(struct usb_device *dev)
         */
 
        for (i = 1; i < 16; ++i) {
-               usb_disable_endpoint(dev, i);
-               usb_disable_endpoint(dev, i + USB_DIR_IN);
+               usb_disable_endpoint(dev, i, true);
+               usb_disable_endpoint(dev, i + USB_DIR_IN, true);
        }
 
        config = dev->actconfig;
+       retval = 0;
+       mutex_lock(&hcd->bandwidth_mutex);
+       /* Make sure we have enough bandwidth for each alternate setting 0 */
+       for (i = 0; i < config->desc.bNumInterfaces; i++) {
+               struct usb_interface *intf = config->interface[i];
+               struct usb_host_interface *alt;
+
+               alt = usb_altnum_to_altsetting(intf, 0);
+               if (!alt)
+                       alt = &intf->altsetting[0];
+               if (alt != intf->cur_altsetting)
+                       retval = usb_hcd_alloc_bandwidth(dev, NULL,
+                                       intf->cur_altsetting, alt);
+               if (retval < 0)
+                       break;
+       }
+       /* If not, reinstate the old alternate settings */
+       if (retval < 0) {
+reset_old_alts:
+               for (i--; i >= 0; i--) {
+                       struct usb_interface *intf = config->interface[i];
+                       struct usb_host_interface *alt;
+
+                       alt = usb_altnum_to_altsetting(intf, 0);
+                       if (!alt)
+                               alt = &intf->altsetting[0];
+                       if (alt != intf->cur_altsetting)
+                               usb_hcd_alloc_bandwidth(dev, NULL,
+                                               alt, intf->cur_altsetting);
+               }
+               mutex_unlock(&hcd->bandwidth_mutex);
+               return retval;
+       }
        retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                        USB_REQ_SET_CONFIGURATION, 0,
                        config->desc.bConfigurationValue, 0,
                        NULL, 0, USB_CTRL_SET_TIMEOUT);
        if (retval < 0)
-               return retval;
-
-       dev->toggle[0] = dev->toggle[1] = 0;
+               goto reset_old_alts;
+       mutex_unlock(&hcd->bandwidth_mutex);
 
        /* re-init hc/hcd interface/endpoint state */
        for (i = 0; i < config->desc.bNumInterfaces; i++) {
                struct usb_interface *intf = config->interface[i];
                struct usb_host_interface *alt;
 
-               if (device_is_registered(&intf->dev))
-                       usb_remove_sysfs_intf_files(intf);
                alt = usb_altnum_to_altsetting(intf, 0);
 
                /* No altsetting 0?  We'll assume the first altsetting.
@@ -1320,15 +1465,22 @@ int usb_reset_configuration(struct usb_device *dev)
                if (!alt)
                        alt = &intf->altsetting[0];
 
+               if (alt != intf->cur_altsetting) {
+                       remove_intf_ep_devs(intf);
+                       usb_remove_sysfs_intf_files(intf);
+               }
                intf->cur_altsetting = alt;
-               usb_enable_interface(dev, intf);
-               if (device_is_registered(&intf->dev))
+               usb_enable_interface(dev, intf, true);
+               if (device_is_registered(&intf->dev)) {
                        usb_create_sysfs_intf_files(intf);
+                       create_intf_ep_devs(intf);
+               }
        }
        return 0;
 }
+EXPORT_SYMBOL_GPL(usb_reset_configuration);
 
-void usb_release_interface(struct device *dev)
+static void usb_release_interface(struct device *dev)
 {
        struct usb_interface *intf = to_usb_interface(dev);
        struct usb_interface_cache *intfc =
@@ -1339,60 +1491,25 @@ void usb_release_interface(struct device *dev)
 }
 
 #ifdef CONFIG_HOTPLUG
-static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
-                char *buffer, int buffer_size)
+static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        struct usb_device *usb_dev;
        struct usb_interface *intf;
        struct usb_host_interface *alt;
-       int i = 0;
-       int length = 0;
-
-       if (!dev)
-               return -ENODEV;
-
-       /* driver is often null here; dev_dbg() would oops */
-       pr_debug ("usb %s: uevent\n", dev->bus_id);
 
        intf = to_usb_interface(dev);
        usb_dev = interface_to_usbdev(intf);
        alt = intf->cur_altsetting;
 
-#ifdef CONFIG_USB_DEVICEFS
-       if (add_uevent_var(envp, num_envp, &i,
-                          buffer, buffer_size, &length,
-                          "DEVICE=/proc/bus/usb/%03d/%03d",
-                          usb_dev->bus->busnum, usb_dev->devnum))
-               return -ENOMEM;
-#endif
-
-       if (add_uevent_var(envp, num_envp, &i,
-                          buffer, buffer_size, &length,
-                          "PRODUCT=%x/%x/%x",
-                          le16_to_cpu(usb_dev->descriptor.idVendor),
-                          le16_to_cpu(usb_dev->descriptor.idProduct),
-                          le16_to_cpu(usb_dev->descriptor.bcdDevice)))
-               return -ENOMEM;
-
-       if (add_uevent_var(envp, num_envp, &i,
-                          buffer, buffer_size, &length,
-                          "TYPE=%d/%d/%d",
-                          usb_dev->descriptor.bDeviceClass,
-                          usb_dev->descriptor.bDeviceSubClass,
-                          usb_dev->descriptor.bDeviceProtocol))
-               return -ENOMEM;
-
-       if (add_uevent_var(envp, num_envp, &i,
-                  buffer, buffer_size, &length,
-                  "INTERFACE=%d/%d/%d",
+       if (add_uevent_var(env, "INTERFACE=%d/%d/%d",
                   alt->desc.bInterfaceClass,
                   alt->desc.bInterfaceSubClass,
                   alt->desc.bInterfaceProtocol))
                return -ENOMEM;
 
-       if (add_uevent_var(envp, num_envp, &i,
-                  buffer, buffer_size, &length,
-                  "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+       if (add_uevent_var(env,
+                  "MODALIAS=usb:"
+                  "v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
                   le16_to_cpu(usb_dev->descriptor.idVendor),
                   le16_to_cpu(usb_dev->descriptor.idProduct),
                   le16_to_cpu(usb_dev->descriptor.bcdDevice),
@@ -1404,14 +1521,12 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
                   alt->desc.bInterfaceProtocol))
                return -ENOMEM;
 
-       envp[i] = NULL;
        return 0;
 }
 
 #else
 
-static int usb_if_uevent(struct device *dev, char **envp,
-                        int num_envp, char *buffer, int buffer_size)
+static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        return -ENODEV;
 }
@@ -1424,8 +1539,8 @@ struct device_type usb_if_device_type = {
 };
 
 static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
-                                                      struct usb_host_config *config,
-                                                      u8 inum)
+                                               struct usb_host_config *config,
+                                               u8 inum)
 {
        struct usb_interface_assoc_descriptor *retval = NULL;
        struct usb_interface_assoc_descriptor *intf_assoc;
@@ -1454,6 +1569,45 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
 
 
 /*
+ * Internal function to queue a device reset
+ *
+ * This is initialized into the workstruct in 'struct
+ * usb_device->reset_ws' that is launched by
+ * message.c:usb_set_configuration() when initializing each 'struct
+ * usb_interface'.
+ *
+ * It is safe to get the USB device without reference counts because
+ * the life cycle of @iface is bound to the life cycle of @udev. Then,
+ * this function will be ran only if @iface is alive (and before
+ * freeing it any scheduled instances of it will have been cancelled).
+ *
+ * We need to set a flag (usb_dev->reset_running) because when we call
+ * the reset, the interfaces might be unbound. The current interface
+ * cannot try to remove the queued work as it would cause a deadlock
+ * (you cannot remove your work from within your executing
+ * workqueue). This flag lets it know, so that
+ * usb_cancel_queued_reset() doesn't try to do it.
+ *
+ * See usb_queue_reset_device() for more details
+ */
+static void __usb_queue_reset_device(struct work_struct *ws)
+{
+       int rc;
+       struct usb_interface *iface =
+               container_of(ws, struct usb_interface, reset_ws);
+       struct usb_device *udev = interface_to_usbdev(iface);
+
+       rc = usb_lock_device_for_reset(udev, iface);
+       if (rc >= 0) {
+               iface->reset_running = 1;
+               usb_reset_device(udev);
+               iface->reset_running = 0;
+               usb_unlock_device(udev);
+       }
+}
+
+
+/*
  * usb_set_configuration - Makes a particular device setting be current
  * @dev: the device whose configuration is being updated
  * @configuration: the configuration being chosen.
@@ -1481,13 +1635,16 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
  * channels are available independently; and choosing between open
  * standard device protocols (like CDC) or proprietary ones.
  *
+ * Note that a non-authorized device (dev->authorized == 0) will only
+ * be put in unconfigured mode.
+ *
  * Note that USB has an additional level of device configurability,
  * associated with interfaces.  That configurability is accessed using
  * usb_set_interface().
  *
  * This call is synchronous. The calling context must be able to sleep,
  * must own the device lock, and must not hold the driver model's USB
- * bus mutex; usb device driver probe() methods cannot use this routine.
+ * bus mutex; usb interface driver probe() methods cannot use this routine.
  *
  * Returns zero on success, or else the status code returned by the
  * underlying call that failed.  On successful completion, each interface
@@ -1500,9 +1657,10 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
        int i, ret;
        struct usb_host_config *cp = NULL;
        struct usb_interface **new_interfaces = NULL;
+       struct usb_hcd *hcd = bus_to_hcd(dev->bus);
        int n, nintf;
 
-       if (configuration == -1)
+       if (dev->authorized == 0 || configuration == -1)
                configuration = 0;
        else {
                for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
@@ -1530,18 +1688,18 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
        if (cp) {
                nintf = cp->desc.bNumInterfaces;
                new_interfaces = kmalloc(nintf * sizeof(*new_interfaces),
-                               GFP_KERNEL);
+                               GFP_NOIO);
                if (!new_interfaces) {
-                       dev_err(&dev->dev, "Out of memory");
+                       dev_err(&dev->dev, "Out of memory\n");
                        return -ENOMEM;
                }
 
                for (; n < nintf; ++n) {
                        new_interfaces[n] = kzalloc(
                                        sizeof(struct usb_interface),
-                                       GFP_KERNEL);
+                                       GFP_NOIO);
                        if (!new_interfaces[n]) {
-                               dev_err(&dev->dev, "Out of memory");
+                               dev_err(&dev->dev, "Out of memory\n");
                                ret = -ENOMEM;
 free_interfaces:
                                while (--n >= 0)
@@ -1563,16 +1721,33 @@ free_interfaces:
        if (ret)
                goto free_interfaces;
 
+       /* Make sure we have bandwidth (and available HCD resources) for this
+        * configuration.  Remove endpoints from the schedule if we're dropping
+        * this configuration to set configuration 0.  After this point, the
+        * host controller will not allow submissions to dropped endpoints.  If
+        * this call fails, the device state is unchanged.
+        */
+       mutex_lock(&hcd->bandwidth_mutex);
+       ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
+       if (ret < 0) {
+               usb_autosuspend_device(dev);
+               mutex_unlock(&hcd->bandwidth_mutex);
+               goto free_interfaces;
+       }
+
        /* if it's already configured, clear out old state first.
         * getting rid of old interfaces means unbinding their drivers.
         */
        if (dev->state != USB_STATE_ADDRESS)
-               usb_disable_device (dev, 1);    // Skip ep0
+               usb_disable_device(dev, 1);     /* Skip ep0 */
 
-       if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-                       USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
-                       NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
+       /* Get rid of pending async Set-Config requests for this device */
+       cancel_async_set_config(dev);
 
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                             USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+                             NULL, 0, USB_CTRL_SET_TIMEOUT);
+       if (ret < 0) {
                /* All the old state is gone, so what else can we do?
                 * The device is probably useless now anyway.
                 */
@@ -1582,9 +1757,12 @@ free_interfaces:
        dev->actconfig = cp;
        if (!cp) {
                usb_set_device_state(dev, USB_STATE_ADDRESS);
+               usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
                usb_autosuspend_device(dev);
+               mutex_unlock(&hcd->bandwidth_mutex);
                goto free_interfaces;
        }
+       mutex_unlock(&hcd->bandwidth_mutex);
        usb_set_device_state(dev, USB_STATE_CONFIGURED);
 
        /* Initialize the new interface structures and the
@@ -1613,21 +1791,23 @@ free_interfaces:
                        alt = &intf->altsetting[0];
 
                intf->cur_altsetting = alt;
-               usb_enable_interface(dev, intf);
+               usb_enable_interface(dev, intf, true);
                intf->dev.parent = &dev->dev;
                intf->dev.driver = NULL;
                intf->dev.bus = &usb_bus_type;
                intf->dev.type = &usb_if_device_type;
+               intf->dev.groups = usb_interface_groups;
                intf->dev.dma_mask = dev->dev.dma_mask;
-               device_initialize (&intf->dev);
-               mark_quiesced(intf);
-               sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
-                        dev->bus->busnum, dev->devpath,
-                        configuration, alt->desc.bInterfaceNumber);
+               INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
+               device_initialize(&intf->dev);
+               dev_set_name(&intf->dev, "%d-%s:%d.%d",
+                       dev->bus->busnum, dev->devpath,
+                       configuration, alt->desc.bInterfaceNumber);
        }
        kfree(new_interfaces);
 
-       if (cp->string == NULL)
+       if (cp->string == NULL &&
+                       !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
                cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
 
        /* Now that all the interfaces are set up, register them
@@ -1639,27 +1819,32 @@ free_interfaces:
        for (i = 0; i < nintf; ++i) {
                struct usb_interface *intf = cp->interface[i];
 
-               dev_dbg (&dev->dev,
+               dev_dbg(&dev->dev,
                        "adding %s (config #%d, interface %d)\n",
-                       intf->dev.bus_id, configuration,
+                       dev_name(&intf->dev), configuration,
                        intf->cur_altsetting->desc.bInterfaceNumber);
-               ret = device_add (&intf->dev);
+               device_enable_async_suspend(&intf->dev);
+               ret = device_add(&intf->dev);
                if (ret != 0) {
                        dev_err(&dev->dev, "device_add(%s) --> %d\n",
-                               intf->dev.bus_id, ret);
+                               dev_name(&intf->dev), ret);
                        continue;
                }
-               usb_create_sysfs_intf_files (intf);
+               create_intf_ep_devs(intf);
        }
 
        usb_autosuspend_device(dev);
        return 0;
 }
 
+static LIST_HEAD(set_config_list);
+static DEFINE_SPINLOCK(set_config_lock);
+
 struct set_config_request {
        struct usb_device       *udev;
        int                     config;
        struct work_struct      work;
+       struct list_head        node;
 };
 
 /* Worker routine for usb_driver_set_configuration() */
@@ -1667,14 +1852,35 @@ static void driver_set_config_work(struct work_struct *work)
 {
        struct set_config_request *req =
                container_of(work, struct set_config_request, work);
+       struct usb_device *udev = req->udev;
+
+       usb_lock_device(udev);
+       spin_lock(&set_config_lock);
+       list_del(&req->node);
+       spin_unlock(&set_config_lock);
 
-       usb_lock_device(req->udev);
-       usb_set_configuration(req->udev, req->config);
-       usb_unlock_device(req->udev);
-       usb_put_dev(req->udev);
+       if (req->config >= -1)          /* Is req still valid? */
+               usb_set_configuration(udev, req->config);
+       usb_unlock_device(udev);
+       usb_put_dev(udev);
        kfree(req);
 }
 
+/* Cancel pending Set-Config requests for a device whose configuration
+ * was just changed
+ */
+static void cancel_async_set_config(struct usb_device *udev)
+{
+       struct set_config_request *req;
+
+       spin_lock(&set_config_lock);
+       list_for_each_entry(req, &set_config_list, node) {
+               if (req->udev == udev)
+                       req->config = -999;     /* Mark as cancelled */
+       }
+       spin_unlock(&set_config_lock);
+}
+
 /**
  * usb_driver_set_configuration - Provide a way for drivers to change device configurations
  * @udev: the device whose configuration is being updated
@@ -1691,7 +1897,7 @@ static void driver_set_config_work(struct work_struct *work)
  * routine gets around the normal restrictions by using a work thread to
  * submit the change-config request.
  *
- * Returns 0 if the request was succesfully queued, error code otherwise.
+ * Returns 0 if the request was successfully queued, error code otherwise.
  * The caller has no way to know whether the queued request will eventually
  * succeed.
  */
@@ -1706,27 +1912,12 @@ int usb_driver_set_configuration(struct usb_device *udev, int config)
        req->config = config;
        INIT_WORK(&req->work, driver_set_config_work);
 
+       spin_lock(&set_config_lock);
+       list_add(&req->node, &set_config_list);
+       spin_unlock(&set_config_lock);
+
        usb_get_dev(udev);
        schedule_work(&req->work);
        return 0;
 }
 EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
-
-// synchronous request completion model
-EXPORT_SYMBOL(usb_control_msg);
-EXPORT_SYMBOL(usb_bulk_msg);
-
-EXPORT_SYMBOL(usb_sg_init);
-EXPORT_SYMBOL(usb_sg_cancel);
-EXPORT_SYMBOL(usb_sg_wait);
-
-// synchronous control message convenience routines
-EXPORT_SYMBOL(usb_get_descriptor);
-EXPORT_SYMBOL(usb_get_status);
-EXPORT_SYMBOL(usb_string);
-
-// synchronous calls that also maintain usbcore state
-EXPORT_SYMBOL(usb_clear_halt);
-EXPORT_SYMBOL(usb_reset_configuration);
-EXPORT_SYMBOL(usb_set_interface);
-