mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
eed3c957dd
commit
306c54d0ed
|
@ -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
|
* make sure irq setup is not touched for xhci in generic hcd code
|
||||||
*/
|
*/
|
||||||
if ((driver->flags & HCD_MASK) < HCD_USB3) {
|
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,
|
dev_err(&dev->dev,
|
||||||
"Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
|
"Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
|
||||||
pci_name(dev));
|
pci_name(dev));
|
||||||
retval = -ENODEV;
|
retval = -ENODEV;
|
||||||
goto disable_pci;
|
goto disable_pci;
|
||||||
}
|
}
|
||||||
hcd_irq = dev->irq;
|
hcd_irq = pci_irq_vector(dev, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev));
|
hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev));
|
||||||
if (!hcd) {
|
if (!hcd) {
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto disable_pci;
|
goto free_irq_vectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
hcd->amd_resume_bug = (usb_hcd_amd_remote_wakeup_quirk(dev) &&
|
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:
|
put_hcd:
|
||||||
usb_put_hcd(hcd);
|
usb_put_hcd(hcd);
|
||||||
|
free_irq_vectors:
|
||||||
|
if ((driver->flags & HCD_MASK) < HCD_USB3)
|
||||||
|
pci_free_irq_vectors(dev);
|
||||||
disable_pci:
|
disable_pci:
|
||||||
pci_disable_device(dev);
|
pci_disable_device(dev);
|
||||||
dev_err(&dev->dev, "init %s fail, %d\n", pci_name(dev), retval);
|
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);
|
up_read(&companions_rwsem);
|
||||||
}
|
}
|
||||||
usb_put_hcd(hcd);
|
usb_put_hcd(hcd);
|
||||||
|
if ((hcd->driver->flags & HCD_MASK) < HCD_USB3)
|
||||||
|
pci_free_irq_vectors(dev);
|
||||||
pci_disable_device(dev);
|
pci_disable_device(dev);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(usb_hcd_pci_remove);
|
EXPORT_SYMBOL_GPL(usb_hcd_pci_remove);
|
||||||
|
@ -454,7 +460,7 @@ static int suspend_common(struct device *dev, bool do_wakeup)
|
||||||
* synchronized here.
|
* synchronized here.
|
||||||
*/
|
*/
|
||||||
if (!hcd->msix_enabled)
|
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
|
/* Downstream ports from this root hub should already be quiesced, so
|
||||||
* there will be no DMA activity. Now we can shut down the upstream
|
* there will be no DMA activity. Now we can shut down the upstream
|
||||||
|
|
Loading…
Reference in New Issue