Merge branch 'stable-3.2' into pandora-3.2
[pandora-kernel.git] / drivers / usb / core / hcd.c
index 73cbbd8..3cedf91 100644 (file)
@@ -442,7 +442,11 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
        struct usb_ctrlrequest *cmd;
        u16             typeReq, wValue, wIndex, wLength;
        u8              *ubuf = urb->transfer_buffer;
-       u8              tbuf [sizeof (struct usb_hub_descriptor)]
+       /*
+        * tbuf should be as big as the BOS descriptor and
+        * the USB hub descriptor.
+        */
+       u8              tbuf[USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE]
                __attribute__((aligned(4)));
        const u8        *bufp = tbuf;
        unsigned        len = 0;
@@ -562,6 +566,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
                        else /* unsupported IDs --> "protocol stall" */
                                goto error;
                        break;
+               case USB_DT_BOS << 8:
+                       goto nongeneric;
                default:
                        goto error;
                }
@@ -596,6 +602,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
        /* CLASS REQUESTS (and errors) */
 
        default:
+nongeneric:
                /* non-generic request */
                switch (typeReq) {
                case GetHubStatus:
@@ -605,6 +612,9 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
                case GetHubDescriptor:
                        len = sizeof (struct usb_hub_descriptor);
                        break;
+               case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+                       /* len is returned by hub_control */
+                       break;
                }
                status = hcd->driver->hub_control (hcd,
                        typeReq, wValue, wIndex,
@@ -615,7 +625,7 @@ error:
                status = -EPIPE;
        }
 
-       if (status) {
+       if (status < 0) {
                len = 0;
                if (status != -EPIPE) {
                        dev_dbg (hcd->self.controller,
@@ -624,6 +634,10 @@ error:
                                typeReq, wValue, wIndex,
                                wLength, status);
                }
+       } else if (status > 0) {
+               /* hub_control may return the length of data copied. */
+               len = status;
+               status = 0;
        }
        if (len) {
                if (urb->transfer_buffer_length < len)
@@ -988,10 +1002,7 @@ static int register_root_hub(struct usb_hcd *hcd)
        if (retval) {
                dev_err (parent_dev, "can't register root hub for %s, %d\n",
                                dev_name(&usb_dev->dev), retval);
-       }
-       mutex_unlock(&usb_bus_list_lock);
-
-       if (retval == 0) {
+       } else {
                spin_lock_irq (&hcd_root_hub_lock);
                hcd->rh_registered = 1;
                spin_unlock_irq (&hcd_root_hub_lock);
@@ -1000,6 +1011,7 @@ static int register_root_hub(struct usb_hcd *hcd)
                if (HCD_DEAD(hcd))
                        usb_hc_died (hcd);      /* This time clean up */
        }
+       mutex_unlock(&usb_bus_list_lock);
 
        return retval;
 }
@@ -1398,11 +1410,10 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
                                        ret = -EAGAIN;
                                else
                                        urb->transfer_flags |= URB_DMA_MAP_SG;
-                               if (n != urb->num_sgs) {
-                                       urb->num_sgs = n;
+                               urb->num_mapped_sgs = n;
+                               if (n != urb->num_sgs)
                                        urb->transfer_flags |=
                                                        URB_DMA_SG_COMBINED;
-                               }
                        } else if (urb->sg) {
                                struct scatterlist *sg = urb->sg;
                                urb->transfer_dma = dma_map_page(
@@ -1531,6 +1542,7 @@ static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status)
 int usb_hcd_unlink_urb (struct urb *urb, int status)
 {
        struct usb_hcd          *hcd;
+       struct usb_device       *udev = urb->dev;
        int                     retval = -EIDRM;
        unsigned long           flags;
 
@@ -1542,20 +1554,19 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
        spin_lock_irqsave(&hcd_urb_unlink_lock, flags);
        if (atomic_read(&urb->use_count) > 0) {
                retval = 0;
-               usb_get_dev(urb->dev);
+               usb_get_dev(udev);
        }
        spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags);
        if (retval == 0) {
                hcd = bus_to_hcd(urb->dev->bus);
                retval = unlink1(hcd, urb, status);
-               usb_put_dev(urb->dev);
+               if (retval == 0)
+                       retval = -EINPROGRESS;
+               else if (retval != -EIDRM && retval != -EBUSY)
+                       dev_dbg(&udev->dev, "hcd_unlink_urb %pK fail %d\n",
+                                       urb, retval);
+               usb_put_dev(udev);
        }
-
-       if (retval == 0)
-               retval = -EINPROGRESS;
-       else if (retval != -EIDRM && retval != -EBUSY)
-               dev_dbg(&urb->dev->dev, "hcd_unlink_urb %p fail %d\n",
-                               urb, retval);
        return retval;
 }
 
