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/amd64 | |
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/amd64')
-rw-r--r-- | sys/amd64/amd64/legacy.c | 18 | ||||
-rw-r--r-- | sys/amd64/include/legacyvar.h | 8 |
2 files changed, 24 insertions, 2 deletions
diff --git a/sys/amd64/amd64/legacy.c b/sys/amd64/amd64/legacy.c index 40da8b6..387a6d9 100644 --- a/sys/amd64/amd64/legacy.c +++ b/sys/amd64/amd64/legacy.c @@ -53,7 +53,9 @@ __FBSDID("$FreeBSD$"); static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device"); struct legacy_device { - int lg_pcibus; + int lg_pcibus; + int lg_pcislot; + int lg_pcifunc; }; #define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev)) @@ -161,6 +163,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit) if (atdev == NULL) return(NULL); atdev->lg_pcibus = -1; + atdev->lg_pcislot = -1; + atdev->lg_pcifunc = -1; child = device_add_child_ordered(bus, order, name, unit); if (child == NULL) @@ -184,6 +188,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) case LEGACY_IVAR_PCIBUS: *result = atdev->lg_pcibus; break; + case LEGACY_IVAR_PCISLOT: + *result = atdev->lg_pcislot; + break; + case LEGACY_IVAR_PCIFUNC: + *result = atdev->lg_pcifunc; + break; default: return ENOENT; } @@ -202,6 +212,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value) case LEGACY_IVAR_PCIBUS: atdev->lg_pcibus = value; break; + case LEGACY_IVAR_PCISLOT: + atdev->lg_pcislot = value; + break; + case LEGACY_IVAR_PCIFUNC: + atdev->lg_pcifunc = value; + break; default: return ENOENT; } diff --git a/sys/amd64/include/legacyvar.h b/sys/amd64/include/legacyvar.h index 12a2864..8116db0 100644 --- a/sys/amd64/include/legacyvar.h +++ b/sys/amd64/include/legacyvar.h @@ -31,7 +31,9 @@ enum legacy_device_ivars { LEGACY_IVAR_PCIDOMAIN, - LEGACY_IVAR_PCIBUS + LEGACY_IVAR_PCIBUS, + LEGACY_IVAR_PCISLOT, + LEGACY_IVAR_PCIFUNC }; #define LEGACY_ACCESSOR(var, ivar, type) \ @@ -39,6 +41,8 @@ enum legacy_device_ivars { LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t) LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t) +LEGACY_ACCESSOR(pcislot, PCISLOT, int) +LEGACY_ACCESSOR(pcifunc, PCIFUNC, int) #undef LEGACY_ACCESSOR @@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value); struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags); +int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, + uint64_t *addr, uint32_t *data); #endif /* !_MACHINE_LEGACYVAR_H_ */ |