diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7bf86774b1aa..583a3e330105 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -397,6 +397,45 @@ static int xhci_run_finished(struct xhci_hcd *xhci) return 0; } +static int xhci_try_enable_msi(struct usb_hcd *hcd) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); + int ret; + + /* + * Some Fresco Logic host controllers advertise MSI, but fail to + * generate interrupts. Don't even try to enable MSI. + */ + if (xhci->quirks & XHCI_BROKEN_MSI) + return 0; + + /* unregister the legacy interrupt */ + if (hcd->irq) + free_irq(hcd->irq, hcd); + hcd->irq = -1; + + ret = xhci_setup_msix(xhci); + if (ret) + /* fall back to msi*/ + ret = xhci_setup_msi(xhci); + + if (!ret) + /* hcd->irq is -1, we have MSI */ + return 0; + + /* fall back to legacy interrupt*/ + ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, + hcd->irq_descr, hcd); + if (ret) { + xhci_err(xhci, "request interrupt %d failed\n", + pdev->irq); + return ret; + } + hcd->irq = pdev->irq; + return 0; +} + /* * Start the HC after it was halted. * @@ -413,9 +452,8 @@ int xhci_run(struct usb_hcd *hcd) { u32 temp; u64 temp_64; - u32 ret; + int ret; struct xhci_hcd *xhci = hcd_to_xhci(hcd); - struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); /* Start the xHCI host controller running only after the USB 2.0 roothub * is setup. @@ -426,34 +464,10 @@ int xhci_run(struct usb_hcd *hcd) return xhci_run_finished(xhci); xhci_dbg(xhci, "xhci_run\n"); - /* unregister the legacy interrupt */ - if (hcd->irq) - free_irq(hcd->irq, hcd); - hcd->irq = -1; - /* Some Fresco Logic host controllers advertise MSI, but fail to - * generate interrupts. Don't even try to enable MSI. - */ - if (xhci->quirks & XHCI_BROKEN_MSI) - goto legacy_irq; - - ret = xhci_setup_msix(xhci); + ret = xhci_try_enable_msi(hcd); if (ret) - /* fall back to msi*/ - ret = xhci_setup_msi(xhci); - - if (ret) { -legacy_irq: - /* fall back to legacy interrupt*/ - ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, - hcd->irq_descr, hcd); - if (ret) { - xhci_err(xhci, "request interrupt %d failed\n", - pdev->irq); - return ret; - } - hcd->irq = pdev->irq; - } + return ret; #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING init_timer(&xhci->event_ring_timer);