aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/msi.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index f9fdc54473c4..9fc9a34ef24a 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -627,22 +627,24 @@ static int msix_capability_init(struct pci_dev *dev,
627 * pci_msi_supported - check whether MSI may be enabled on device 627 * pci_msi_supported - check whether MSI may be enabled on device
628 * @dev: pointer to the pci_dev data structure of MSI device function 628 * @dev: pointer to the pci_dev data structure of MSI device function
629 * 629 *
630 * MSI must be globally enabled and supported by the device and its root 630 * Look at global flags, the device itself, and its parent busses
631 * bus. But, the root bus is not easy to find since some architectures 631 * to return 0 if MSI are supported for the device.
632 * have virtual busses on top of the PCI hierarchy (for instance the
633 * hypertransport bus), while the actual bus where MSI must be supported
634 * is below. So we test the MSI flag on all parent busses and assume
635 * that no quirk will ever set the NO_MSI flag on a non-root bus.
636 **/ 632 **/
637static 633static
638int pci_msi_supported(struct pci_dev * dev) 634int pci_msi_supported(struct pci_dev * dev)
639{ 635{
640 struct pci_bus *bus; 636 struct pci_bus *bus;
641 637
638 /* MSI must be globally enabled and supported by the device */
642 if (!pci_msi_enable || !dev || dev->no_msi) 639 if (!pci_msi_enable || !dev || dev->no_msi)
643 return -EINVAL; 640 return -EINVAL;
644 641
645 /* check MSI flags of all parent busses */ 642 /* Any bridge which does NOT route MSI transactions from it's
643 * secondary bus to it's primary bus must set NO_MSI flag on
644 * the secondary pci_bus.
645 * We expect only arch-specific PCI host bus controller driver
646 * or quirks for specific PCI bridges to be setting NO_MSI.
647 */
646 for (bus = dev->bus; bus; bus = bus->parent) 648 for (bus = dev->bus; bus; bus = bus->parent)
647 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) 649 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
648 return -EINVAL; 650 return -EINVAL;