@@ -1634,7 +1645,7 @@ rescan:
                /* kick hcd */
                unlink1(hcd, urb, -ESHUTDOWN);
                dev_dbg (hcd->self.controller,
-                       "shutdown urb %p ep%d%s%s\n",
+                       "shutdown urb %pK ep%d%s%s\n",
                        urb, usb_endpoint_num(&ep->desc),
                        is_in ? "in" : "out",
                        ({      char *s;
@@ -1885,6 +1896,8 @@ int usb_alloc_streams(struct usb_interface *interface,
                return -EINVAL;
        if (dev->speed != USB_SPEED_SUPER)
                return -EINVAL;
+       if (dev->state < USB_STATE_CONFIGURED)
+               return -ENODEV;
 
        /* Streams only apply to bulk endpoints. */
        for (i = 0; i < num_eps; i++)
@@ -1961,8 +1974,9 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
        int             status;
        int             old_state = hcd->state;
 
-       dev_dbg(&rhdev->dev, "bus %s%s\n",
-                       (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend");
+       dev_dbg(&rhdev->dev, "bus %ssuspend, wakeup %d\n",
+                       (PMSG_IS_AUTO(msg) ? "auto-" : ""),
+                       rhdev->do_remote_wakeup);
        if (HCD_DEAD(hcd)) {
                dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "suspend");
                return 0;
@@ -1997,8 +2011,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
        int             status;
        int             old_state = hcd->state;
 
-       dev_dbg(&rhdev->dev, "usb %s%s\n",
-                       (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume");
+       dev_dbg(&rhdev->dev, "usb %sresume\n",
+                       (PMSG_IS_AUTO(msg) ? "auto-" : ""));
        if (HCD_DEAD(hcd)) {
                dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume");
                return 0;
@@ -2429,7 +2443,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
         * but drivers can override it in reset() if needed, along with
         * recording the overall controller's system wakeup capability.
         */
-       device_init_wakeup(&rhdev->dev, 1);
+       device_set_wakeup_capable(&rhdev->dev, 1);
 
        /* HCD_FLAG_RH_RUNNING doesn't matter until the root hub is
         * registered.  But since the controller can die at any time,
@@ -2451,8 +2465,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
                        && device_can_wakeup(&hcd->self.root_hub->dev))
                dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
 
-       /* enable irqs just before we start the controller */
-       if (usb_hcd_is_primary_hcd(hcd)) {
+       /* enable irqs just before we start the controller,
+        * if the BIOS provides legacy PCI irqs.
+        */
+       if (usb_hcd_is_primary_hcd(hcd) && irqnum) {
                retval = usb_hcd_request_irqs(hcd, irqnum, irqflags);
                if (retval)
                        goto err_request_irq;
@@ -2478,6 +2494,13 @@ int usb_add_hcd(struct usb_hcd *hcd,
        }
        if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
                usb_hcd_poll_rh_status(hcd);
+
+       /*
+        * Host controllers don't generate their own wakeup requests;
+        * they only forward requests from the root hub.  Therefore
+        * controllers should always be enabled for remote wakeup.
+        */
+       device_wakeup_enable(hcd->self.controller);
        return retval;
 
 error_create_attr_group: