s390/appldata: restore missing init_virt_timer()
[deliverable/linux.git] / drivers / usb / core / hub.c
index bd9dc3504b5149b2ff5091d67bb514a92cbc0a88..babba885978d11e1ba4ece32373ba38a962c3f64 100644 (file)
 
 #include "hub.h"
 
-/* if we are in debug mode, always announce new devices */
-#ifdef DEBUG
-#ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES
-#define CONFIG_USB_ANNOUNCE_NEW_DEVICES
-#endif
-#endif
-
 #define USB_VENDOR_GENESYS_LOGIC               0x05e3
 #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND       0x01
 
@@ -1154,7 +1147,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
                        /* Tell khubd to disconnect the device or
                         * check for a new connection
                         */
-                       if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
+                       if (udev || (portstatus & USB_PORT_STAT_CONNECTION) ||
+                           (portstatus & USB_PORT_STAT_OVERCURRENT))
                                set_bit(port1, hub->change_bits);
 
                } else if (portstatus & USB_PORT_STAT_ENABLE) {
@@ -1607,7 +1601,7 @@ static void hub_disconnect(struct usb_interface *intf)
 {
        struct usb_hub *hub = usb_get_intfdata(intf);
        struct usb_device *hdev = interface_to_usbdev(intf);
-       int i;
+       int port1;
 
        /* Take the hub off the event list and don't let it be added again */
        spin_lock_irq(&hub_event_lock);
@@ -1622,11 +1616,15 @@ static void hub_disconnect(struct usb_interface *intf)
        hub->error = 0;
        hub_quiesce(hub, HUB_DISCONNECT);
 
-       usb_set_intfdata (intf, NULL);
+       /* Avoid races with recursively_mark_NOTATTACHED() */
+       spin_lock_irq(&device_state_lock);
+       port1 = hdev->maxchild;
+       hdev->maxchild = 0;
+       usb_set_intfdata(intf, NULL);
+       spin_unlock_irq(&device_state_lock);
 
-       for (i = 0; i < hdev->maxchild; i++)
-               usb_hub_remove_port_device(hub, i + 1);
-       hub->hdev->maxchild = 0;
+       for (; port1 > 0; --port1)
+               usb_hub_remove_port_device(hub, port1);
 
        if (hub->hdev->speed == USB_SPEED_HIGH)
                highspeed_hubs--;
@@ -2235,17 +2233,13 @@ static int usb_enumerate_device(struct usb_device *udev)
                        return err;
                }
        }
-       if (udev->wusb == 1 && udev->authorized == 0) {
-               udev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
-               udev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
-               udev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
-       } else {
-               /* read the standard strings and cache them if present */
-               udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
-               udev->manufacturer = usb_cache_string(udev,
-                                                     udev->descriptor.iManufacturer);
-               udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
-       }
+
+       /* read the standard strings and cache them if present */
+       udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
+       udev->manufacturer = usb_cache_string(udev,
+                                             udev->descriptor.iManufacturer);
+       udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
+
        err = usb_enumerate_device_otg(udev);
        if (err < 0)
                return err;
@@ -2427,16 +2421,6 @@ int usb_deauthorize_device(struct usb_device *usb_dev)
        usb_dev->authorized = 0;
        usb_set_configuration(usb_dev, -1);
 
-       kfree(usb_dev->product);
-       usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
-       kfree(usb_dev->manufacturer);
-       usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
-       kfree(usb_dev->serial);
-       usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
-
-       usb_destroy_configuration(usb_dev);
-       usb_dev->descriptor.bNumConfigurations = 0;
-
 out_unauthorized:
        usb_unlock_device(usb_dev);
        return 0;
@@ -2464,17 +2448,7 @@ int usb_authorize_device(struct usb_device *usb_dev)
                goto error_device_descriptor;
        }
 
-       kfree(usb_dev->product);
-       usb_dev->product = NULL;
-       kfree(usb_dev->manufacturer);
-       usb_dev->manufacturer = NULL;
-       kfree(usb_dev->serial);
-       usb_dev->serial = NULL;
-
        usb_dev->authorized = 1;
