diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2011-09-23 14:19:58 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-09-26 15:51:12 -0700 |
commit | 421aa841a134f6a743111cf44d0c6d3b45e3cf8c (patch) | |
tree | 01be6ebd0ad752bac77c3b432cd3ee4b0050b4a8 /drivers/usb/host/xhci.c | |
parent | 3fd1ec58734e38a3f48776b6831ad0279d92d094 (diff) | |
download | linux-421aa841a134f6a743111cf44d0c6d3b45e3cf8c.tar.gz linux-421aa841a134f6a743111cf44d0c6d3b45e3cf8c.tar.bz2 linux-421aa841a134f6a743111cf44d0c6d3b45e3cf8c.zip |
usb/xhci: hide MSI code behind PCI bars
The MSI related fuctionality requires a few structs which are not
available if CONFIG_PCI is not enabled. This is a prepartion to allow
xhci be built without CONFIG_PCI set.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r-- | drivers/usb/host/xhci.c | 160 |
1 files changed, 98 insertions, 62 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 583a3e330105..a8c3e8a34d26 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -175,28 +175,19 @@ int xhci_reset(struct xhci_hcd *xhci) return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); } -/* - * Free IRQs - * free all IRQs request - */ -static void xhci_free_irq(struct xhci_hcd *xhci) +#ifdef CONFIG_PCI +static int xhci_free_msi(struct xhci_hcd *xhci) { int i; - struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); - - /* return if using legacy interrupt */ - if (xhci_to_hcd(xhci)->irq >= 0) - return; - if (xhci->msix_entries) { - for (i = 0; i < xhci->msix_count; i++) - if (xhci->msix_entries[i].vector) - free_irq(xhci->msix_entries[i].vector, - xhci_to_hcd(xhci)); - } else if (pdev->irq >= 0) - free_irq(pdev->irq, xhci_to_hcd(xhci)); + if (!xhci->msix_entries) + return -EINVAL; - return; + for (i = 0; i < xhci->msix_count; i++) + if (xhci->msix_entries[i].vector) + free_irq(xhci->msix_entries[i].vector, + xhci_to_hcd(xhci)); + return 0; } /* @@ -224,6 +215,28 @@ static int xhci_setup_msi(struct xhci_hcd *xhci) } /* + * Free IRQs + * free all IRQs request + */ +static void xhci_free_irq(struct xhci_hcd *xhci) +{ + struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); + int ret; + + /* return if using legacy interrupt */ + if (xhci_to_hcd(xhci)->irq >= 0) + return; + + ret = xhci_free_msi(xhci); + if (!ret) + return; + if (pdev->irq >= 0) + free_irq(pdev->irq, xhci_to_hcd(xhci)); + + return; +} + +/* * Set up MSI-X */ static int xhci_setup_msix(struct xhci_hcd *xhci) @@ -302,6 +315,72 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci) return; } +static void xhci_msix_sync_irqs(struct xhci_hcd *xhci) +{ + int i; + + if (xhci->msix_entries) { + for (i = 0; i < xhci->msix_count; i++) + synchronize_irq(xhci->msix_entries[i].vector); + } +} + +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; +} + +#else + +static int xhci_try_enable_msi(struct usb_hcd *hcd) +{ + return 0; +} + +static void xhci_cleanup_msix(struct xhci_hcd *xhci) +{ +} + +static void xhci_msix_sync_irqs(struct xhci_hcd *xhci) +{ +} + +#endif + /* * Initialize memory for HCD and xHC (one-time init). * @@ -397,45 +476,6 @@ 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. * @@ -708,7 +748,6 @@ int xhci_suspend(struct xhci_hcd *xhci) int rc = 0; struct usb_hcd *hcd = xhci_to_hcd(xhci); u32 command; - int i; spin_lock_irq(&xhci->lock); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); @@ -744,10 +783,7 @@ int xhci_suspend(struct xhci_hcd *xhci) /* step 5: remove core well power */ /* synchronize irq when using MSI-X */ - if (xhci->msix_entries) { - for (i = 0; i < xhci->msix_count; i++) - synchronize_irq(xhci->msix_entries[i].vector); - } + xhci_msix_sync_irqs(xhci); return rc; } |