Merge remote-tracking branch 'origin/develop-3.0' into develop-3.0-jb
[firefly-linux-kernel-4.4.55.git] / drivers / usb / core / hcd.c
old mode 100644 (file)
new mode 100755 (executable)
index 0ec8c12..cc8b9c5
@@ -38,7 +38,6 @@
 #include <asm/unaligned.h>
 #include <linux/platform_device.h>
 #include <linux/workqueue.h>
-#include <linux/pm_runtime.h>
 
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
@@ -298,7 +297,7 @@ static const u8 ss_rh_config_descriptor[] = {
        /* one configuration */
        0x09,       /*  __u8  bLength; */
        0x02,       /*  __u8  bDescriptorType; Configuration */
-       0x19, 0x00, /*  __le16 wTotalLength; FIXME */
+       0x1f, 0x00, /*  __le16 wTotalLength; */
        0x01,       /*  __u8  bNumInterfaces; (1) */
        0x01,       /*  __u8  bConfigurationValue; */
        0x00,       /*  __u8  iConfiguration; */
@@ -328,11 +327,14 @@ static const u8 ss_rh_config_descriptor[] = {
                    /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8)
                     * see hub.c:hub_configure() for details. */
        (USB_MAXCHILDREN + 1 + 7) / 8, 0x00,
-       0x0c        /*  __u8  ep_bInterval; (256ms -- usb 2.0 spec) */
-       /*
-        * All 3.0 hubs should have an endpoint companion descriptor,
-        * but we're ignoring that for now.  FIXME?
-        */
+       0x0c,       /*  __u8  ep_bInterval; (256ms -- usb 2.0 spec) */
+
+       /* one SuperSpeed endpoint companion descriptor */
+       0x06,        /* __u8 ss_bLength */
+       0x30,        /* __u8 ss_bDescriptorType; SuperSpeed EP Companion */
+       0x00,        /* __u8 ss_bMaxBurst; allows 1 TX between ACKs */
+       0x00,        /* __u8 ss_bmAttributes; 1 packet per service interval */
+       0x02, 0x00   /* __le16 ss_wBytesPerInterval; 15 bits for max 15 ports */
 };
 
 /*-------------------------------------------------------------------------*/
@@ -505,7 +507,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
        case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
                switch (wValue & 0xff00) {
                case USB_DT_DEVICE << 8:
-                       switch (hcd->driver->flags & HCD_MASK) {
+                       switch (hcd->speed) {
                        case HCD_USB3:
                                bufp = usb3_rh_dev_descriptor;
                                break;
@@ -523,7 +525,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
                                patch_protocol = 1;
                        break;
                case USB_DT_CONFIG << 8:
-                       switch (hcd->driver->flags & HCD_MASK) {
+                       switch (hcd->speed) {
                        case HCD_USB3:
                                bufp = ss_rh_config_descriptor;
                                len = sizeof ss_rh_config_descriptor;
@@ -698,7 +700,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
        /* The USB 2.0 spec says 256 ms.  This is close enough and won't
         * exceed that limit if HZ is 100. The math is more clunky than
         * maybe expected, this is to make sure that all timers for USB devices
-        * fire at the same time to give the CPU a break inbetween */
+        * fire at the same time to give the CPU a break in between */
        if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) :
                        (length == 0 && hcd->status_urb != NULL))
                mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
@@ -984,7 +986,7 @@ static int register_root_hub(struct usb_hcd *hcd)
                spin_unlock_irq (&hcd_root_hub_lock);
 
                /* Did the HC die before the root hub was registered? */
-               if (hcd->state == HC_STATE_HALT)
+               if (HCD_DEAD(hcd))
                        usb_hc_died (hcd);      /* This time clean up */
        }
 
@@ -1090,13 +1092,10 @@ int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb)
         * Check the host controller's state and add the URB to the
         * endpoint's queue.
         */
-       switch (hcd->state) {
-       case HC_STATE_RUNNING:
-       case HC_STATE_RESUMING:
+       if (HCD_RH_RUNNING(hcd)) {
                urb->unlinked = 0;
                list_add_tail(&urb->urb_list, &urb->ep->urb_list);
-               break;
-       default:
+       } else {
                rc = -ESHUTDOWN;
                goto done;
        }
@@ -1154,6 +1153,8 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
                dev_warn(hcd->self.controller, "Unlink after no-IRQ?  "
                        "Controller is probably using the wrong IRQ.\n");
                set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+               if (hcd->shared_hcd)
+                       set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
        }
 
        return 0;
@@ -1263,18 +1264,8 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle,
        *dma_handle = 0;
 }
 
