diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-05-05 14:16:18 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-05-05 14:16:18 +0000 |
commit | 7a84bcea6b9be61aa405059ba996e8d0001656a1 (patch) | |
tree | 07baae926801fc646f5277421461ccac124b393c /sys/dev/pci | |
parent | bfad4bde7ce2e35762ab0fbf0d1179ad9b84561f (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.c | 20 | ||||
-rw-r--r-- | sys/dev/pci/pcivar.h | 5 | ||||
-rw-r--r-- | sys/dev/pci/ppb.c | 33 |
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); } } |