diff options
author | 2012-09-19 23:01:21 +0000 | |
---|---|---|
committer | 2012-09-19 23:01:21 +0000 | |
commit | 73d6ed63b050c19dec21d71e1f9121cff99aa761 (patch) | |
tree | 66ab0583fab13a91ecd639ca9d2358d1e0ff5019 | |
parent | ioctl requests are u_long not int, spotted via clang (diff) | |
download | wireguard-openbsd-73d6ed63b050c19dec21d71e1f9121cff99aa761.tar.xz wireguard-openbsd-73d6ed63b050c19dec21d71e1f9121cff99aa761.zip |
Add resource tracking for PCI bus numbers. This will allow us to prevent
attaching the same PCI bus twice and in the long run this will allown us
to hot plug PCI busses and support CardBus on machines where the firmware
doesn't assign a bus number to CardBus devices.
While there, print a bit more information for memory and io conflicts.
-rw-r--r-- | sys/dev/pci/pci.c | 52 | ||||
-rw-r--r-- | sys/dev/pci/pcivar.h | 5 |
2 files changed, 42 insertions, 15 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 7c2de8c1c5d..a19420b7d18 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci.c,v 1.95 2012/09/07 19:26:48 kettenis Exp $ */ +/* $OpenBSD: pci.c,v 1.96 2012/09/19 23:01:21 kettenis Exp $ */ /* $NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $ */ /* @@ -175,6 +175,7 @@ pciattach(struct device *parent, struct device *self, void *aux) sc->sc_ioex = pba->pba_ioex; sc->sc_memex = pba->pba_memex; sc->sc_pmemex = pba->pba_pmemex; + sc->sc_busex = pba->pba_busex; sc->sc_domain = pba->pba_domain; sc->sc_bus = pba->pba_bus; sc->sc_bridgetag = pba->pba_bridgetag; @@ -182,7 +183,13 @@ pciattach(struct device *parent, struct device *self, void *aux) sc->sc_maxndevs = pci_bus_maxdevs(pba->pba_pc, pba->pba_bus); sc->sc_intrswiz = pba->pba_intrswiz; sc->sc_intrtag = pba->pba_intrtag; + + /* Reserve our own bus number. */ + if (sc->sc_busex) + extent_alloc_region(sc->sc_busex, sc->sc_bus, 1, EX_NOWAIT); + pci_enumerate_bus(sc, pci_reserve_resources, NULL); + pci_enumerate_bus(sc, pci_count_vga, NULL); if (pci_enumerate_bus(sc, pci_primary_vga, NULL)) pci_vga_pci = sc; @@ -401,6 +408,7 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag, pa.pa_ioex = sc->sc_ioex; pa.pa_memex = sc->sc_memex; pa.pa_pmemex = sc->sc_pmemex; + pa.pa_busex = sc->sc_busex; pa.pa_domain = sc->sc_domain; pa.pa_bus = bus; pa.pa_device = device; @@ -749,12 +757,16 @@ pci_reserve_resources(struct pci_attach_args *pa) { pci_chipset_tag_t pc = pa->pa_pc; pcitag_t tag = pa->pa_tag; - pcireg_t bhlc, blr, type; + pcireg_t bhlc, blr, type, bir; bus_addr_t base, limit; bus_size_t size; int reg, reg_start, reg_end; + int bus, dev, func; + int sec, sub; int flags; + pci_decompose_tag(pc, tag, &bus, &dev, &func); + bhlc = pci_conf_read(pc, tag, PCI_BHLC_REG); switch (PCI_HDRTYPE_TYPE(bhlc)) { case 0: @@ -795,8 +807,8 @@ pci_reserve_resources(struct pci_attach_args *pa) #endif if (pa->pa_memex && extent_alloc_region(pa->pa_memex, base, size, EX_NOWAIT)) { - printf("mem address conflict 0x%x/0x%x\n", - base, size); + printf("%d:%d:%d: mem address conflict 0x%x/0x%x\n", + bus, dev, func, base, size); pci_conf_write(pc, tag, reg, 0); if (type & PCI_MAPREG_MEM_TYPE_64BIT) pci_conf_write(pc, tag, reg + 4, 0); @@ -805,8 +817,8 @@ pci_reserve_resources(struct pci_attach_args *pa) case PCI_MAPREG_TYPE_IO: if (pa->pa_ioex && extent_alloc_region(pa->pa_ioex, base, size, EX_NOWAIT)) { - printf("io address conflict 0x%x/0x%x\n", - base, size); + printf("%d:%d:%d: io address conflict 0x%x/0x%x\n", + bus, dev, func, base, size); pci_conf_write(pc, tag, reg, 0); } break; @@ -832,8 +844,8 @@ pci_reserve_resources(struct pci_attach_args *pa) size = 0; if (pa->pa_ioex && base > 0 && size > 0) { if (extent_alloc_region(pa->pa_ioex, base, size, EX_NOWAIT)) { - printf("bridge io address conflict 0x%x/0x%x\n", - base, size); + printf("%d:%d:%d: bridge io address conflict 0x%x/0x%x\n", + bus, dev, func, base, size); blr &= 0xffff0000; blr |= 0x000000f0; pci_conf_write(pc, tag, PPB_REG_IOSTATUS, blr); @@ -850,8 +862,8 @@ pci_reserve_resources(struct pci_attach_args *pa) size = 0; 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); + printf("%d:%d:%d: bridge mem address conflict 0x%x/0x%x\n", + bus, dev, func, base, size); pci_conf_write(pc, tag, PPB_REG_MEM, 0x0000fff0); } } @@ -866,18 +878,30 @@ pci_reserve_resources(struct pci_attach_args *pa) 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); + printf("%d:%d:%d: bridge mem address conflict 0x%x/0x%x\n", + bus, dev, func, base, size); pci_conf_write(pc, tag, PPB_REG_PREFMEM, 0x0000fff0); } } 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); + printf("%d:%d:%d: bridge mem address conflict 0x%x/0x%x\n", + bus, dev, func, base, size); pci_conf_write(pc, tag, PPB_REG_PREFMEM, 0x0000fff0); } } + /* Figure out the bus range handled by the bridge. */ + bir = pci_conf_read(pc, tag, PPB_REG_BUSINFO); + sec = PPB_BUSINFO_SECONDARY(bir); + sub = PPB_BUSINFO_SUBORDINATE(bir); + if (pa->pa_busex && sub >= sec) { + if (extent_alloc_region(pa->pa_busex, sec, sub - sec + 1, + EX_NOWAIT)) { + printf("%d:%d:%d: bridge bus conflict %d-%d\n", + bus, dev, func, sec, sub); + } + } + return (0); } diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index 1f862f8cc0c..2aec82ec631 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pcivar.h,v 1.66 2011/05/30 19:09:46 kettenis Exp $ */ +/* $OpenBSD: pcivar.h,v 1.67 2012/09/19 23:01:21 kettenis Exp $ */ /* $NetBSD: pcivar.h,v 1.23 1997/06/06 23:48:05 thorpej Exp $ */ /* @@ -95,6 +95,7 @@ struct pcibus_attach_args { struct extent *pba_ioex; struct extent *pba_memex; struct extent *pba_pmemex; + struct extent *pba_busex; int pba_domain; /* PCI domain */ int pba_bus; /* PCI bus number */ @@ -127,6 +128,7 @@ struct pci_attach_args { struct extent *pa_ioex; struct extent *pa_memex; struct extent *pa_pmemex; + struct extent *pa_busex; u_int pa_domain; u_int pa_bus; @@ -187,6 +189,7 @@ struct pci_softc { struct extent *sc_ioex; struct extent *sc_memex; struct extent *sc_pmemex; + struct extent *sc_busex; LIST_HEAD(, pci_dev) sc_devs; int sc_domain, sc_bus, sc_maxndevs; pcitag_t *sc_bridgetag; |