usb: xhci: Prefer endpoint context dequeue pointer over stopped_trb
[cascardo/linux.git] / drivers / usb / core / hub.c
index 64ea219..090469e 100644 (file)
@@ -141,19 +141,27 @@ static int usb_device_supports_lpm(struct usb_device *udev)
                return 0;
        }
 
-       /* All USB 3.0 must support LPM, but we need their max exit latency
-        * information from the SuperSpeed Extended Capabilities BOS descriptor.
+       /*
+        * According to the USB 3.0 spec, all USB 3.0 devices must support LPM.
+        * However, there are some that don't, and they set the U1/U2 exit
+        * latencies to zero.
         */
        if (!udev->bos->ss_cap) {
-               dev_warn(&udev->dev, "No LPM exit latency info found.  "
-                               "Power management will be impacted.\n");
+               dev_info(&udev->dev, "No LPM exit latency info found, disabling LPM.\n");
+               return 0;
+       }
+
+       if (udev->bos->ss_cap->bU1devExitLat == 0 &&
+                       udev->bos->ss_cap->bU2DevExitLat == 0) {
+               if (udev->parent)
+                       dev_info(&udev->dev, "LPM exit latency is zeroed, disabling LPM.\n");
+               else
+                       dev_info(&udev->dev, "We don't know the algorithms for LPM for this host, disabling LPM.\n");
                return 0;
        }
-       if (udev->parent->lpm_capable)
-               return 1;
 
-       dev_warn(&udev->dev, "Parent hub missing LPM exit latency info.  "
-                       "Power management will be impacted.\n");
+       if (!udev->parent || udev->parent->lpm_capable)
+               return 1;
        return 0;
 }
 
@@ -499,7 +507,8 @@ static void led_work (struct work_struct *work)
                changed++;
        }
        if (changed)
-               schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
+               queue_delayed_work(system_power_efficient_wq,
+                               &hub->leds, LED_CYCLE_PERIOD);
 }
 
 /* use a short timeout for hub/port status fetches */