-static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+void usb_hcd_unmap_urb_setup_for_dma(struct usb_hcd *hcd, struct urb *urb)
 {
-       if (hcd->driver->unmap_urb_for_dma)
-               hcd->driver->unmap_urb_for_dma(hcd, urb);
-       else
-               usb_hcd_unmap_urb_for_dma(hcd, urb);
-}
-
-void usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
-{
-       enum dma_data_direction dir;
-
        if (urb->transfer_flags & URB_SETUP_MAP_SINGLE)
                dma_unmap_single(hcd->self.controller,
                                urb->setup_dma,
@@ -1287,6 +1278,25 @@ void usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
                                sizeof(struct usb_ctrlrequest),
                                DMA_TO_DEVICE);
 
+       /* Make it safe to call this routine more than once */
+       urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL);
+}
+EXPORT_SYMBOL_GPL(usb_hcd_unmap_urb_setup_for_dma);
+
+static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+       if (hcd->driver->unmap_urb_for_dma)
+               hcd->driver->unmap_urb_for_dma(hcd, urb);
+       else
+               usb_hcd_unmap_urb_for_dma(hcd, urb);
+}
+
+void usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+       enum dma_data_direction dir;
+
+       usb_hcd_unmap_urb_setup_for_dma(hcd, urb);
+
        dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
        if (urb->transfer_flags & URB_DMA_MAP_SG)
                dma_unmap_sg(hcd->self.controller,
@@ -1311,8 +1321,7 @@ void usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
                                dir);
 
        /* Make it safe to call this routine more than once */
-       urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
-                       URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
+       urb->transfer_flags &= ~(URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
                        URB_DMA_MAP_SINGLE | URB_MAP_LOCAL);
 }
 EXPORT_SYMBOL_GPL(usb_hcd_unmap_urb_for_dma);
