summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2007-01-13 04:57:37 +0000
committerjhb <jhb@FreeBSD.org>2007-01-13 04:57:37 +0000
commit053f91b1b39c7a6ec974200bb7801edf27adb10f (patch)
treeec820e36829ba1e1545becb5800b8dd0b6da973f
parentcbd9e164046125adc3cf7eee878772255b2ab871 (diff)
downloadFreeBSD-src-053f91b1b39c7a6ec974200bb7801edf27adb10f.zip
FreeBSD-src-053f91b1b39c7a6ec974200bb7801edf27adb10f.tar.gz
- Add a new flag to the PCI-PCI driver to disable MSI on devices behind the
bridge if it doesn't pass MSI messages up correctly. We set the flag in pcib_attach() if the device ID is disabled via a PCI quirk. - Disable MSI for devices behind the AMD 8131 HT-PCIX bridge. Linux has the same quirk. Tested by: no one despite repeated calls for testers
-rw-r--r--sys/dev/pci/pci.c6
-rw-r--r--sys/dev/pci/pci_pci.c9
-rw-r--r--sys/dev/pci/pcib_private.h1
3 files changed, 16 insertions, 0 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index f209f31..018de34 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -194,6 +194,12 @@ struct pci_quirk pci_quirks[] = {
{ 0x25788086, PCI_QUIRK_DISABLE_MSI, 0, 0 },
{ 0x35808086, PCI_QUIRK_DISABLE_MSI, 0, 0 },
+ /*
+ * MSI doesn't work with devices behind the AMD 8131 HT-PCIX
+ * bridge.
+ */
+ { 0x74501022, PCI_QUIRK_DISABLE_MSI, 0, 0 },
+
{ 0 }
};
diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c
index 9e0cce4..8accc42 100644
--- a/sys/dev/pci/pci_pci.c
+++ b/sys/dev/pci/pci_pci.c
@@ -240,6 +240,9 @@ pcib_attach_common(device_t dev)
}
}
+ if (pci_msi_device_blacklisted(dev))
+ sc->flags |= PCIB_DISABLE_MSI;
+
/*
* Intel 815, 845 and other chipsets say they are PCI-PCI bridges,
* but have a ProgIF of 0x80. The 82801 family (AA, AB, BAM/CAM,
@@ -547,8 +550,11 @@ pcib_route_interrupt(device_t pcib, device_t dev, int pin)
int
pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
{
+ struct pcib_softc *sc = device_get_softc(dev);
device_t bus;
+ if (sc->flags & PCIB_DISABLE_MSI)
+ return (ENXIO);
bus = device_get_parent(pcib);
return (PCIB_ALLOC_MSI(device_get_parent(bus), dev, count, maxcount,
irqs));
@@ -568,8 +574,11 @@ pcib_release_msi(device_t pcib, device_t dev, int count, int *irqs)
int
pcib_alloc_msix(device_t pcib, device_t dev, int index, int *irq)
{
+ struct pcib_softc *sc = device_get_softc(dev);
device_t bus;
+ if (sc->flags & PCIB_DISABLE_MSI)
+ return (ENXIO);
bus = device_get_parent(pcib);
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, index, irq));
}
diff --git a/sys/dev/pci/pcib_private.h b/sys/dev/pci/pcib_private.h
index 493b87d..9575df2 100644
--- a/sys/dev/pci/pcib_private.h
+++ b/sys/dev/pci/pcib_private.h
@@ -46,6 +46,7 @@ struct pcib_softc
device_t dev;
uint32_t flags; /* flags */
#define PCIB_SUBTRACTIVE 0x1
+#define PCIB_DISABLE_MSI 0x2
uint16_t command; /* command register */
uint8_t secbus; /* secondary bus number */
uint8_t subbus; /* subordinate bus number */
OpenPOWER on IntegriCloud