diff options
author | Henric Jungheim <henric@cvs.openbsd.org> | 2003-03-06 08:26:09 +0000 |
---|---|---|
committer | Henric Jungheim <henric@cvs.openbsd.org> | 2003-03-06 08:26:09 +0000 |
commit | efca87016057d41201643e65d1f1c5d44716db0b (patch) | |
tree | 0a757cfc249bf077773a2182e04fd490183c3e6c /sys/arch/sparc64/dev/sbus.c | |
parent | 6216a22d89b680747bfb42b651aed1076b9dbf92 (diff) |
The existing IOMMU code had a rounding problem that was most noticeable
on faster systems under heavy network load. This replaces some of the
unreadable iommu functions with something a little less dense and a lot
less crash prone.
The bus_dma function pointer/cookie handling was broken. Change them
to work like the stacked bus_space drivers (where "work" is the key
word).
Tested my many (thanks).
ok jason@ deraadt@
Diffstat (limited to 'sys/arch/sparc64/dev/sbus.c')
-rw-r--r-- | sys/arch/sparc64/dev/sbus.c | 132 |
1 files changed, 79 insertions, 53 deletions
diff --git a/sys/arch/sparc64/dev/sbus.c b/sys/arch/sparc64/dev/sbus.c index c86439995ce..0bfe842cc9c 100644 --- a/sys/arch/sparc64/dev/sbus.c +++ b/sys/arch/sparc64/dev/sbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sbus.c,v 1.15 2003/02/17 01:29:20 henric Exp $ */ +/* $OpenBSD: sbus.c,v 1.16 2003/03/06 08:26:08 henric Exp $ */ /* $NetBSD: sbus.c,v 1.46 2001/10/07 20:30:41 eeh Exp $ */ /*- @@ -176,19 +176,25 @@ extern struct cfdriver sbus_cd; /* * DVMA routines */ -int sbus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t, - struct proc *, int); -void sbus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); -int sbus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, bus_dma_segment_t *, - int, bus_size_t, int); -void sbus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, bus_size_t, int); -int sbus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, bus_size_t alignment, - bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, - int flags); -void sbus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs); -int sbus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs, - size_t size, caddr_t *kvap, int flags); -void sbus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva, size_t size); +int sbus_dmamap_create(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void sbus_dmamap_destroy(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); +int sbus_dmamap_load(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +void sbus_dmamap_unload(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); +int sbus_dmamap_load_raw(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +void sbus_dmamap_sync(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); +int sbus_dmamem_alloc(bus_dma_tag_t, bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, + int nsegs, int *rsegs, int flags); +void sbus_dmamem_free(bus_dma_tag_t, bus_dma_tag_t tag, + bus_dma_segment_t *segs, int nsegs); +int sbus_dmamem_map(bus_dma_tag_t, bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, size_t size, caddr_t *kvap, int flags); +void sbus_dmamem_unmap(bus_dma_tag_t, bus_dma_tag_t tag, caddr_t kva, + size_t size); /* * Child devices receive the Sbus interrupt level in their attach @@ -806,12 +812,9 @@ sbus_alloc_dmatag(struct sbus_softc *sc) sdt->_cookie = sc; sdt->_parent = psdt; -#define PCOPY(x) sdt->x = psdt->x - PCOPY(_dmamap_create); - PCOPY(_dmamap_destroy); + sdt->_dmamap_create = sbus_dmamap_create; + sdt->_dmamap_destroy = sbus_dmamap_destroy; sdt->_dmamap_load = sbus_dmamap_load; - PCOPY(_dmamap_load_mbuf); - PCOPY(_dmamap_load_uio); sdt->_dmamap_load_raw = sbus_dmamap_load_raw; sdt->_dmamap_unload = sbus_dmamap_unload; sdt->_dmamap_sync = sbus_dmamap_sync; @@ -819,91 +822,114 @@ sbus_alloc_dmatag(struct sbus_softc *sc) sdt->_dmamem_free = sbus_dmamem_free; sdt->_dmamem_map = sbus_dmamem_map; sdt->_dmamem_unmap = sbus_dmamem_unmap; - PCOPY(_dmamem_mmap); -#undef PCOPY sc->sc_dmatag = sdt; return (sdt); } int -sbus_dmamap_load(bus_dma_tag_t tag, bus_dmamap_t map, void *buf, - bus_size_t buflen, struct proc *p, int flags) +sbus_dmamap_create(bus_dma_tag_t t, bus_dma_tag_t t0, bus_size_t size, + int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags, + bus_dmamap_t *dmamp) { - struct sbus_softc *sc = tag->_cookie; + struct sbus_softc *sc = t->_cookie; - return (iommu_dvmamap_load(tag, &sc->sc_is, map, buf, buflen, + return (iommu_dvmamap_create(t0, &sc->sc_is, &sc->sc_sb, size, + nsegments, maxsegsz, boundary, flags, dmamp)); +} + +void +sbus_dmamap_destroy(bus_dma_tag_t t, bus_dma_tag_t t0, bus_dmamap_t map) +{ + iommu_dvmamap_destroy(t0, map); +} + +int +sbus_dmamap_load(bus_dma_tag_t t, bus_dma_tag_t t0, bus_dmamap_t map, + void *buf, bus_size_t buflen, struct proc *p, int flags) +{ + struct sbus_softc *sc = t->_cookie; + + return (iommu_dvmamap_load(t0, &sc->sc_is, map, buf, buflen, p, flags)); } int -sbus_dmamap_load_raw(bus_dma_tag_t tag, bus_dmamap_t map, +sbus_dmamap_load_raw(bus_dma_tag_t t, bus_dma_tag_t t0, bus_dmamap_t map, bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags) { - struct sbus_softc *sc = tag->_cookie; + struct sbus_softc *sc = t->_cookie; - return (iommu_dvmamap_load_raw(tag, &sc->sc_is, map, segs, + return (iommu_dvmamap_load_raw(t0, &sc->sc_is, map, segs, nsegs, flags, size)); } void -sbus_dmamap_unload(bus_dma_tag_t tag, bus_dmamap_t map) +sbus_dmamap_unload(bus_dma_tag_t t, bus_dma_tag_t t0, bus_dmamap_t map) { - struct sbus_softc *sc = tag->_cookie; + struct sbus_softc *sc = t->_cookie; - iommu_dvmamap_unload(tag, &sc->sc_is, map); + iommu_dvmamap_unload(t0, &sc->sc_is, map); } void -sbus_dmamap_sync(bus_dma_tag_t tag, bus_dmamap_t map, bus_addr_t offset, - bus_size_t len, int ops) +sbus_dmamap_sync(bus_dma_tag_t t, bus_dma_tag_t t0, bus_dmamap_t map, + bus_addr_t offset, bus_size_t len, int ops) { - struct sbus_softc *sc = tag->_cookie; + struct sbus_softc *sc = t->_cookie; + + if (t->_parent == NULL) + panic("sbus_dmamap_sync: no parent"); + + for (t = t->_parent; t->_dmamap_sync == NULL; t = t->_parent) + if (t == NULL) + panic("sbus_dmamap_sync: can't find implementation"); if (ops & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)) { /* Flush the CPU then the IOMMU */ - bus_dmamap_sync(tag->_parent, map, offset, len, ops); - iommu_dvmamap_sync(tag, &sc->sc_is, map, offset, len, ops); + (*t->_dmamap_sync)(t, t0, map, offset, len, ops); + iommu_dvmamap_sync(t0, &sc->sc_is, map, offset, len, ops); } if (ops & (BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)) { /* Flush the IOMMU then the CPU */ - iommu_dvmamap_sync(tag, &sc->sc_is, map, offset, len, ops); - bus_dmamap_sync(tag->_parent, map, offset, len, ops); + iommu_dvmamap_sync(t0, &sc->sc_is, map, offset, len, ops); + (*t->_dmamap_sync)(t, t0, map, offset, len, ops); } } int -sbus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, bus_size_t alignment, - bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, - int flags) +sbus_dmamem_alloc(bus_dma_tag_t t, bus_dma_tag_t t0, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, + int nsegs, int *rsegs, int flags) { - struct sbus_softc *sc = tag->_cookie; + struct sbus_softc *sc = t->_cookie; - return (iommu_dvmamem_alloc(tag, &sc->sc_is, size, alignment, boundary, + return (iommu_dvmamem_alloc(t0, &sc->sc_is, size, alignment, boundary, segs, nsegs, rsegs, flags)); } void -sbus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs) +sbus_dmamem_free(bus_dma_tag_t t, bus_dma_tag_t t0, bus_dma_segment_t *segs, + int nsegs) { - struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; + struct sbus_softc *sc = t->_cookie; - iommu_dvmamem_free(tag, &sc->sc_is, segs, nsegs); + iommu_dvmamem_free(t0, &sc->sc_is, segs, nsegs); } int -sbus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs, - size_t size, caddr_t *kvap, int flags) +sbus_dmamem_map(bus_dma_tag_t t, bus_dma_tag_t t0, bus_dma_segment_t *segs, + int nsegs, size_t size, caddr_t *kvap, int flags) { - struct sbus_softc *sc = tag->_cookie; + struct sbus_softc *sc = t->_cookie; - return (iommu_dvmamem_map(tag, &sc->sc_is, segs, nsegs, size, + return (iommu_dvmamem_map(t0, &sc->sc_is, segs, nsegs, size, kvap, flags)); } void -sbus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva, size_t size) +sbus_dmamem_unmap(bus_dma_tag_t t, bus_dma_tag_t t0, caddr_t kva, size_t size) { - struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; + struct sbus_softc *sc = t->_cookie; - iommu_dvmamem_unmap(tag, &sc->sc_is, kva, size); + iommu_dvmamem_unmap(t0, &sc->sc_is, kva, size); } |