summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-05-05 14:16:18 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-05-05 14:16:18 +0000
commit7a84bcea6b9be61aa405059ba996e8d0001656a1 (patch)
tree07baae926801fc646f5277421461ccac124b393c /sys/dev/pci
parentbfad4bde7ce2e35762ab0fbf0d1179ad9b84561f (diff)
Add extents for prefetchable memory mapped I/O. Should remove conflict
messages for devices using prefetchable memory sitting behind bridges.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/pci.c20
-rw-r--r--sys/dev/pci/pcivar.h5
-rw-r--r--sys/dev/pci/ppb.c33
3 files changed, 53 insertions, 5 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 543cc0f35df..8f292474458 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci.c,v 1.60 2009/04/06 20:51:48 kettenis Exp $ */
+/* $OpenBSD: pci.c,v 1.61 2009/05/05 14:16:17 kettenis Exp $ */
/* $NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $ */
/*
@@ -157,6 +157,7 @@ pciattach(struct device *parent, struct device *self, void *aux)
sc->sc_pc = pba->pba_pc;
sc->sc_ioex = pba->pba_ioex;
sc->sc_memex = pba->pba_memex;
+ sc->sc_pmemex = pba->pba_pmemex;
sc->sc_domain = pba->pba_domain;
sc->sc_bus = pba->pba_bus;
sc->sc_bridgetag = pba->pba_bridgetag;
@@ -283,6 +284,7 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
pa.pa_pc = pc;
pa.pa_ioex = sc->sc_ioex;
pa.pa_memex = sc->sc_memex;
+ pa.pa_pmemex = sc->sc_pmemex;
pa.pa_domain = sc->sc_domain;
pa.pa_bus = bus;
pa.pa_device = device;
@@ -514,6 +516,7 @@ pci_reserve_resources(struct pci_attach_args *pa)
bus_addr_t base, limit;
bus_size_t size;
int reg, reg_start, reg_end;
+ int flags;
bhlc = pci_conf_read(pc, tag, PCI_BHLC_REG);
switch (PCI_HDRTYPE_TYPE(bhlc)) {
@@ -537,7 +540,7 @@ pci_reserve_resources(struct pci_attach_args *pa)
if (!pci_mapreg_probe(pc, tag, reg, &type))
continue;
- if (pci_mapreg_info(pc, tag, reg, type, &base, &size, NULL))
+ if (pci_mapreg_info(pc, tag, reg, type, &base, &size, &flags))
continue;
if (base == 0)
@@ -546,6 +549,13 @@ pci_reserve_resources(struct pci_attach_args *pa)
switch (type) {
case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
+#ifdef BUS_SPACE_MAP_PREFETCHABLE
+ if (ISSET(flags, BUS_SPACE_MAP_PREFETCHABLE) &&
+ pa->pa_pmemex && extent_alloc_region(pa->pa_pmemex,
+ base, size, EX_NOWAIT) == 0) {
+ break;
+ }
+#endif
if (pa->pa_memex && extent_alloc_region(pa->pa_memex,
base, size, EX_NOWAIT))
printf("mem address conflict 0x%x/0x%x\n",
@@ -602,7 +612,11 @@ pci_reserve_resources(struct pci_attach_args *pa)
size = (limit - base + 1);
else
size = 0;
- if (pa->pa_memex && base > 0 && size > 0) {
+ if (pa->pa_pmemex && base > 0 && size > 0) {
+ if (extent_alloc_region(pa->pa_pmemex, base, size, EX_NOWAIT))
+ printf("bridge mem address conflict 0x%x/0x%x\n",
+ base, size);
+ } else if (pa->pa_memex && base > 0 && size > 0) {
if (extent_alloc_region(pa->pa_memex, base, size, EX_NOWAIT))
printf("bridge mem address conflict 0x%x/0x%x\n",
base, size);
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index 0347e29430b..6566e50d061 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcivar.h,v 1.58 2009/04/06 20:51:48 kettenis Exp $ */
+/* $OpenBSD: pcivar.h,v 1.59 2009/05/05 14:16:17 kettenis Exp $ */
/* $NetBSD: pcivar.h,v 1.23 1997/06/06 23:48:05 thorpej Exp $ */
/*
@@ -93,6 +93,7 @@ struct pcibus_attach_args {
struct extent *pba_ioex;
struct extent *pba_memex;
+ struct extent *pba_pmemex;
int pba_domain; /* PCI domain */
int pba_bus; /* PCI bus number */
@@ -124,6 +125,7 @@ struct pci_attach_args {
struct extent *pa_ioex;
struct extent *pa_memex;
+ struct extent *pa_pmemex;
u_int pa_domain;
u_int pa_bus;
@@ -180,6 +182,7 @@ struct pci_softc {
pci_chipset_tag_t sc_pc;
struct extent *sc_ioex;
struct extent *sc_memex;
+ struct extent *sc_pmemex;
void *sc_powerhook;
LIST_HEAD(, pci_dev) sc_devs;
int sc_domain, sc_bus, sc_maxndevs;
diff --git a/sys/dev/pci/ppb.c b/sys/dev/pci/ppb.c
index 2744e2e575a..d5e066b43e0 100644
--- a/sys/dev/pci/ppb.c
+++ b/sys/dev/pci/ppb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ppb.c,v 1.31 2009/04/24 20:03:55 kettenis Exp $ */
+/* $OpenBSD: ppb.c,v 1.32 2009/05/05 14:16:17 kettenis Exp $ */
/* $NetBSD: ppb.c,v 1.16 1997/06/06 23:48:05 thorpej Exp $ */
/*
@@ -51,12 +51,14 @@ struct ppb_softc {
void *sc_intrhand;
struct extent *sc_ioex;
struct extent *sc_memex;
+ struct extent *sc_pmemex;
struct device *sc_psc;
int sc_cap_off;
struct timeout sc_to;
bus_addr_t sc_iobase, sc_iolimit;
bus_addr_t sc_membase, sc_memlimit;
+ bus_addr_t sc_pmembase, sc_pmemlimit;
};
int ppbmatch(struct device *, void *, void *);
@@ -209,6 +211,22 @@ ppbattach(struct device *parent, struct device *self, void *aux)
}
}
+ /* Figure out the prefetchable MMI/O address range of the bridge. */
+ blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFMEM);
+ sc->sc_pmembase = (blr & 0x0000fff0) << 16;
+ sc->sc_pmemlimit = (blr & 0xfff00000) | 0x000fffff;
+ if (sc->sc_pmemlimit > sc->sc_pmembase) {
+ name = malloc(32, M_DEVBUF, M_NOWAIT);
+ if (name) {
+ snprintf(name, 32, "%s pcipmem", sc->sc_dev.dv_xname);
+ sc->sc_pmemex = extent_create(name, 0, 0xffffffff,
+ M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);
+ extent_free(sc->sc_pmemex, sc->sc_pmembase,
+ sc->sc_pmemlimit - sc->sc_pmembase + 1,
+ EX_NOWAIT);
+ }
+ }
+
attach:
/*
* Attach the PCI bus that hangs off of it.
@@ -224,6 +242,7 @@ ppbattach(struct device *parent, struct device *self, void *aux)
pba.pba_pc = pc;
pba.pba_ioex = sc->sc_ioex;
pba.pba_memex = sc->sc_memex;
+ pba.pba_pmemex = sc->sc_pmemex;
#if 0
pba.pba_flags = pa->pa_flags & ~PCI_FLAGS_MRM_OKAY;
#endif
@@ -261,6 +280,12 @@ ppbdetach(struct device *self, int flags)
free(name, M_DEVBUF);
}
+ if (sc->sc_pmemex) {
+ name = sc->sc_pmemex->ex_name;
+ extent_destroy(sc->sc_pmemex);
+ free(name, M_DEVBUF);
+ }
+
return (rv);
}
@@ -455,6 +480,12 @@ ppb_hotplug_remove(void *arg1, void *arg2)
EX_NOWAIT | EX_CONFLICTOK);
extent_free(sc->sc_memex, sc->sc_membase,
sc->sc_memlimit - sc->sc_membase + 1, EX_NOWAIT);
+
+ extent_alloc_region(sc->sc_pmemex, sc->sc_pmembase,
+ sc->sc_pmemlimit - sc->sc_pmembase + 1,
+ EX_NOWAIT | EX_CONFLICTOK);
+ extent_free(sc->sc_pmemex, sc->sc_pmembase,
+ sc->sc_pmemlimit - sc->sc_pmembase + 1, EX_NOWAIT);
}
}