@@ -1040,8 +1049,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
                 */
                if (type == HUB_INIT) {
                        delay = hub_power_on(hub, false);
-                       PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2);
-                       schedule_delayed_work(&hub->init_work,
+                       INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
+                       queue_delayed_work(system_power_efficient_wq,
+                                       &hub->init_work,
                                        msecs_to_jiffies(delay));
 
                        /* Suppress autosuspend until init is done */
@@ -1194,8 +1204,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 
                /* Don't do a long sleep inside a workqueue routine */
                if (type == HUB_INIT2) {
-                       PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func3);
-                       schedule_delayed_work(&hub->init_work,
+                       INIT_DELAYED_WORK(&hub->init_work, hub_init_func3);
+                       queue_delayed_work(system_power_efficient_wq,
+                                       &hub->init_work,
                                        msecs_to_jiffies(delay));
                        return;         /* Continues at init3: below */
                } else {
@@ -1209,7 +1220,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
        if (status < 0)
                dev_err(hub->intfdev, "activate --> %d\n", status);
        if (hub->has_indicators && blinkenlights)
-               schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
+               queue_delayed_work(system_power_efficient_wq,
+                               &hub->leds, LED_CYCLE_PERIOD);
 
        /* Scan all ports that need attention */
        kick_khubd(hub);
@@ -1788,7 +1800,7 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
  * to one of these "claimed" ports, the program will "own" the device.
  */
 static int find_port_owner(struct usb_device *hdev, unsigned port1,
-               struct dev_state ***ppowner)
+               struct usb_dev_state ***ppowner)
 {
        struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
 
@@ -1806,10 +1818,10 @@ static int find_port_owner(struct usb_device *hdev, unsigned port1,
 
 /* In the following three functions, the caller must hold hdev's lock */
 int usb_hub_claim_port(struct usb_device *hdev, unsigned port1,
-                      struct dev_state *owner)
+                      struct usb_dev_state *owner)
 {
        int rc;
-       struct dev_state **powner;
+       struct usb_dev_state **powner;
 
        rc = find_port_owner(hdev, port1, &powner);
        if (rc)
@@ -1819,12 +1831,13 @@ int usb_hub_claim_port(struct usb_device *hdev, unsigned port1,
        *powner = owner;
        return rc;
 }
+EXPORT_SYMBOL_GPL(usb_hub_claim_port);
 
 int usb_hub_release_port(struct usb_device *hdev, unsigned port1,
-                        struct dev_state *owner)
+                        struct usb_dev_state *owner)
 {
        int rc;
-       struct dev_state **powner;
+       struct usb_dev_state **powner;
 
        rc = find_port_owner(hdev, port1, &powner);
        if (rc)
@@ -1834,8 +1847,9 @@ int usb_hub_release_port(struct usb_device *hdev, unsigned port1,
        *powner = NULL;
        return rc;
 }
+EXPORT_SYMBOL_GPL(usb_hub_release_port);
 
-void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner)
+void usb_hub_release_all_ports(struct usb_device *hdev, struct usb_dev_state *owner)
 {
        struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
        int n;
@@ -3093,9 +3107,19 @@ static int finish_port_resume(struct usb_device *udev)
         * operation is carried out here, after the port has been
         * resumed.
         */
-       if (udev->reset_resume)
+       if (udev->reset_resume) {
+               /*
+                * If the device morphs or switches modes when it is reset,
+                * we don't want to perform a reset-resume.  We'll fail the
+                * resume, which will cause a logical disconnect, and then
+                * the device will be rediscovered.
+                */
  retry_reset_resume:
-               status = usb_reset_and_verify_device(udev);
+               if (udev->quirks & USB_QUIRK_RESET)
+                       status = -ENODEV;
+               else
+                       status = usb_reset_and_verify_device(udev);
+       }
 
        /* 10.5.4.5 says be sure devices in the tree are still there.
         * For now let's assume the device didn't go crazy on resume,
@@ -3958,7 +3982,7 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
        connect_type = usb_get_hub_port_connect_type(udev->parent,
                        udev->portnum);
 
-       if ((udev->bos->ext_cap->bmAttributes & USB_BESL_SUPPORT) ||
+       if ((udev->bos->ext_cap->bmAttributes & cpu_to_le32(USB_BESL_SUPPORT)) ||
                        connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
                udev->usb2_hw_lpm_allowed = 1;
                usb_set_usb2_hardware_lpm(udev, 1);
@@ -4107,8 +4131,12 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 
                        did_new_scheme = true;
                        retval = hub_enable_device(udev);
-                       if (retval < 0)
+                       if (retval < 0) {
+                               dev_err(&udev->dev,
+                                       "hub failed to enable device, error %d\n",
+                                       retval);
                                goto fail;
+                       }
 
 #define GET_DESCRIPTOR_BUFSIZE 64
                        buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
@@ -4311,7 +4339,8 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
                /* hub LEDs are probably harder to miss than syslog */
                if (hub->has_indicators) {
                        hub->indicator[port1-1] = INDICATOR_GREEN_BLINK;
-                       schedule_delayed_work (&hub->leds, 0);
+                       queue_delayed_work(system_power_efficient_wq,
+                                       &hub->leds, 0);
                }
        }
        kfree(qual);
@@ -4540,7 +4569,9 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
                                if (hub->has_indicators) {
                                        hub->indicator[port1-1] =
                                                INDICATOR_AMBER_BLINK;
-                                       schedule_delayed_work (&hub->leds, 0);
+                                       queue_delayed_work(
+                                               system_power_efficient_wq,
+                                               &hub->leds, 0);
                                }
                                status = -ENOTCONN;     /* Don't retry */
                                goto loop_disable;
@@ -4739,6 +4770,8 @@ static void hub_events(void)
 
                /* deal with port status changes */
                for (i = 1; i <= hdev->maxchild; i++) {
+                       struct usb_device *udev = hub->ports[i - 1]->child;
+
                        if (test_bit(i, hub->busy_bits))
                                continue;
                        connect_change = test_bit(i, hub->change_bits);
@@ -4837,8 +4870,6 @@ static void hub_events(void)
                         */
                        if (hub_port_warm_reset_required(hub, portstatus)) {
                                int status;
-                               struct usb_device *udev =
-                                       hub->ports[i - 1]->child;
 
                                dev_dbg(hub_dev, "warm reset port %d\n", i);
                                if (!udev ||
@@ -4855,6 +4886,24 @@ static void hub_events(void)
                                        usb_unlock_device(udev);
                                        connect_change = 0;
                                }
+                       /*
+                        * On disconnect USB3 protocol ports transit from U0 to
+                        * SS.Inactive to Rx.Detect. If this happens a warm-
+                        * reset is not needed, but a (re)connect may happen
+                        * before khubd runs and sees the disconnect, and the
+                        * device may be an unknown state.
+                        *
+                        * If the port went through SS.Inactive without khubd
+                        * seeing it the C_LINK_STATE change flag will be set,
+                        * and we reset the dev to put it in a known state.
+                        */
+                       } else if (udev && hub_is_superspeed(hub->hdev) &&
+                                  (portchange & USB_PORT_STAT_C_LINK_STATE) &&
+                                  (portstatus & USB_PORT_STAT_CONNECTION)) {
+                               usb_lock_device(udev);
+                               usb_reset_device(udev);
+                               usb_unlock_device(udev);
+                               connect_change = 0;
                        }
 
                        if (connect_change)
@@ -5112,7 +5161,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
        struct usb_hcd                  *hcd = bus_to_hcd(udev->bus);
        struct usb_device_descriptor    descriptor = udev->descriptor;
        struct usb_host_bos             *bos;
-       int                             i, ret = 0;
+       int                             i, j, ret = 0;
        int                             port1 = udev->portnum;
 
        if (udev->state == USB_STATE_NOTATTACHED ||
@@ -5238,6 +5287,9 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
                                ret);
                        goto re_enumerate;
                }
+               /* Resetting also frees any allocated streams */
+               for (j = 0; j < intf->cur_altsetting->desc.bNumEndpoints; j++)
+                       intf->cur_altsetting->endpoint[j].streams = 0;
        }
 
 done:
@@ -5340,10 +5392,11 @@ int usb_reset_device(struct usb_device *udev)
                                else if (cintf->condition ==
                                                USB_INTERFACE_BOUND)
                                        rebind = 1;
+                               if (rebind)
+                                       cintf->needs_binding = 1;
                        }
-                       if (ret == 0 && rebind)
-                               usb_rebind_intf(cintf);
                }
+               usb_unbind_and_rebind_marked_interfaces(udev);
        }
 
        usb_autosuspend_device(udev);