aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2020-07-02 17:30:45 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-07-21 13:38:21 +0200
commit306c54d0edb6ba94d39877524dddebaad7770cf2 (patch)
treed75c0124ae3985f0089aa583f113c1e578926634
parentMerge 5.8-rc6 into usb-next (diff)
downloadlinux-dev-306c54d0edb6ba94d39877524dddebaad7770cf2.tar.xz
linux-dev-306c54d0edb6ba94d39877524dddebaad7770cf2.zip
usb: hcd: Try MSI interrupts on PCI devices
It appears that some platforms share same IRQ line between several devices, some of which are EHCI and OHCI controllers. This is neither practical nor performance-wise, especially in the case when they are supporting MSI. In order to improve the situation try to allocate MSI and fallback to legacy IRQ if no MSI available. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://lore.kernel.org/r/20200702143045.23429-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/core/hcd-pci.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 1547aa6e5314..4dc443aaef5c 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -194,20 +194,21 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id,
* make sure irq setup is not touched for xhci in generic hcd code
*/
if ((driver->flags & HCD_MASK) < HCD_USB3) {
- if (!dev->irq) {
+ retval = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY | PCI_IRQ_MSI);
+ if (retval < 0) {
dev_err(&dev->dev,
"Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
pci_name(dev));
retval = -ENODEV;
goto disable_pci;
}
- hcd_irq = dev->irq;
+ hcd_irq = pci_irq_vector(dev, 0);
}
hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev));
if (!hcd) {
retval = -ENOMEM;
- goto disable_pci;
+ goto free_irq_vectors;
}
hcd->amd_resume_bug = (usb_hcd_amd_remote_wakeup_quirk(dev) &&
@@ -286,6 +287,9 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id,
put_hcd:
usb_put_hcd(hcd);
+free_irq_vectors:
+ if ((driver->flags & HCD_MASK) < HCD_USB3)
+ pci_free_irq_vectors(dev);
disable_pci:
pci_disable_device(dev);
dev_err(&dev->dev, "init %s fail, %d\n", pci_name(dev), retval);
@@ -343,6 +347,8 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
up_read(&companions_rwsem);
}
usb_put_hcd(hcd);
+ if ((hcd->driver->flags & HCD_MASK) < HCD_USB3)
+ pci_free_irq_vectors(dev);
pci_disable_device(dev);
}
EXPORT_SYMBOL_GPL(usb_hcd_pci_remove);
@@ -454,7 +460,7 @@ static int suspend_common(struct device *dev, bool do_wakeup)
* synchronized here.
*/
if (!hcd->msix_enabled)
- synchronize_irq(pci_dev->irq);
+ synchronize_irq(pci_irq_vector(pci_dev, 0));
/* Downstream ports from this root hub should already be quiesced, so
* there will be no DMA activity. Now we can shut down the upstream