diff options
author | jhb <jhb@FreeBSD.org> | 2012-03-29 19:03:22 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2012-03-29 19:03:22 +0000 |
commit | 876e74a14e5e797af724083627fdae328d77d62a (patch) | |
tree | 16d6f5200857c5f9b1d5733c5b7289fa5ebbdc2d /sys/x86 | |
parent | 38fb55f1d4d3789de9a985973acad5091a0e222e (diff) | |
download | FreeBSD-src-876e74a14e5e797af724083627fdae328d77d62a.zip FreeBSD-src-876e74a14e5e797af724083627fdae328d77d62a.tar.gz |
Use a more proper fix for enabling HT MSI mapping windows on Host-PCI
bridges. Rather than blindly enabling the windows on all of them, only
enable the window when an MSI interrupt is enabled for a device behind
the bridge, similar to what already happens for HT PCI-PCI bridges.
To implement this, each x86 Host-PCI bridge driver has to be able to
locate it's actual backing device on bus 0. For ACPI, use the _ADR
method to find the slot and function of the device. For the non-ACPI
case, the legacy(4) driver already scans bus 0 looking for Host-PCI
bridge devices. Now it saves the slot and function of each bridge that
it finds as ivars that the Host-PCI bridge driver can then use in its
pcib_map_msi() method.
This fixes machines where non-MSI interrupts were broken by the previous
round of HT MSI changes.
Tested by: bapt
MFC after: 1 week
Diffstat (limited to 'sys/x86')
-rw-r--r-- | sys/x86/pci/pci_bus.c | 22 | ||||
-rw-r--r-- | sys/x86/x86/mptable_pci.c | 12 |
2 files changed, 20 insertions, 14 deletions
diff --git a/sys/x86/pci/pci_bus.c b/sys/x86/pci/pci_bus.c index 995e714..4363e7b 100644 --- a/sys/x86/pci/pci_bus.c +++ b/sys/x86/pci/pci_bus.c @@ -112,14 +112,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq) return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq)); } -static int +int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, uint32_t *data) { - device_t bus; + device_t bus, hostb; + int error, func, slot; bus = device_get_parent(pcib); - return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data)); + error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data); + if (error) + return (error); + + slot = legacy_get_pcislot(pcib); + func = legacy_get_pcifunc(pcib); + if (slot == -1 || func == -1) + return (0); + hostb = pci_find_bsf(0, slot, func); + KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__, + slot, func)); + pci_ht_map_msi(hostb, *addr); + return (0); + } static const char * @@ -453,6 +467,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent) "pcib", busnum); device_set_desc(child, s); legacy_set_pcibus(child, busnum); + legacy_set_pcislot(child, slot); + legacy_set_pcifunc(child, func); found = 1; if (id == 0x12258086) diff --git a/sys/x86/x86/mptable_pci.c b/sys/x86/x86/mptable_pci.c index 985cfa7..70a00b5 100644 --- a/sys/x86/x86/mptable_pci.c +++ b/sys/x86/x86/mptable_pci.c @@ -97,16 +97,6 @@ mptable_hostb_alloc_msix(device_t pcib, device_t dev, int *irq) return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq)); } -static int -mptable_hostb_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, - uint32_t *data) -{ - device_t bus; - - bus = device_get_parent(pcib); - return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data)); -} - #ifdef NEW_PCIB static int mptable_is_isa_range(u_long start, u_long end) @@ -214,7 +204,7 @@ static device_method_t mptable_hostb_methods[] = { DEVMETHOD(pcib_release_msi, pcib_release_msi), DEVMETHOD(pcib_alloc_msix, mptable_hostb_alloc_msix), DEVMETHOD(pcib_release_msix, pcib_release_msix), - DEVMETHOD(pcib_map_msi, mptable_hostb_map_msi), + DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi), DEVMETHOD_END }; |