-       result = usb_enumerate_device(usb_dev);
-       if (result < 0)
-               goto error_enumerate;
        /* Choose and set the configuration.  This registers the interfaces
         * with the driver core and lets interface drivers bind to them.
         */
@@ -2490,7 +2464,6 @@ int usb_authorize_device(struct usb_device *usb_dev)
        }
        dev_info(&usb_dev->dev, "authorized to connect\n");
 
-error_enumerate:
 error_device_descriptor:
        usb_autosuspend_device(usb_dev);
 error_autoresume:
@@ -2523,10 +2496,25 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
 #define HUB_LONG_RESET_TIME    200
 #define HUB_RESET_TIMEOUT      800
 
+/*
+ * "New scheme" enumeration causes an extra state transition to be
+ * exposed to an xhci host and causes USB3 devices to receive control
+ * commands in the default state.  This has been seen to cause
+ * enumeration failures, so disable this enumeration scheme for USB3
+ * devices.
+ */
+static bool use_new_scheme(struct usb_device *udev, int retry)
+{
+       if (udev->speed == USB_SPEED_SUPER)
+               return false;
+
+       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 Complinance Mode state?
+/* Is a USB 3.0 port in the Inactive or Compliance Mode state?
  * Port worm reset is required to recover
  */
 static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus)
@@ -3334,7 +3322,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 
                udev = hub->ports[port1 - 1]->child;
                if (udev && udev->can_submit) {
-                       dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
+                       dev_warn(&intf->dev, "port %d not suspended yet\n",
+                                       port1);
                        if (PMSG_IS_AUTO(msg))
                                return -EBUSY;
                }
@@ -3981,6 +3970,20 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
        }
 }
 
+static int hub_enable_device(struct usb_device *udev)
+{
+       struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
+       if (!hcd->driver->enable_device)
+               return 0;
+       if (udev->state == USB_STATE_ADDRESS)
+               return 0;
+       if (udev->state != USB_STATE_DEFAULT)
+               return -EINVAL;
+
+       return hcd->driver->enable_device(hcd, udev);
+}
+
 /* Reset device, (re)assign address, get device descriptor.
  * Device connection must be stable, no more debouncing needed.
  * Returns device in USB_STATE_ADDRESS, except on error.
@@ -4093,7 +4096,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
         * this area, and this is how Linux has done it for ages.
         * Change it cautiously.
         *
-        * NOTE:  If USE_NEW_SCHEME() is true we will start by issuing
+        * NOTE:  If use_new_scheme() is true we will start by issuing
         * a 64-byte GET_DESCRIPTOR request.  This is what Windows does,
         * so it may help with some non-standards-compliant devices.
         * Otherwise we start with SET_ADDRESS and then try to read the
@@ -4101,10 +4104,17 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
         * value.
         */
        for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
-               if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) {
+               bool did_new_scheme = false;
+
+               if (use_new_scheme(udev, retry_counter)) {
                        struct usb_device_descriptor *buf;
                        int r = 0;
 
+                       did_new_scheme = true;
+                       retval = hub_enable_device(udev);
+                       if (retval < 0)
+                               goto fail;
+
 #define GET_DESCRIPTOR_BUFSIZE 64
                        buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
                        if (!buf) {
@@ -4193,7 +4203,11 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
                         *  - read ep0 maxpacket even for high and low speed,
                         */
                        msleep(10);
-                       if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3))
+                       /* use_new_scheme() checks the speed which may have
+                        * changed since the initial look so we cache the result
+                        * in did_new_scheme
+                        */
+                       if (did_new_scheme)
                                break;
                }
 
@@ -4900,7 +4914,7 @@ static void hub_events(void)
 
 static int hub_thread(void *__unused)
 {
-       /* khubd needs to be freezable to avoid intefering with USB-PERSIST
+       /* khubd needs to be freezable to avoid interfering with USB-PERSIST
         * port handover.  Otherwise it might see that a full-speed device
         * was gone before the EHCI controller had handed its port over to
         * the companion full-speed controller.
This page took 0.027873 seconds and 5 git commands to generate.