Kernel bump from 4.1.3-rt to 4.1.7-rt.
[kvmfornfv.git] / kernel / drivers / usb / core / hub.c
index 3b71516..1e9a8c9 100644 (file)
@@ -122,7 +122,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev)
        return usb_get_intfdata(hdev->actconfig->interface[0]);
 }
 
-static int usb_device_supports_lpm(struct usb_device *udev)
+int usb_device_supports_lpm(struct usb_device *udev)
 {
        /* USB 2.1 (and greater) devices indicate LPM support through
         * their USB 2.0 Extended Capabilities BOS descriptor.
@@ -2616,9 +2616,6 @@ static bool use_new_scheme(struct usb_device *udev, int retry)
        return USE_NEW_SCHEME(retry);
 }
 
-static int hub_port_reset(struct usb_hub *hub, int port1,
-                       struct usb_device *udev, unsigned int delay, bool warm);
-
 /* Is a USB 3.0 port in the Inactive or Compliance Mode state?
  * Port worm reset is required to recover
  */
@@ -2706,44 +2703,6 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
        return 0;
 }
 
-static void hub_port_finish_reset(struct usb_hub *hub, int port1,
-                       struct usb_device *udev, int *status)
-{
-       switch (*status) {
-       case 0:
-               /* TRSTRCY = 10 ms; plus some extra */
-               msleep(10 + 40);
-               if (udev) {
-                       struct usb_hcd *hcd = bus_to_hcd(udev->bus);
-
-                       update_devnum(udev, 0);
-                       /* The xHC may think the device is already reset,
-                        * so ignore the status.
-                        */
-                       if (hcd->driver->reset_device)
-                               hcd->driver->reset_device(hcd, udev);
-               }
-               /* FALL THROUGH */
-       case -ENOTCONN:
-       case -ENODEV:
-               usb_clear_port_feature(hub->hdev,
-                               port1, USB_PORT_FEAT_C_RESET);
-               if (hub_is_superspeed(hub->hdev)) {
-                       usb_clear_port_feature(hub->hdev, port1,
-                                       USB_PORT_FEAT_C_BH_PORT_RESET);
-                       usb_clear_port_feature(hub->hdev, port1,
-                                       USB_PORT_FEAT_C_PORT_LINK_STATE);
-                       usb_clear_port_feature(hub->hdev, port1,
-                                       USB_PORT_FEAT_C_CONNECTION);
-               }
-               if (udev)
-                       usb_set_device_state(udev, *status
-                                       ? USB_STATE_NOTATTACHED
-                                       : USB_STATE_DEFAULT);
-               break;
-       }
-}
-
 /* Handle port reset and port warm(BH) reset (for USB3 protocol ports) */
 static int hub_port_reset(struct usb_hub *hub, int port1,
                        struct usb_device *udev, unsigned int delay, bool warm)
@@ -2767,13 +2726,10 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
                 * If the caller hasn't explicitly requested a warm reset,
                 * double check and see if one is needed.
                 */
-               status = hub_port_status(hub, port1,
-                                       &portstatus, &portchange);
-               if (status < 0)
-                       goto done;
-
-               if (hub_port_warm_reset_required(hub, port1, portstatus))
-                       warm = true;
+               if (hub_port_status(hub, port1, &portstatus, &portchange) == 0)
+                       if (hub_port_warm_reset_required(hub, port1,
+                                                       portstatus))
+                               warm = true;
        }
        clear_bit(port1, hub->warm_reset_bits);
 
@@ -2799,11 +2755,19 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
 
                /* Check for disconnect or reset */
                if (status == 0 || status == -ENOTCONN || status == -ENODEV) {
-                       hub_port_finish_reset(hub, port1, udev, &status);
+                       usb_clear_port_feature(hub->hdev, port1,
+                                       USB_PORT_FEAT_C_RESET);
 
                        if (!hub_is_superspeed(hub->hdev))
                                goto done;
 
+                       usb_clear_port_feature(hub->hdev, port1,
+                                       USB_PORT_FEAT_C_BH_PORT_RESET);
+                       usb_clear_port_feature(hub->hdev, port1,
+                                       USB_PORT_FEAT_C_PORT_LINK_STATE);
+                       usb_clear_port_feature(hub->hdev, port1,
+                                       USB_PORT_FEAT_C_CONNECTION);
+
                        /*
                         * If a USB 3.0 device migrates from reset to an error
                         * state, re-issue the warm reset.
@@ -2836,6 +2800,26 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
        dev_err(&port_dev->dev, "Cannot enable. Maybe the USB cable is bad?\n");
 
 done:
+       if (status == 0) {
+               /* TRSTRCY = 10 ms; plus some extra */
+               msleep(10 + 40);
+               if (udev) {
+                       struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
+                       update_devnum(udev, 0);
+                       /* The xHC may think the device is already reset,
+                        * so ignore the status.
+                        */
+                       if (hcd->driver->reset_device)
+                               hcd->driver->reset_device(hcd, udev);
+
+                       usb_set_device_state(udev, USB_STATE_DEFAULT);
+               }
+       } else {
+               if (udev)
+                       usb_set_device_state(udev, USB_STATE_NOTATTACHED);
+       }
+
        if (!hub_is_superspeed(hub->hdev))
                up_read(&ehci_cf_port_reset_rwsem);