@@ -1339,6 +1348,8 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
         */
 
        if (usb_endpoint_xfer_control(&urb->ep->desc)) {
+               if (hcd->self.uses_pio_for_control)
+                       return ret;
                if (hcd->self.uses_dma) {
                        urb->setup_dma = dma_map_single(
                                        hcd->self.controller,
@@ -1376,11 +1387,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(
@@ -1572,8 +1582,8 @@ void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
 
        /* pass ownership to the completion handler */
        urb->status = status;
-       urb->complete (urb);
        atomic_dec (&urb->use_count);
+       urb->complete (urb);
        if (unlikely(atomic_read(&urb->reject)))
                wake_up (&usb_kill_urb_queue);
        usb_put_urb (urb);
@@ -1753,6 +1763,8 @@ int usb_hcd_alloc_bandwidth(struct usb_device *udev,
                struct usb_interface *iface = usb_ifnum_to_if(udev,
                                cur_alt->desc.bInterfaceNumber);
 
+               if (!iface)
+                       return -EINVAL;
                if (iface->resetting_device) {
                        /*
                         * The USB core just reset the device, so the xHCI host
@@ -1897,7 +1909,7 @@ void usb_free_streams(struct usb_interface *interface,
 
        /* Streams only apply to bulk endpoints. */
        for (i = 0; i < num_eps; i++)
-               if (!usb_endpoint_xfer_bulk(&eps[i]->desc))
+               if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc))
                        return;
 
        hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
@@ -1922,7 +1934,7 @@ int usb_hcd_get_frame_number (struct usb_device *udev)
 {
        struct usb_hcd  *hcd = bus_to_hcd(udev->bus);
 
-       if (!HC_IS_RUNNING (hcd->state))
+       if (!HCD_RH_RUNNING(hcd))
                return -ESHUTDOWN;
        return hcd->driver->get_frame_number (hcd);
 }
@@ -1939,10 +1951,16 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
 
        dev_dbg(&rhdev->dev, "bus %s%s\n",
                        (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend");
+       if (HCD_DEAD(hcd)) {
+               dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "suspend");
+               return 0;
+       }
+
        if (!hcd->driver->bus_suspend) {
                printk("%s,error,everest\n",__func__);
                status = -ENOENT;
        } else {
+               clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
                hcd->state = HC_STATE_QUIESCING;
                status = hcd->driver->bus_suspend(hcd);
        }
@@ -1950,7 +1968,12 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
                usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
                hcd->state = HC_STATE_SUSPENDED;
        } else {
-               hcd->state = old_state;
+               spin_lock_irq(&hcd_root_hub_lock);
+               if (!HCD_DEAD(hcd)) {
+                       set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+                       hcd->state = old_state;
+               }
+               spin_unlock_irq(&hcd_root_hub_lock);
                dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
                                "suspend", status);
        }
@@ -1965,21 +1988,30 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
 
        dev_dbg(&rhdev->dev, "usb %s%s\n",
                        (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume");
-       clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
+       if (HCD_DEAD(hcd)) {
+               dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume");
+               return 0;
+       }
        if (!hcd->driver->bus_resume)
                return -ENOENT;
-       if (hcd->state == HC_STATE_RUNNING)
+       if (HCD_RH_RUNNING(hcd))
                return 0;
 
        hcd->state = HC_STATE_RESUMING;
        status = hcd->driver->bus_resume(hcd);
+       clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
        if (status == 0) {
                /* TRSMRCY = 10 msec */
                msleep(10);
-               usb_set_device_state(rhdev, rhdev->actconfig
-                               ? USB_STATE_CONFIGURED
-                               : USB_STATE_ADDRESS);
-               hcd->state = HC_STATE_RUNNING;
+               spin_lock_irq(&hcd_root_hub_lock);
+               if (!HCD_DEAD(hcd)) {
+                       usb_set_device_state(rhdev, rhdev->actconfig
+                                       ? USB_STATE_CONFIGURED
+                                       : USB_STATE_ADDRESS);
+                       set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+                       hcd->state = HC_STATE_RUNNING;
+               }
+               spin_unlock_irq(&hcd_root_hub_lock);
        } else {
                hcd->state = old_state;
                dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
@@ -2090,15 +2122,14 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
         */
        local_irq_save(flags);
 
-       if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) {
+       if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) {
                rc = IRQ_NONE;
        } else if (hcd->driver->irq(hcd) == IRQ_NONE) {
                rc = IRQ_NONE;
        } else {
                set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
-
-               if (unlikely(hcd->state == HC_STATE_HALT))
-                       usb_hc_died(hcd);
+               if (hcd->shared_hcd)
+                       set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
                rc = IRQ_HANDLED;
        }
 
@@ -2115,7 +2146,9 @@ EXPORT_SYMBOL_GPL(usb_hcd_irq);
  *
  * This is called by bus glue to report a USB host controller that died
  * while operations may still have been pending.  It's called automatically
- * by the PCI glue, so only glue for non-PCI busses should need to call it. 
+ * by the PCI glue, so only glue for non-PCI busses should need to call it.
+ *
+ * Only call this function with the primary HCD.
  */
 void usb_hc_died (struct usb_hcd *hcd)
 {
@@ -2124,6 +2157,8 @@ void usb_hc_died (struct usb_hcd *hcd)
        dev_err (hcd->self.controller, "HC died; cleaning up\n");
 
        spin_lock_irqsave (&hcd_root_hub_lock, flags);
+       clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+       set_bit(HCD_FLAG_DEAD, &hcd->flags);
        if (hcd->rh_registered) {
                clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 
@@ -2132,17 +2167,31 @@ void usb_hc_died (struct usb_hcd *hcd)
                                USB_STATE_NOTATTACHED);
                usb_kick_khubd (hcd->self.root_hub);
        }
+       if (usb_hcd_is_primary_hcd(hcd) && hcd->shared_hcd) {
+               hcd = hcd->shared_hcd;
+               if (hcd->rh_registered) {
+                       clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+
+                       /* make khubd clean up old urbs and devices */
+                       usb_set_device_state(hcd->self.root_hub,
+                                       USB_STATE_NOTATTACHED);
+                       usb_kick_khubd(hcd->self.root_hub);
+               }
+       }
        spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
+       /* Make sure that the other roothub is also deallocated. */
 }
 EXPORT_SYMBOL_GPL (usb_hc_died);
 
 /*-------------------------------------------------------------------------*/
 
 /**
- * usb_create_hcd - create and initialize an HCD structure
+ * usb_create_shared_hcd - create and initialize an HCD structure
  * @driver: HC driver that will use this hcd
  * @dev: device for this HC, stored in hcd->self.controller
  * @bus_name: value to store in hcd->self.bus_name
+ * @primary_hcd: a pointer to the usb_hcd structure that is sharing the
+ *              PCI device.  Only allocate certain resources for the primary HCD
  * Context: !in_interrupt()
  *
  * Allocate a struct usb_hcd, with extra space at the end for the
@@ -2151,8 +2200,9 @@ EXPORT_SYMBOL_GPL (usb_hc_died);
  *
  * If memory is unavailable, returns NULL.
  */
-struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
-               struct device *dev, const char *bus_name)
+struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
+               struct device *dev, const char *bus_name,
+               struct usb_hcd *primary_hcd)
 {
        struct usb_hcd *hcd;
 
@@ -2161,7 +2211,24 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
                dev_dbg (dev, "hcd alloc failed\n");
                return NULL;
        }
-       dev_set_drvdata(dev, hcd);
+       if (primary_hcd == NULL) {
+               hcd->bandwidth_mutex = kmalloc(sizeof(*hcd->bandwidth_mutex),
+                               GFP_KERNEL);
+               if (!hcd->bandwidth_mutex) {
+                       kfree(hcd);
+                       dev_dbg(dev, "hcd bandwidth mutex alloc failed\n");
+                       return NULL;
+               }
+               mutex_init(hcd->bandwidth_mutex);
+               dev_set_drvdata(dev, hcd);
+       } else {
+               hcd->bandwidth_mutex = primary_hcd->bandwidth_mutex;
+               hcd->primary_hcd = primary_hcd;
+               primary_hcd->primary_hcd = primary_hcd;
+               hcd->shared_hcd = primary_hcd;
+               primary_hcd->shared_hcd = hcd;
+       }
+
        kref_init(&hcd->kref);
 
        usb_bus_init(&hcd->self);
@@ -2175,19 +2242,53 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
 #ifdef CONFIG_USB_SUSPEND
        INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
 #endif
-       mutex_init(&hcd->bandwidth_mutex);
 
        hcd->driver = driver;
+       hcd->speed = driver->flags & HCD_MASK;
        hcd->product_desc = (driver->product_desc) ? driver->product_desc :
                        "USB Host Controller";
        return hcd;
 }
+EXPORT_SYMBOL_GPL(usb_create_shared_hcd);
+
+/**
+ * usb_create_hcd - create and initialize an HCD structure
+ * @driver: HC driver that will use this hcd
+ * @dev: device for this HC, stored in hcd->self.controller
+ * @bus_name: value to store in hcd->self.bus_name
+ * Context: !in_interrupt()
+ *
+ * Allocate a struct usb_hcd, with extra space at the end for the
+ * HC driver's private data.  Initialize the generic members of the
+ * hcd structure.
+ *
+ * If memory is unavailable, returns NULL.
+ */
+struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
+               struct device *dev, const char *bus_name)
+{
+       return usb_create_shared_hcd(driver, dev, bus_name, NULL);
+}
 EXPORT_SYMBOL_GPL(usb_create_hcd);
 
