diff options
author | scottl <scottl@FreeBSD.org> | 2003-01-29 07:25:27 +0000 |
---|---|---|
committer | scottl <scottl@FreeBSD.org> | 2003-01-29 07:25:27 +0000 |
commit | 27cbbd88a297ee95096971d969fc28f1f2c7a09c (patch) | |
tree | d21203bdfa9f1d0c2ea53afbd752b1326d109e6c | |
parent | 1bc11f23c6b4c14967b2c1745df47caa7147c66e (diff) | |
download | FreeBSD-src-27cbbd88a297ee95096971d969fc28f1f2c7a09c.zip FreeBSD-src-27cbbd88a297ee95096971d969fc28f1f2c7a09c.tar.gz |
Implement bus_dmamem_alloc_size() and bus_dmamem_free_size() as
counterparts to bus_dmamem_alloc() and bus_dmamem_free(). This allows
the caller to specify the size of the allocation instead of it defaulting
to the max_size field of the busdma tag.
This is intended to aid in converting drivers to busdma. Lots of
hardware cannot understand scatter/gather lists, which forces the
driver to copy the i/o buffers to a single contiguous region
before sending it to the hardware. Without these new methods, this
would require a new busdma tag for each operation, or a complex
internal allocator/cache for each driver.
Allocations greater than PAGE_SIZE are rounded up to the next
PAGE_SIZE by contigmalloc(), so this is not suitable for multiple
static allocations that would be better served by a single
fixed-length subdivided allocation.
Reviewed by: jake (sparc64)
-rw-r--r-- | sys/alpha/alpha/busdma_machdep.c | 34 | ||||
-rw-r--r-- | sys/alpha/include/bus.h | 6 | ||||
-rw-r--r-- | sys/amd64/amd64/busdma_machdep.c | 34 | ||||
-rw-r--r-- | sys/amd64/include/bus_dma.h | 6 | ||||
-rw-r--r-- | sys/i386/i386/busdma_machdep.c | 34 | ||||
-rw-r--r-- | sys/i386/include/bus_dma.h | 6 | ||||
-rw-r--r-- | sys/sparc64/include/bus.h | 30 | ||||
-rw-r--r-- | sys/sparc64/include/iommuvar.h | 4 | ||||
-rw-r--r-- | sys/sparc64/pci/psycho.c | 27 | ||||
-rw-r--r-- | sys/sparc64/sbus/sbus.c | 25 | ||||
-rw-r--r-- | sys/sparc64/sparc64/bus_machdep.c | 44 | ||||
-rw-r--r-- | sys/sparc64/sparc64/iommu.c | 31 | ||||
-rw-r--r-- | sys/sys/bus_dma.h | 6 |
13 files changed, 248 insertions, 39 deletions
diff --git a/sys/alpha/alpha/busdma_machdep.c b/sys/alpha/alpha/busdma_machdep.c index 9de3342..3fcbc30 100644 --- a/sys/alpha/alpha/busdma_machdep.c +++ b/sys/alpha/alpha/busdma_machdep.c @@ -350,14 +350,18 @@ bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) * A dmamap to for use with dmamap_load is also allocated. */ int -bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, - bus_dmamap_t *mapp) +bus_dmamem_alloc_size(bus_dma_tag_t dmat, void** vaddr, int flags, + bus_dmamap_t *mapp, bus_size_t size) { + + if (size > dmat->maxsize) + return (ENOMEM); + /* If we succeed, no mapping/bouncing will be required */ *mapp = &nobounce_dmamap; - if ((dmat->maxsize <= PAGE_SIZE) && dmat->lowaddr >= ptoa(Maxmem)) { - *vaddr = malloc(dmat->maxsize, M_DEVBUF, + if ((size <= PAGE_SIZE) && dmat->lowaddr >= ptoa(Maxmem)) { + *vaddr = malloc(size, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : 0); } else { /* @@ -365,7 +369,7 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, * and handles multi-seg allocations. Nobody is doing * multi-seg allocations yet though. */ - *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, + *vaddr = contigmalloc(size, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : 0, 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul, dmat->boundary); @@ -375,12 +379,20 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, return (0); } +int +bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, + bus_dmamap_t *mapp) +{ + return (bus_dmamem_alloc_size(dmat, vaddr, flags, mapp, dmat->maxsize)); +} + /* * Free a piece of memory and it's allociated dmamap, that was allocated * via bus_dmamem_alloc. */ void -bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) +bus_dmamem_free_size(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map, + bus_size_t size) { /* * dmamem does not need to be bounced, so the map should be @@ -388,10 +400,16 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) */ if (map != &nobounce_dmamap) panic("bus_dmamem_free: Invalid map freed\n"); - if ((dmat->maxsize <= PAGE_SIZE) && dmat->lowaddr >= ptoa(Maxmem)) + if ((size <= PAGE_SIZE) && dmat->lowaddr >= ptoa(Maxmem)) free(vaddr, M_DEVBUF); else - contigfree(vaddr, dmat->maxsize, M_DEVBUF); + contigfree(vaddr, size, M_DEVBUF); +} + +void +bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) +{ + bus_dmamem_free_size(dmat, vaddr, map, dmat->maxsize); } #define BUS_DMAMAP_NSEGS ((BUS_SPACE_MAXSIZE / PAGE_SIZE) + 1) diff --git a/sys/alpha/include/bus.h b/sys/alpha/include/bus.h index 784eda3..3a87d1a 100644 --- a/sys/alpha/include/bus.h +++ b/sys/alpha/include/bus.h @@ -571,6 +571,9 @@ int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map); * bus device space based on the constraints lited in the dma tag. * A dmamap to for use with dmamap_load is also allocated. */ +int bus_dmamem_alloc_size(bus_dma_tag_t dmat, void** vaddr, int flags, + bus_dmamap_t *mapp, bus_size_t size); + int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, bus_dmamap_t *mapp); @@ -578,6 +581,9 @@ int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, * Free a piece of memory and it's allociated dmamap, that was allocated * via bus_dmamem_alloc. */ +void bus_dmamem_free_size(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map, + bus_size_t size); + void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map); /* diff --git a/sys/amd64/amd64/busdma_machdep.c b/sys/amd64/amd64/busdma_machdep.c index eb6cc9d..c55469f 100644 --- a/sys/amd64/amd64/busdma_machdep.c +++ b/sys/amd64/amd64/busdma_machdep.c @@ -331,14 +331,18 @@ bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) * A dmamap to for use with dmamap_load is also allocated. */ int -bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, - bus_dmamap_t *mapp) +bus_dmamem_alloc_size(bus_dma_tag_t dmat, void** vaddr, int flags, + bus_dmamap_t *mapp, bus_size_t size) { + + if (size > dmat->maxsize) + return (ENOMEM); + /* If we succeed, no mapping/bouncing will be required */ *mapp = NULL; - if ((dmat->maxsize <= PAGE_SIZE) && dmat->lowaddr >= ptoa(Maxmem)) { - *vaddr = malloc(dmat->maxsize, M_DEVBUF, + if ((size <= PAGE_SIZE) && dmat->lowaddr >= ptoa(Maxmem)) { + *vaddr = malloc(size, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : 0); } else { /* @@ -346,7 +350,7 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, * and handles multi-seg allocations. Nobody is doing * multi-seg allocations yet though. */ - *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, + *vaddr = contigmalloc(size, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : 0, 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul, dmat->boundary); @@ -356,12 +360,20 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, return (0); } +int +bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, + bus_dmamap_t *mapp) +{ + return (bus_dmamem_alloc_size(dmat, vaddr, flags, mapp, dmat->maxsize)); +} + /* * Free a piece of memory and it's allociated dmamap, that was allocated * via bus_dmamem_alloc. Make the same choice for free/contigfree. */ void -bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) +bus_dmamem_free_size(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map, + bus_size_t size) { /* * dmamem does not need to be bounced, so the map should be @@ -369,10 +381,16 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) */ if (map != NULL) panic("bus_dmamem_free: Invalid map freed\n"); - if ((dmat->maxsize <= PAGE_SIZE) && dmat->lowaddr >= ptoa(Maxmem)) + if ((size <= PAGE_SIZE) && dmat->lowaddr >= ptoa(Maxmem)) free(vaddr, M_DEVBUF); else - contigfree(vaddr, dmat->maxsize, M_DEVBUF); + contigfree(vaddr, size, M_DEVBUF); +} + +void +bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) +{ + bus_dmamem_free_size(dmat, vaddr, map, dmat->maxsize); } #define BUS_DMAMAP_NSEGS ((BUS_SPACE_MAXSIZE / PAGE_SIZE) + 1) diff --git a/sys/amd64/include/bus_dma.h b/sys/amd64/include/bus_dma.h index 6790731..4a1740d 100644 --- a/sys/amd64/include/bus_dma.h +++ b/sys/amd64/include/bus_dma.h @@ -180,6 +180,9 @@ int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map); * bus device space based on the constraints lited in the dma tag. * A dmamap to for use with dmamap_load is also allocated. */ +int bus_dmamem_alloc_size(bus_dma_tag_t dmat, void** vaddr, int flags, + bus_dmamap_t *mapp, bus_size_t size); + int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, bus_dmamap_t *mapp); @@ -187,6 +190,9 @@ int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, * Free a piece of memory and it's allociated dmamap, that was allocated * via bus_dmamem_alloc. */ +void bus_dmamem_free_size(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map, + bus_size_t size); + void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map); /* diff --git a/sys/i386/i386/busdma_machdep.c b/sys/i386/i386/busdma_machdep.c index eb6cc9d..c55469f 100644 --- a/sys/i386/i386/busdma_machdep.c +++ b/sys/i386/i386/busdma_machdep.c @@ -331,14 +331,18 @@ bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) * A dmamap to for use with dmamap_load is also allocated. */ int -bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, - bus_dmamap_t *mapp) +bus_dmamem_alloc_size(bus_dma_tag_t dmat, void** vaddr, int flags, + bus_dmamap_t *mapp, bus_size_t size) { + + if (size > dmat->maxsize) + return (ENOMEM); + /* If we succeed, no mapping/bouncing will be required */ *mapp = NULL; - if ((dmat->maxsize <= PAGE_SIZE) && dmat->lowaddr >= ptoa(Maxmem)) { - *vaddr = malloc(dmat->maxsize, M_DEVBUF, + if ((size <= PAGE_SIZE) && dmat->lowaddr >= ptoa(Maxmem)) { + *vaddr = malloc(size, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : 0); } else { /* @@ -346,7 +350,7 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, * and handles multi-seg allocations. Nobody is doing * multi-seg allocations yet though. */ - *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, + *vaddr = contigmalloc(size, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : 0, 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul, dmat->boundary); @@ -356,12 +360,20 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, return (0); } +int +bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, + bus_dmamap_t *mapp) +{ + return (bus_dmamem_alloc_size(dmat, vaddr, flags, mapp, dmat->maxsize)); +} + /* * Free a piece of memory and it's allociated dmamap, that was allocated * via bus_dmamem_alloc. Make the same choice for free/contigfree. */ void -bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) +bus_dmamem_free_size(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map, + bus_size_t size) { /* * dmamem does not need to be bounced, so the map should be @@ -369,10 +381,16 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) */ if (map != NULL) panic("bus_dmamem_free: Invalid map freed\n"); - if ((dmat->maxsize <= PAGE_SIZE) && dmat->lowaddr >= ptoa(Maxmem)) + if ((size <= PAGE_SIZE) && dmat->lowaddr >= ptoa(Maxmem)) free(vaddr, M_DEVBUF); else - contigfree(vaddr, dmat->maxsize, M_DEVBUF); + contigfree(vaddr, size, M_DEVBUF); +} + +void +bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) +{ + bus_dmamem_free_size(dmat, vaddr, map, dmat->maxsize); } #define BUS_DMAMAP_NSEGS ((BUS_SPACE_MAXSIZE / PAGE_SIZE) + 1) diff --git a/sys/i386/include/bus_dma.h b/sys/i386/include/bus_dma.h index 6790731..4a1740d 100644 --- a/sys/i386/include/bus_dma.h +++ b/sys/i386/include/bus_dma.h @@ -180,6 +180,9 @@ int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map); * bus device space based on the constraints lited in the dma tag. * A dmamap to for use with dmamap_load is also allocated. */ +int bus_dmamem_alloc_size(bus_dma_tag_t dmat, void** vaddr, int flags, + bus_dmamap_t *mapp, bus_size_t size); + int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, bus_dmamap_t *mapp); @@ -187,6 +190,9 @@ int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, * Free a piece of memory and it's allociated dmamap, that was allocated * via bus_dmamem_alloc. */ +void bus_dmamem_free_size(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map, + bus_size_t size); + void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map); /* diff --git a/sys/sparc64/include/bus.h b/sys/sparc64/include/bus.h index 95089fa..2a90c01 100644 --- a/sys/sparc64/include/bus.h +++ b/sys/sparc64/include/bus.h @@ -971,8 +971,12 @@ struct bus_dma_tag { /* * DMA memory utility functions. */ + int (*dt_dmamem_alloc_size)(bus_dma_tag_t, bus_dma_tag_t, void **, + int, bus_dmamap_t *, bus_size_t size); int (*dt_dmamem_alloc)(bus_dma_tag_t, bus_dma_tag_t, void **, int, bus_dmamap_t *); + void (*dt_dmamem_free_size)(bus_dma_tag_t, bus_dma_tag_t, void *, + bus_dmamap_t, bus_size_t size); void (*dt_dmamem_free)(bus_dma_tag_t, bus_dma_tag_t, void *, bus_dmamap_t); }; @@ -1084,6 +1088,19 @@ sparc64_dmamap_sync(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t m, sparc64_dmamap_sync((t), (t), (m), (op)) static __inline int +sparc64_dmamem_alloc_size(bus_dma_tag_t pt, bus_dma_tag_t dt, void **v, int f, + bus_dmamap_t *m, bus_size_t s) +{ + bus_dma_tag_t lt; + + for (lt = pt; lt->dmamem_alloc == NULL; lt = lt->parent) + ; + return ((*lt->dmamem_alloc_size)(lt, dt, v, f, m, s)); +} +#define bus_dmamem_alloc_size(t, v, f, m, s) \ + sparc64_dmamem_alloc_size((t), (t), (v), (f), (m), (s)) + +static __inline int sparc64_dmamem_alloc(bus_dma_tag_t pt, bus_dma_tag_t dt, void **v, int f, bus_dmamap_t *m) { @@ -1097,6 +1114,19 @@ sparc64_dmamem_alloc(bus_dma_tag_t pt, bus_dma_tag_t dt, void **v, int f, sparc64_dmamem_alloc((t), (t), (v), (f), (m)) static __inline void +sparc64_dmamem_free_size(bus_dma_tag_t pt, bus_dma_tag_t dt, void *v, + bus_dmamap_t m, bus_size_t s) +{ + bus_dma_tag_t lt; + + for (lt = pt; lt->dmamem_free == NULL; lt = lt->parent) + ; + (*lt->dmamem_free_size)(lt, dt, v, m, s); +} +#define bus_dmamem_free_size(t, v, m, s) \ + sparc64_dmamem_free_size((t), (t), (v), (m), (s)) + +static __inline void sparc64_dmamem_free(bus_dma_tag_t pt, bus_dma_tag_t dt, void *v, bus_dmamap_t m) { diff --git a/sys/sparc64/include/iommuvar.h b/sys/sparc64/include/iommuvar.h index 1052ba3..3c99822 100644 --- a/sys/sparc64/include/iommuvar.h +++ b/sys/sparc64/include/iommuvar.h @@ -95,8 +95,12 @@ void iommu_dvmamap_unload(bus_dma_tag_t, bus_dma_tag_t, struct iommu_state *, bus_dmamap_t); void iommu_dvmamap_sync(bus_dma_tag_t, bus_dma_tag_t, struct iommu_state *, bus_dmamap_t, bus_dmasync_op_t); +int iommu_dvmamem_alloc_size(bus_dma_tag_t, bus_dma_tag_t, struct iommu_state *, + void **, int, bus_dmamap_t *, bus_size_t size); int iommu_dvmamem_alloc(bus_dma_tag_t, bus_dma_tag_t, struct iommu_state *, void **, int, bus_dmamap_t *); +void iommu_dvmamem_free_size(bus_dma_tag_t, bus_dma_tag_t, struct iommu_state *, + void *, bus_dmamap_t, bus_size_t size); void iommu_dvmamem_free(bus_dma_tag_t, bus_dma_tag_t, struct iommu_state *, void *, bus_dmamap_t); diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c index 9b32b95..418b81c 100644 --- a/sys/sparc64/pci/psycho.c +++ b/sys/sparc64/pci/psycho.c @@ -113,8 +113,12 @@ static int psycho_dmamap_load_uio(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, static void psycho_dmamap_unload(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); static void psycho_dmamap_sync(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t); +static int psycho_dmamem_alloc_size(bus_dma_tag_t, bus_dma_tag_t, void **, int, + bus_dmamap_t *, bus_size_t size); static int psycho_dmamem_alloc(bus_dma_tag_t, bus_dma_tag_t, void **, int, bus_dmamap_t *); +static void psycho_dmamem_free_size(bus_dma_tag_t, bus_dma_tag_t, void *, + bus_dmamap_t, bus_size_t size); static void psycho_dmamem_free(bus_dma_tag_t, bus_dma_tag_t, void *, bus_dmamap_t); @@ -497,7 +501,9 @@ psycho_attach(device_t dev) sc->sc_dmat->dt_dmamap_load_uio = psycho_dmamap_load_uio; sc->sc_dmat->dt_dmamap_unload = psycho_dmamap_unload; sc->sc_dmat->dt_dmamap_sync = psycho_dmamap_sync; + sc->sc_dmat->dt_dmamem_alloc_size = psycho_dmamem_alloc_size; sc->sc_dmat->dt_dmamem_alloc = psycho_dmamem_alloc; + sc->sc_dmat->dt_dmamem_free_size = psycho_dmamem_free_size; sc->sc_dmat->dt_dmamem_free = psycho_dmamem_free; /* XXX: register as root dma tag (kluge). */ sparc64_root_dma_tag = sc->sc_dmat; @@ -1314,6 +1320,17 @@ psycho_alloc_bus_tag(struct psycho_softc *sc, int type) * hooks into the iommu dvma calls. */ static int +psycho_dmamem_alloc_size(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void **vaddr, + int flags, bus_dmamap_t *mapp, bus_size_t size) +{ + struct psycho_softc *sc; + + sc = (struct psycho_softc *)pdmat->cookie; + return (iommu_dvmamem_alloc_size(pdmat, ddmat, sc->sc_is, vaddr, flags, + mapp, size)); +} + +static int psycho_dmamem_alloc(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void **vaddr, int flags, bus_dmamap_t *mapp) { @@ -1325,6 +1342,16 @@ psycho_dmamem_alloc(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void **vaddr, } static void +psycho_dmamem_free_size(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void *vaddr, + bus_dmamap_t map, bus_size_t size) +{ + struct psycho_softc *sc; + + sc = (struct psycho_softc *)pdmat->cookie; + iommu_dvmamem_free_size(pdmat, ddmat, sc->sc_is, vaddr, map, size); +} + +static void psycho_dmamem_free(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void *vaddr, bus_dmamap_t map) { diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c index d76efb5..2689090 100644 --- a/sys/sparc64/sbus/sbus.c +++ b/sys/sparc64/sbus/sbus.c @@ -244,8 +244,12 @@ static int sbus_dmamap_load_uio(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, static void sbus_dmamap_unload(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); static void sbus_dmamap_sync(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t); +static int sbus_dmamem_alloc_size(bus_dma_tag_t, bus_dma_tag_t, void **, int, + bus_dmamap_t *, bus_size_t size); static int sbus_dmamem_alloc(bus_dma_tag_t, bus_dma_tag_t, void **, int, bus_dmamap_t *); +static void sbus_dmamem_free_size(bus_dma_tag_t, bus_dma_tag_t, void *, + bus_dmamap_t, bus_size_t); static void sbus_dmamem_free(bus_dma_tag_t, bus_dma_tag_t, void *, bus_dmamap_t); @@ -349,7 +353,9 @@ sbus_probe(device_t dev) sc->sc_cdmatag->dt_dmamap_load_uio = sbus_dmamap_load_uio; sc->sc_cdmatag->dt_dmamap_unload = sbus_dmamap_unload; sc->sc_cdmatag->dt_dmamap_sync = sbus_dmamap_sync; + sc->sc_cdmatag->dt_dmamem_alloc_size = sbus_dmamem_alloc_size; sc->sc_cdmatag->dt_dmamem_alloc = sbus_dmamem_alloc; + sc->sc_cdmatag->dt_dmamem_free_size = sbus_dmamem_free_size; sc->sc_cdmatag->dt_dmamem_free = sbus_dmamem_free; /* XXX: register as root dma tag (kluge). */ sparc64_root_dma_tag = sc->sc_cdmatag; @@ -988,6 +994,16 @@ sbus_dmamap_sync(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, bus_dmamap_t map, } static int +sbus_dmamem_alloc_size(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void **vaddr, + int flags, bus_dmamap_t *mapp, bus_size_t size) +{ + struct sbus_softc *sc = (struct sbus_softc *)pdmat->cookie; + + return (iommu_dvmamem_alloc_size(pdmat, ddmat, &sc->sc_is, vaddr, flags, + mapp, size)); +} + +static int sbus_dmamem_alloc(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void **vaddr, int flags, bus_dmamap_t *mapp) { @@ -998,6 +1014,15 @@ sbus_dmamem_alloc(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void **vaddr, } static void +sbus_dmamem_free_size(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void *vaddr, + bus_dmamap_t map, bus_size_t size) +{ + struct sbus_softc *sc = (struct sbus_softc *)pdmat->cookie; + + iommu_dvmamem_free_size(pdmat, ddmat, &sc->sc_is, vaddr, map, size); +} + +static void sbus_dmamem_free(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void *vaddr, bus_dmamap_t map) { diff --git a/sys/sparc64/sparc64/bus_machdep.c b/sys/sparc64/sparc64/bus_machdep.c index e63a844..92afbcc 100644 --- a/sys/sparc64/sparc64/bus_machdep.c +++ b/sys/sparc64/sparc64/bus_machdep.c @@ -168,8 +168,12 @@ static int nexus_dmamap_load_uio(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, static void nexus_dmamap_unload(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); static void nexus_dmamap_sync(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t); +static int nexus_dmamem_alloc_size(bus_dma_tag_t, bus_dma_tag_t, void **, int, + bus_dmamap_t *, u_long size); static int nexus_dmamem_alloc(bus_dma_tag_t, bus_dma_tag_t, void **, int, bus_dmamap_t *); +static void nexus_dmamem_free_size(bus_dma_tag_t, bus_dma_tag_t, void *, + bus_dmamap_t, u_long size); static void nexus_dmamem_free(bus_dma_tag_t, bus_dma_tag_t, void *, bus_dmamap_t); @@ -222,7 +226,9 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, newtag->dt_dmamap_load_uio = NULL; newtag->dt_dmamap_unload = NULL; newtag->dt_dmamap_sync = NULL; + newtag->dt_dmamem_alloc_size = NULL; newtag->dt_dmamem_alloc = NULL; + newtag->dt_dmamem_free_size = NULL; newtag->dt_dmamem_free = NULL; /* Take into account any restrictions imposed by our parent tag */ @@ -604,12 +610,15 @@ sparc64_dmamem_free_map(bus_dma_tag_t dmat, bus_dmamap_t map) * by bus-specific DMA memory allocation functions. */ static int -nexus_dmamem_alloc(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void **vaddr, - int flags, bus_dmamap_t *mapp) +nexus_dmamem_alloc_size(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void **vaddr, + int flags, bus_dmamap_t *mapp, bus_size_t size) { - if ((ddmat->dt_maxsize <= PAGE_SIZE)) { - *vaddr = malloc(ddmat->dt_maxsize, M_DEVBUF, + if (size > ddmat->dt_maxsize) + return (ENOMEM); + + if ((size <= PAGE_SIZE)) { + *vaddr = malloc(size, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : 0); } else { /* @@ -617,7 +626,7 @@ nexus_dmamem_alloc(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void **vaddr, * and handles multi-seg allocations. Nobody is doing multi-seg * allocations yet though. */ - *vaddr = contigmalloc(ddmat->dt_maxsize, M_DEVBUF, + *vaddr = contigmalloc(size, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : 0, 0ul, ddmat->dt_lowaddr, ddmat->dt_alignment ? ddmat->dt_alignment : 1UL, @@ -630,20 +639,35 @@ nexus_dmamem_alloc(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void **vaddr, return (0); } +static int +nexus_dmamem_alloc(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void **vaddr, + int flags, bus_dmamap_t *mapp) +{ + return (sparc64_dmamem_alloc_size(pdmat, ddmat, vaddr, flags, mapp, + ddmat->maxsize)); +} + /* * Common function for freeing DMA-safe memory. May be called by * bus-specific DMA memory free functions. */ static void -nexus_dmamem_free(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void *vaddr, - bus_dmamap_t map) +nexus_dmamem_free_size(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void *vaddr, + bus_dmamap_t map, bus_size_t size) { sparc64_dmamem_free_map(ddmat, map); - if ((ddmat->dt_maxsize <= PAGE_SIZE)) + if ((size <= PAGE_SIZE)) free(vaddr, M_DEVBUF); else - contigfree(vaddr, ddmat->dt_maxsize, M_DEVBUF); + contigfree(vaddr, size, M_DEVBUF); +} + +static void +nexus_dmamem_free(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, void *vaddr, + bus_dmamap_t map) +{ + sparc64_dmamem_free_size(pdmat, ddmat, vaddr, map, ddmat->dt_maxsize); } struct bus_dma_tag nexus_dmatag = { @@ -669,7 +693,9 @@ struct bus_dma_tag nexus_dmatag = { nexus_dmamap_unload, nexus_dmamap_sync, + nexus_dmamem_alloc_size, nexus_dmamem_alloc, + nexus_dmamem_free_size, nexus_dmamem_free, }; diff --git a/sys/sparc64/sparc64/iommu.c b/sys/sparc64/sparc64/iommu.c index ff707d3..375f894 100644 --- a/sys/sparc64/sparc64/iommu.c +++ b/sys/sparc64/sparc64/iommu.c @@ -668,18 +668,22 @@ iommu_dvma_vallocseg(bus_dma_tag_t dt, struct iommu_state *is, bus_dmamap_t map, } int -iommu_dvmamem_alloc(bus_dma_tag_t pt, bus_dma_tag_t dt, struct iommu_state *is, - void **vaddr, int flags, bus_dmamap_t *mapp) +iommu_dvmamem_alloc_size(bus_dma_tag_t pt, bus_dma_tag_t dt, + struct iommu_state *is, void **vaddr, int flags, bus_dmamap_t *mapp, + bus_size_t size) { int error; + if (size > dt->maxsize) + return (ENOMEM); + /* * XXX: This will break for 32 bit transfers on machines with more than * 16G (1 << 34 bytes) of memory. */ if ((error = sparc64_dmamem_alloc_map(dt, mapp)) != 0) return (error); - if ((*vaddr = malloc(dt->dt_maxsize, M_IOMMU, + if ((*vaddr = malloc(size, M_IOMMU, (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : 0)) == NULL) { error = ENOMEM; sparc64_dmamem_free_map(dt, *mapp); @@ -690,13 +694,21 @@ iommu_dvmamem_alloc(bus_dma_tag_t pt, bus_dma_tag_t dt, struct iommu_state *is, * Try to preallocate DVMA space. If this fails, it is retried at load * time. */ - iommu_dvma_valloc(dt, is, *mapp, IOMMU_SIZE_ROUNDUP(dt->dt_maxsize)); + iommu_dvma_valloc(dt, is, *mapp, IOMMU_SIZE_ROUNDUP(size)); return (0); } +int +iommu_dvmamem_alloc(bus_dma_tag_t pt, bus_dma_tag_t dt, struct iommu_state *is, + void **vaddr, int flags, bus_dmamap_t *mapp) +{ + return (iommu_dvmamem_alloc_size(pt, dt, is, vaddr, flags, mapp, + dt->maxsize)); +} + void -iommu_dvmamem_free(bus_dma_tag_t pt, bus_dma_tag_t dt, struct iommu_state *is, - void *vaddr, bus_dmamap_t map) +iommu_dvmamem_free_size(bus_dma_tag_t pt, bus_dma_tag_t dt, + struct iommu_state *is, void *vaddr, bus_dmamap_t map, bus_size_t size) { iommu_dvma_vfree(is, map); @@ -704,6 +716,13 @@ iommu_dvmamem_free(bus_dma_tag_t pt, bus_dma_tag_t dt, struct iommu_state *is, free(vaddr, M_IOMMU); } +void +iommu_dvmamem_free(bus_dma_tag_t pt, bus_dma_tag_t dt, struct iommu_state *is, + void *vaddr, bus_dmamap_t map) +{ + iommu_dvmamem_free_size(pt, dt, is, vaddr, map, dt->maxsize); +} + int iommu_dvmamap_create(bus_dma_tag_t pt, bus_dma_tag_t dt, struct iommu_state *is, int flags, bus_dmamap_t *mapp) diff --git a/sys/sys/bus_dma.h b/sys/sys/bus_dma.h index 6790731..4a1740d 100644 --- a/sys/sys/bus_dma.h +++ b/sys/sys/bus_dma.h @@ -180,6 +180,9 @@ int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map); * bus device space based on the constraints lited in the dma tag. * A dmamap to for use with dmamap_load is also allocated. */ +int bus_dmamem_alloc_size(bus_dma_tag_t dmat, void** vaddr, int flags, + bus_dmamap_t *mapp, bus_size_t size); + int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, bus_dmamap_t *mapp); @@ -187,6 +190,9 @@ int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, * Free a piece of memory and it's allociated dmamap, that was allocated * via bus_dmamem_alloc. */ +void bus_dmamem_free_size(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map, + bus_size_t size); + void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map); /* |