diff options
author | jhb <jhb@FreeBSD.org> | 2007-01-13 04:57:37 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2007-01-13 04:57:37 +0000 |
commit | 053f91b1b39c7a6ec974200bb7801edf27adb10f (patch) | |
tree | ec820e36829ba1e1545becb5800b8dd0b6da973f | |
parent | cbd9e164046125adc3cf7eee878772255b2ab871 (diff) | |
download | FreeBSD-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.c | 6 | ||||
-rw-r--r-- | sys/dev/pci/pci_pci.c | 9 | ||||
-rw-r--r-- | sys/dev/pci/pcib_private.h | 1 |
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 */ |