summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2012-03-29 19:03:22 +0000
committerjhb <jhb@FreeBSD.org>2012-03-29 19:03:22 +0000
commit876e74a14e5e797af724083627fdae328d77d62a (patch)
tree16d6f5200857c5f9b1d5733c5b7289fa5ebbdc2d /sys/amd64
parent38fb55f1d4d3789de9a985973acad5091a0e222e (diff)
downloadFreeBSD-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.c18
-rw-r--r--sys/amd64/include/legacyvar.h8
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_ */
OpenPOWER on IntegriCloud