[PATCH] PCI: AMD 8131 MSI quirk called too late, bus_flags not inherited ?
authorBrice Goglin <brice@myri.com>
Tue, 23 May 2006 07:05:27 +0000 (03:05 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 21 Jun 2006 19:00:00 +0000 (12:00 -0700)
The PCI_BUS_FLAGS_NO_MSI bus flags does not appear do be inherited
correctly from the amd8131 MSI quirk to its parent busses. It makes
devices behind a bridge behind amd8131 try to enable MSI while the
amd8131 does not support it.
We fix this by looking at flags of all parent busses in
pci_enable_msi() and pci_enable_msix().

By the way, also add the missing dev->no_msi check in pci_enable_msix()

Signed-off-by: Brice Goglin <brice@myri.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/pci/msi.c

index f8105783da2f54d6a9e1a2eb80ad9ebe6d1aa80d..4aea563bda60720eb58b5f691c5eda4c6a7043ed 100644 (file)
@@ -916,6 +916,7 @@ static int msix_capability_init(struct pci_dev *dev,
  **/
 int pci_enable_msi(struct pci_dev* dev)
 {
+       struct pci_bus *bus;
        int pos, temp, status = -EINVAL;
        u16 control;
 
@@ -925,8 +926,9 @@ int pci_enable_msi(struct pci_dev* dev)
        if (dev->no_msi)
                return status;
 
-       if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
-               return -EINVAL;
+       for (bus = dev->bus; bus; bus = bus->parent)
+               if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
+                       return -EINVAL;
 
        temp = dev->irq;
 
@@ -1162,6 +1164,7 @@ static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec)
  **/
 int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
 {
+       struct pci_bus *bus;
        int status, pos, nr_entries, free_vectors;
        int i, j, temp;
        u16 control;
@@ -1170,6 +1173,13 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
        if (!pci_msi_enable || !dev || !entries)
                return -EINVAL;
 
+       if (dev->no_msi)
+               return -EINVAL;
+
+       for (bus = dev->bus; bus; bus = bus->parent)
+               if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
+                       return -EINVAL;
+
        status = msi_init();
        if (status < 0)
                return status;