diff options
author | marius <marius@FreeBSD.org> | 2011-10-02 23:22:38 +0000 |
---|---|---|
committer | marius <marius@FreeBSD.org> | 2011-10-02 23:22:38 +0000 |
commit | b730263346b617e3949a799cd7cbbaec0a0faaba (patch) | |
tree | 8a3ccb0c4cbe92ab406722848f03d20132c1e280 /sys/sparc64/sbus | |
parent | 2dc050638298978fc3e396cc2d0206c599dc8c46 (diff) | |
download | FreeBSD-src-b730263346b617e3949a799cd7cbbaec0a0faaba.zip FreeBSD-src-b730263346b617e3949a799cd7cbbaec0a0faaba.tar.gz |
Make sparc64 compatible with NEW_PCIB and enable it:
- Implement bus_adjust_resource() methods as far as necessary and in non-PCI
bridge drivers as far as feasible without rototilling them.
- As NEW_PCIB does a layering violation by activating resources at layers
above pci(4) without previously bubbling up their allocation there, move
the assignment of bus tags and handles from the bus_alloc_resource() to
the bus_activate_resource() methods like at least the other NEW_PCIB
enabled architectures do. This is somewhat unfortunate as previously
sparc64 (ab)used resource activation to indicate whether SYS_RES_MEMORY
resources should be mapped into KVA, which is only necessary if their
going to be accessed via the pointer returned from rman_get_virtual() but
not for bus_space(9) as the later always uses physical access on sparc64.
Besides wasting KVA if we always map in SYS_RES_MEMORY resources, a driver
also may deliberately not map them in if the firmware already has done so,
possibly in a special way. So in order to still allow a driver to decide
whether a SYS_RES_MEMORY resource should be mapped into KVA we let it
indicate that by calling bus_space_map(9) with BUS_SPACE_MAP_LINEAR as
actually documented in the bus_space(9) page. This is implemented by
allocating a separate bus tag per SYS_RES_MEMORY resource and passing the
resource via the previously unused bus tag cookie so we later on can call
rman_set_virtual() in sparc64_bus_mem_map(). As a side effect this now
also allows to actually indicate that a SYS_RES_MEMORY resource should be
mapped in as cacheable and/or read-only via BUS_SPACE_MAP_CACHEABLE and
BUS_SPACE_MAP_READONLY respectively.
- Do some minor cleanup like taking advantage of rman_init_from_resource(),
factor out the common part of bus tag allocation into a newly added
sparc64_alloc_bus_tag(), hook up some missing newbus methods and replace
some homegrown versions with the generic counterparts etc.
- While at it, let apb_attach() (which can't use the generic NEW_PCIB code
as APB bridges just don't have the base and limit registers implemented)
regarding the config space registers cached in pcib_softc and the SYSCTL
reporting nodes set up.
Diffstat (limited to 'sys/sparc64/sbus')
-rw-r--r-- | sys/sparc64/sbus/dma_sbus.c | 1 | ||||
-rw-r--r-- | sys/sparc64/sbus/sbus.c | 158 |
2 files changed, 75 insertions, 84 deletions
diff --git a/sys/sparc64/sbus/dma_sbus.c b/sys/sparc64/sbus/dma_sbus.c index 1310f37..2594243 100644 --- a/sys/sparc64/sbus/dma_sbus.c +++ b/sys/sparc64/sbus/dma_sbus.c @@ -118,6 +118,7 @@ static device_method_t dma_methods[] = { DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c index dbe3859..f9f78da 100644 --- a/sys/sparc64/sbus/sbus.c +++ b/sys/sparc64/sbus/sbus.c @@ -108,7 +108,6 @@ struct sbus_rd { struct sbus_softc { device_t sc_dev; bus_dma_tag_t sc_cdmatag; - bus_space_tag_t sc_cbustag; int sc_clockfreq; /* clock frequency (in Hz) */ int sc_nrange; struct sbus_rd *sc_rd; @@ -137,9 +136,9 @@ static bus_read_ivar_t sbus_read_ivar; static bus_get_resource_list_t sbus_get_resource_list; static bus_setup_intr_t sbus_setup_intr; static bus_alloc_resource_t sbus_alloc_resource; -static bus_release_resource_t sbus_release_resource; static bus_activate_resource_t sbus_activate_resource; -static bus_deactivate_resource_t sbus_deactivate_resource; +static bus_adjust_resource_t sbus_adjust_resource; +static bus_release_resource_t sbus_release_resource; static bus_get_dma_tag_t sbus_get_dma_tag; static ofw_bus_get_devinfo_t sbus_get_devinfo; @@ -153,7 +152,6 @@ static void sbus_intr_assign(void *); static void sbus_intr_clear(void *); static int sbus_find_intrmap(struct sbus_softc *, u_int, bus_addr_t *, bus_addr_t *); -static bus_space_tag_t sbus_alloc_bustag(struct sbus_softc *); static driver_intr_t sbus_overtemp; static driver_intr_t sbus_pwrfail; static int sbus_print_res(struct sbus_devinfo *); @@ -171,10 +169,11 @@ static device_method_t sbus_methods[] = { DEVMETHOD(bus_probe_nomatch, sbus_probe_nomatch), DEVMETHOD(bus_read_ivar, sbus_read_ivar), DEVMETHOD(bus_alloc_resource, sbus_alloc_resource), - DEVMETHOD(bus_activate_resource, sbus_activate_resource), - DEVMETHOD(bus_deactivate_resource, sbus_deactivate_resource), + DEVMETHOD(bus_activate_resource, sbus_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_adjust_resource, sbus_adjust_resource), DEVMETHOD(bus_release_resource, sbus_release_resource), - DEVMETHOD(bus_setup_intr, sbus_setup_intr), + DEVMETHOD(bus_setup_intr, sbus_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_get_resource_list, sbus_get_resource_list), @@ -284,7 +283,6 @@ sbus_attach(device_t dev) if (OF_getprop(node, "interrupts", &prop, sizeof(prop)) == -1) panic("%s: cannot get IGN", __func__); sc->sc_ign = INTIGN(prop); - sc->sc_cbustag = sbus_alloc_bustag(sc); /* * Record clock frequency for synchronous SCSI. @@ -343,7 +341,6 @@ sbus_attach(device_t dev) sc->sc_burst = (SBUS_BURST64_DEF << SBUS_BURST64_SHIFT) | SBUS_BURST_DEF; - /* initalise the IOMMU */ /* punch in our copies */ @@ -375,7 +372,7 @@ sbus_attach(device_t dev) sc->sc_cdmatag->dt_cookie = &sc->sc_is; sc->sc_cdmatag->dt_mt = &iommu_dma_methods; - /* + /* * Hunt through all the interrupt mapping regs and register our * interrupt controller for the corresponding interrupt vectors. * We do this early in order to be able to catch stray interrupts. @@ -701,12 +698,12 @@ sbus_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, /* * Make sure the vector is fully specified and we registered * our interrupt controller for it. - */ + */ vec = rman_get_start(ires); if (INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &sbus_ic) { device_printf(dev, "invalid interrupt vector 0x%lx\n", vec); - return (EINVAL); - } + return (EINVAL); + } return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr, arg, cookiep)); } @@ -721,14 +718,12 @@ sbus_alloc_resource(device_t bus, device_t child, int type, int *rid, struct resource_list *rl; struct resource_list_entry *rle; device_t schild; - bus_space_handle_t bh; bus_addr_t toffs; bus_size_t tend; int i, slot; - int isdefault, needactivate, passthrough; + int isdefault, passthrough; isdefault = (start == 0UL && end == ~0UL); - needactivate = flags & RF_ACTIVE; passthrough = (device_get_parent(child) != bus); rle = NULL; sc = device_get_softc(bus); @@ -751,7 +746,6 @@ sbus_alloc_resource(device_t bus, device_t child, int type, int *rid, } } rm = NULL; - bh = toffs = tend = 0; schild = child; while (device_get_parent(schild) != bus) schild = device_get_parent(schild); @@ -768,24 +762,21 @@ sbus_alloc_resource(device_t bus, device_t child, int type, int *rid, toffs = start - sc->sc_rd[i].rd_coffset; tend = end - sc->sc_rd[i].rd_coffset; rm = &sc->sc_rd[i].rd_rman; - bh = sc->sc_rd[i].rd_bushandle; break; } if (rm == NULL) return (NULL); - flags &= ~RF_ACTIVE; - rv = rman_reserve_resource(rm, toffs, tend, count, flags, - child); + + rv = rman_reserve_resource(rm, toffs, tend, count, flags & + ~RF_ACTIVE, child); if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); - rman_set_bustag(rv, sc->sc_cbustag); - rman_set_bushandle(rv, bh + rman_get_start(rv)); - if (needactivate) { - if (bus_activate_resource(child, type, *rid, rv)) { - rman_release_resource(rv); - return (NULL); - } + + if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, + type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); } if (!passthrough) rle->res = rv; @@ -799,41 +790,53 @@ static int sbus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { - void *p; - int error; + struct sbus_softc *sc; + struct bus_space_tag *tag; + int i; - if (type == SYS_RES_IRQ) { - return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), - child, type, rid, r)); - } - if (type == SYS_RES_MEMORY) { - /* - * Need to memory-map the device space, as some drivers - * depend on the virtual address being set and usable. - */ - error = sparc64_bus_mem_map(rman_get_bustag(r), - rman_get_bushandle(r), rman_get_size(r), 0, 0, &p); - if (error != 0) - return (error); - rman_set_virtual(r, p); + switch (type) { + case SYS_RES_IRQ: + return (bus_generic_activate_resource(bus, child, type, rid, + r)); + case SYS_RES_MEMORY: + sc = device_get_softc(bus); + for (i = 0; i < sc->sc_nrange; i++) { + if (rman_is_region_manager(r, + &sc->sc_rd[i].rd_rman) != 0) { + tag = sparc64_alloc_bus_tag(r, + rman_get_bustag(sc->sc_sysio_res), + SBUS_BUS_SPACE, NULL); + if (tag == NULL) + return (ENOMEM); + rman_set_bustag(r, tag); + rman_set_bushandle(r, + sc->sc_rd[i].rd_bushandle + + rman_get_start(r)); + return (rman_activate_resource(r)); + } + } + /* FALLTHROUGH */ + default: + return (EINVAL); } - return (rman_activate_resource(r)); } static int -sbus_deactivate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) +sbus_adjust_resource(device_t bus, device_t child, int type, + struct resource *r, u_long start, u_long end) { + struct sbus_softc *sc; + int i; - if (type == SYS_RES_IRQ) { - return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), - child, type, rid, r)); - } if (type == SYS_RES_MEMORY) { - sparc64_bus_mem_unmap(rman_get_virtual(r), rman_get_size(r)); - rman_set_virtual(r, NULL); + sc = device_get_softc(bus); + for (i = 0; i < sc->sc_nrange; i++) + if (rman_is_region_manager(r, + &sc->sc_rd[i].rd_rman) != 0) + return (rman_adjust_resource(r, start, end)); + return (EINVAL); } - return (rman_deactivate_resource(r)); + return (bus_generic_adjust_resource(bus, child, type, r, start, end)); } static int @@ -846,23 +849,26 @@ sbus_release_resource(device_t bus, device_t child, int type, int rid, passthrough = (device_get_parent(child) != bus); rl = BUS_GET_RESOURCE_LIST(bus, child); - if (type == SYS_RES_IRQ) - return (resource_list_release(rl, bus, child, type, rid, r)); - if ((rman_get_flags(r) & RF_ACTIVE) != 0) { - error = bus_deactivate_resource(child, type, rid, r); + if (type == SYS_RES_MEMORY) { + if ((rman_get_flags(r) & RF_ACTIVE) != 0) { + error = bus_deactivate_resource(child, type, rid, r); + if (error) + return (error); + } + error = rman_release_resource(r); if (error != 0) return (error); + if (!passthrough) { + rle = resource_list_find(rl, type, rid); + KASSERT(rle != NULL, + ("%s: resource entry not found!", __func__)); + KASSERT(rle->res != NULL, + ("%s: resource entry is not busy", __func__)); + rle->res = NULL; + } + return (0); } - error = rman_release_resource(r); - if (error != 0 || passthrough) - return (error); - rle = resource_list_find(rl, type, rid); - if (rle == NULL) - panic("%s: cannot find resource", __func__); - if (rle->res == NULL) - panic("%s: resource entry is not busy", __func__); - rle->res = NULL; - return (0); + return (resource_list_release(rl, bus, child, type, rid, r)); } static bus_dma_tag_t @@ -918,22 +924,6 @@ sbus_pwrfail(void *arg) shutdown_nice(0); } -static bus_space_tag_t -sbus_alloc_bustag(struct sbus_softc *sc) -{ - bus_space_tag_t sbt; - - sbt = (bus_space_tag_t)malloc(sizeof(struct bus_space_tag), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (sbt == NULL) - panic("%s: out of memory", __func__); - - sbt->bst_cookie = sc; - sbt->bst_parent = rman_get_bustag(sc->sc_sysio_res); - sbt->bst_type = SBUS_BUS_SPACE; - return (sbt); -} - static int sbus_print_res(struct sbus_devinfo *sdi) { |