summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2011-01-09 11:38:10 +0000
committerkettenis <kettenis@openbsd.org>2011-01-09 11:38:10 +0000
commitd3b3aeffbef1a2862cdf2f552a23b4d933b84446 (patch)
tree35ed463e5835814fc80c60f2623212368538a53e
parentsync (diff)
downloadwireguard-openbsd-d3b3aeffbef1a2862cdf2f552a23b4d933b84446.tar.xz
wireguard-openbsd-d3b3aeffbef1a2862cdf2f552a23b4d933b84446.zip
Only use memory mapped extended PCIe config space access for the busses
advertised in the MCFG table, and fall back on the traditional method for other busses. Fixes issue reported by henning@.
-rw-r--r--sys/arch/amd64/pci/pci_machdep.c66
-rw-r--r--sys/arch/i386/pci/pci_machdep.c68
2 files changed, 64 insertions, 70 deletions
diff --git a/sys/arch/amd64/pci/pci_machdep.c b/sys/arch/amd64/pci/pci_machdep.c
index 10a5df20ae0..4e7a6d9f0a5 100644
--- a/sys/arch/amd64/pci/pci_machdep.c
+++ b/sys/arch/amd64/pci/pci_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.c,v 1.38 2011/01/04 21:17:49 kettenis Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.39 2011/01/09 11:38:10 kettenis Exp $ */
/* $NetBSD: pci_machdep.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */
/*-
@@ -108,6 +108,7 @@ bus_addr_t pci_mcfg_addr;
int pci_mcfg_min_bus, pci_mcfg_max_bus;
bus_space_tag_t pci_mcfgt = X86_BUS_SPACE_MEM;
bus_space_handle_t pci_mcfgh[256];
+void pci_mcfg_map_bus(int);
struct mutex pci_conf_lock = MUTEX_INITIALIZER(IPL_HIGH);
@@ -170,14 +171,6 @@ pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
if (bus >= 256 || device >= 32 || function >= 8)
panic("pci_make_tag: bad request");
- if (pci_mcfg_addr) {
- if (bus < pci_mcfg_min_bus || bus > pci_mcfg_max_bus ||
- device >= 32 || function >= 8)
- panic("pci_make_tag: bad request");
-
- return (bus << 20) | (device << 15) | (function << 12);
- }
-
return (PCI_MODE1_ENABLE |
(bus << 16) | (device << 11) | (function << 8));
}
@@ -185,16 +178,6 @@ pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
void
pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp)
{
- if (pci_mcfg_addr) {
- if (bp != NULL)
- *bp = (tag >> 20) & 0xff;
- if (dp != NULL)
- *dp = (tag >> 15) & 0x1f;
- if (fp != NULL)
- *fp = (tag >> 12) & 0x7;
- return;
- }
-
if (bp != NULL)
*bp = (tag >> 16) & 0xff;
if (dp != NULL)
@@ -206,12 +189,28 @@ pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp)
int
pci_conf_size(pci_chipset_tag_t pc, pcitag_t tag)
{
- if (pci_mcfg_addr)
- return PCIE_CONFIG_SPACE_SIZE;
+ int bus;
+
+ if (pci_mcfg_addr) {
+ pci_decompose_tag(pc, tag, &bus, NULL, NULL);
+ if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus)
+ return PCIE_CONFIG_SPACE_SIZE;
+ }
return PCI_CONFIG_SPACE_SIZE;
}
+void
+pci_mcfg_map_bus(int bus)
+{
+ if (pci_mcfgh[bus])
+ return;
+
+ if (bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20), 1 << 20,
+ 0, &pci_mcfgh[bus]))
+ panic("pci_conf_read: cannot map mcfg space");
+}
+
pcireg_t
pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
{
@@ -220,12 +219,12 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
if (pci_mcfg_addr) {
pci_decompose_tag(pc, tag, &bus, NULL, NULL);
- if (pci_mcfgh[bus] == 0 &&
- bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20),
- 1 << 20, 0, &pci_mcfgh[bus]))
- panic("pci_conf_read: cannot map mcfg space");
- return bus_space_read_4(pci_mcfgt, pci_mcfgh[bus],
- (tag & 0x000ff000) | reg);
+ if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) {
+ pci_mcfg_map_bus(bus);
+ data = bus_space_read_4(pci_mcfgt, pci_mcfgh[bus],
+ (tag & 0x000ff00) << 4 | reg);
+ return data;
+ }
}
PCI_CONF_LOCK();
@@ -244,13 +243,12 @@ pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
if (pci_mcfg_addr) {
pci_decompose_tag(pc, tag, &bus, NULL, NULL);
- if (pci_mcfgh[bus] == 0 &&
- bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20),
- 1 << 20, 0, &pci_mcfgh[bus]))
- panic("pci_conf_write: cannot map mcfg space");
- bus_space_write_4(pci_mcfgt, pci_mcfgh[bus],
- (tag & 0x000ff000) | reg, data);
- return;
+ if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) {
+ pci_mcfg_map_bus(bus);
+ bus_space_write_4(pci_mcfgt, pci_mcfgh[bus],
+ (tag & 0x000ff00) << 4 | reg, data);
+ return;
+ }
}
PCI_CONF_LOCK();
diff --git a/sys/arch/i386/pci/pci_machdep.c b/sys/arch/i386/pci/pci_machdep.c
index e6404bf3f91..8d684f8f306 100644
--- a/sys/arch/i386/pci/pci_machdep.c
+++ b/sys/arch/i386/pci/pci_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.c,v 1.56 2011/01/04 21:17:49 kettenis Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.57 2011/01/09 11:38:10 kettenis Exp $ */
/* $NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $ */
/*-
@@ -126,6 +126,7 @@ bus_addr_t pci_mcfg_addr;
int pci_mcfg_min_bus, pci_mcfg_max_bus;
bus_space_tag_t pci_mcfgt = I386_BUS_SPACE_MEM;
bus_space_handle_t pci_mcfgh[256];
+void pci_mcfg_map_bus(int);
struct mutex pci_conf_lock = MUTEX_INITIALIZER(IPL_HIGH);
@@ -224,15 +225,6 @@ pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
{
pcitag_t tag;
- if (pci_mcfg_addr) {
- if (bus < pci_mcfg_min_bus || bus > pci_mcfg_max_bus ||
- device >= 32 || function >= 8)
- panic("pci_make_tag: bad request");
-
- tag.mode1 = (bus << 20) | (device << 15) | (function << 12);
- return tag;
- }
-
switch (pci_mode) {
case 1:
if (bus >= 256 || device >= 32 || function >= 8)
@@ -259,16 +251,6 @@ pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
void
pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp)
{
- if (pci_mcfg_addr) {
- if (bp != NULL)
- *bp = (tag.mode1 >> 20) & 0xff;
- if (dp != NULL)
- *dp = (tag.mode1 >> 15) & 0x1f;
- if (fp != NULL)
- *fp = (tag.mode1 >> 12) & 0x7;
- return;
- }
-
switch (pci_mode) {
case 1:
if (bp != NULL)
@@ -294,12 +276,28 @@ pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp)
int
pci_conf_size(pci_chipset_tag_t pc, pcitag_t tag)
{
- if (pci_mcfg_addr)
- return PCIE_CONFIG_SPACE_SIZE;
+ int bus;
+
+ if (pci_mcfg_addr) {
+ pci_decompose_tag(pc, tag, &bus, NULL, NULL);
+ if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus)
+ return PCIE_CONFIG_SPACE_SIZE;
+ }
return PCI_CONFIG_SPACE_SIZE;
}
+void
+pci_mcfg_map_bus(int bus)
+{
+ if (pci_mcfgh[bus])
+ return;
+
+ if (bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20), 1 << 20,
+ 0, &pci_mcfgh[bus]))
+ panic("pci_conf_read: cannot map mcfg space");
+}
+
pcireg_t
pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
{
@@ -308,13 +306,12 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
if (pci_mcfg_addr) {
pci_decompose_tag(pc, tag, &bus, NULL, NULL);
- if (pci_mcfgh[bus] == 0 &&
- bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20),
- 1 << 20, 0, &pci_mcfgh[bus]))
- panic("pci_conf_read: cannot map mcfg space");
- data = bus_space_read_4(pci_mcfgt, pci_mcfgh[bus],
- (tag.mode1 & 0x000ff000) | reg);
- return data;
+ if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) {
+ pci_mcfg_map_bus(bus);
+ data = bus_space_read_4(pci_mcfgt, pci_mcfgh[bus],
+ (tag.mode1 & 0x000ff00) << 4 | reg);
+ return data;
+ }
}
PCI_CONF_LOCK();
@@ -345,13 +342,12 @@ pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
if (pci_mcfg_addr) {
pci_decompose_tag(pc, tag, &bus, NULL, NULL);
- if (pci_mcfgh[bus] == 0 &&
- bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20),
- 1 << 20, 0, &pci_mcfgh[bus]))
- panic("pci_conf_write: cannot map mcfg space");
- bus_space_write_4(pci_mcfgt, pci_mcfgh[bus],
- (tag.mode1 & 0x000ff000) | reg, data);
- return;
+ if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) {
+ pci_mcfg_map_bus(bus);
+ bus_space_write_4(pci_mcfgt, pci_mcfgh[bus],
+ (tag.mode1 & 0x000ff00) << 4 | reg, data);
+ return;
+ }
}
PCI_CONF_LOCK();