USB: Don't fail USB3 probe on missing legacy PCI IRQ.
authorSarah Sharp <sarah.a.sharp@linux.intel.com>
Thu, 23 Feb 2012 21:20:13 +0000 (13:20 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 1 Mar 2012 00:34:27 +0000 (16:34 -0800)
commit 68d07f64b8a11a852d48d1b05b724c3e20c0d94b upstream

Intel has a PCI USB xhci host controller on a new platform. It doesn't
have a line IRQ definition in BIOS.  The Linux driver refuses to
initialize this controller, but Windows works well because it only depends
on MSI.

Actually, Linux also can work for MSI.  This patch avoids the line IRQ
checking for USB3 HCDs in usb core PCI probe.  It allows the xHCI driver
to try to enable MSI or MSI-X first.  It will fail the probe if MSI
enabling failed and there's no legacy PCI IRQ.

This patch should be backported to kernels as old as 2.6.32.

[Maintainer note: This patch is a backport of commit
68d07f64b8a11a852d48d1b05b724c3e20c0d94b "USB: Don't fail USB3 probe on
missing legacy PCI IRQ." to the 3.0 kernel.  Note, the original patch
description was wrong.  We should not back port this to kernels older
than 2.6.36, since that was the first kernel to support MSI and MSI-X
for xHCI hosts.  These systems will just not work without MSI support,
so the probe should fail on kernels older than 2.6.36.]

Signed-off-by: Alex Shi <alex.shi@intel.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.c
drivers/usb/host/xhci.c

index ce22f4a84ed0ade731c6586f6a51d01433f67d45..6c1642b382fdbdac30af6ff646a73874151782bd 100644 (file)
@@ -187,7 +187,10 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
                return -ENODEV;
        dev->current_state = PCI_D0;
 
-       if (!dev->irq) {
+       /* The xHCI driver supports MSI and MSI-X,
+        * so don't fail if the BIOS doesn't provide a legacy IRQ.
+        */
+       if (!dev->irq && (driver->flags & HCD_MASK) != HCD_USB3) {
                dev_err(&dev->dev,
                        "Found HC with no IRQ.  Check BIOS/PCI %s setup!\n",
                        pci_name(dev));
index 691d212cac4979ecb2e881ebb5fbe83144723e64..45e090850c93c78884f8e69be05ee8d0837ccb2b 100644 (file)
@@ -2435,8 +2435,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;
index 107438eca2b12a0b40e5fd0c05ea9ed7ed5c38f2..b4416d8dd481a5ab3d9ce27a9fca451f9870a48c 100644 (file)
@@ -444,6 +444,11 @@ int xhci_run(struct usb_hcd *hcd)
 
        if (ret) {
 legacy_irq:
+               if (!pdev->irq) {
+                       xhci_err(xhci, "No msi-x/msi found and "
+                                       "no IRQ in BIOS\n");
+                       return -EINVAL;
+               }
                /* fall back to legacy interrupt*/
                ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
                                        hcd->irq_descr, hcd);