+/*
+ * Roothubs that share one PCI device must also share the bandwidth mutex.
+ * Don't deallocate the bandwidth_mutex until the last shared usb_hcd is
+ * deallocated.
+ *
+ * Make sure to only deallocate the bandwidth_mutex when the primary HCD is
+ * freed.  When hcd_release() is called for the non-primary HCD, set the
+ * primary_hcd's shared_hcd pointer to null (since the non-primary HCD will be
+ * freed shortly).
+ */
 static void hcd_release (struct kref *kref)
 {
        struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
 
+       if (usb_hcd_is_primary_hcd(hcd))
+               kfree(hcd->bandwidth_mutex);
+       else
+               hcd->shared_hcd->shared_hcd = NULL;
        kfree(hcd);
 }
 
@@ -2206,6 +2307,54 @@ void usb_put_hcd (struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL_GPL(usb_put_hcd);
 
+int usb_hcd_is_primary_hcd(struct usb_hcd *hcd)
+{
+       if (!hcd->primary_hcd)
+               return 1;
+       return hcd == hcd->primary_hcd;
+}
+EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd);
+
+static int usb_hcd_request_irqs(struct usb_hcd *hcd,
+               unsigned int irqnum, unsigned long irqflags)
+{
+       int retval;
+
+       if (hcd->driver->irq) {
+
+               /* IRQF_DISABLED doesn't work as advertised when used together
+                * with IRQF_SHARED. As usb_hcd_irq() will always disable
+                * interrupts we can remove it here.
+                */
+               if (irqflags & IRQF_SHARED)
+                       irqflags &= ~IRQF_DISABLED;
+
+               snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
+                               hcd->driver->description, hcd->self.busnum);
+               retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
+                               hcd->irq_descr, hcd);
+               if (retval != 0) {
+                       dev_err(hcd->self.controller,
+                                       "request interrupt %d failed\n",
+                                       irqnum);
+                       return retval;
+               }
+               hcd->irq = irqnum;
+               dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum,
+                               (hcd->driver->flags & HCD_MEMORY) ?
+                                       "io mem" : "io base",
+                                       (unsigned long long)hcd->rsrc_start);
+       } else {
+               hcd->irq = -1;
+               if (hcd->rsrc_start)
+                       dev_info(hcd->self.controller, "%s 0x%08llx\n",
+                                       (hcd->driver->flags & HCD_MEMORY) ?
+                                       "io mem" : "io base",
+                                       (unsigned long long)hcd->rsrc_start);
+       }
+       return 0;
+}
+
 /**
  * usb_add_hcd - finish generic HCD structure initialization and register
  * @hcd: the usb_hcd structure to initialize
@@ -2246,7 +2395,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
        }
        hcd->self.root_hub = rhdev;
 
-       switch (hcd->driver->flags & HCD_MASK) {
+       switch (hcd->speed) {
        case HCD_USB11:
                rhdev->speed = USB_SPEED_FULL;
                break;
@@ -2257,6 +2406,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
                rhdev->speed = USB_SPEED_SUPER;
                break;
        default:
+               retval = -EINVAL;
                goto err_set_rh_speed;
        }
 
@@ -2266,6 +2416,12 @@ int usb_add_hcd(struct usb_hcd *hcd,
         */
        device_init_wakeup(&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,
+        * let's initialize the flag before touching the hardware.
+        */
+       set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+
        /* "reset" is misnamed; its role is now one-time init. the controller
         * should already have been reset (and boot firmware kicked off etc).
         */
@@ -2280,39 +2436,18 @@ 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 (hcd->driver->irq) {
-
-               /* IRQF_DISABLED doesn't work as advertised when used together
-                * with IRQF_SHARED. As usb_hcd_irq() will always disable
-                * interrupts we can remove it here.
-                */
-               if (irqflags & IRQF_SHARED)
-                       irqflags &= ~IRQF_DISABLED;
-
-               snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
-                               hcd->driver->description, hcd->self.busnum);
-               if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
-                               hcd->irq_descr, hcd)) != 0) {
-                       dev_err(hcd->self.controller,
-                                       "request interrupt %d failed\n", irqnum);
+       /* 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;
-               }
-               hcd->irq = irqnum;
-               dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum,
-                               (hcd->driver->flags & HCD_MEMORY) ?
-                                       "io mem" : "io base",
-                                       (unsigned long long)hcd->rsrc_start);
-       } else {
-               hcd->irq = -1;
-               if (hcd->rsrc_start)
-                       dev_info(hcd->self.controller, "%s 0x%08llx\n",
-                                       (hcd->driver->flags & HCD_MEMORY) ?
-                                       "io mem" : "io base",
-                                       (unsigned long long)hcd->rsrc_start);
        }
 
-       if ((retval = hcd->driver->start(hcd)) < 0) {
+       hcd->state = HC_STATE_RUNNING;
+       retval = hcd->driver->start(hcd);
+       if (retval < 0) {
                dev_err(hcd->self.controller, "startup error %d\n", retval);
                goto err_hcd_driver_start;
        }
@@ -2333,6 +2468,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
        return retval;
 
 error_create_attr_group:
+       clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
        if (HC_IS_RUNNING(hcd->state))
                hcd->state = HC_STATE_QUIESCING;
        spin_lock_irq(&hcd_root_hub_lock);
@@ -2354,7 +2490,7 @@ err_register_root_hub:
        clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
        del_timer_sync(&hcd->rh_timer);
 err_hcd_driver_start:
-       if (hcd->irq >= 0)
+       if (usb_hcd_is_primary_hcd(hcd) && hcd->irq >= 0)
                free_irq(irqnum, hcd);
 err_request_irq:
 err_hcd_driver_setup:
@@ -2385,6 +2521,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
        usb_get_dev(rhdev);
        sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group);
 
+       clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
        if (HC_IS_RUNNING (hcd->state))
                hcd->state = HC_STATE_QUIESCING;
 
@@ -2417,8 +2554,10 @@ void usb_remove_hcd(struct usb_hcd *hcd)
        clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
        del_timer_sync(&hcd->rh_timer);
 
-       if (hcd->irq >= 0)
-               free_irq(hcd->irq, hcd);
+       if (usb_hcd_is_primary_hcd(hcd)) {
+               if (hcd->irq >= 0)
+                       free_irq(hcd->irq, hcd);
+       }
 
        usb_put_dev(hcd->self.root_hub);
        usb_deregister_bus(&hcd->self);