summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2003-01-29 07:25:27 +0000
committerscottl <scottl@FreeBSD.org>2003-01-29 07:25:27 +0000
commit27cbbd88a297ee95096971d969fc28f1f2c7a09c (patch)
treed21203bdfa9f1d0c2ea53afbd752b1326d109e6c
parent1bc11f23c6b4c14967b2c1745df47caa7147c66e (diff)
downloadFreeBSD-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.c34
-rw-r--r--sys/alpha/include/bus.h6
-rw-r--r--sys/amd64/amd64/busdma_machdep.c34
-rw-r--r--sys/amd64/include/bus_dma.h6
-rw-r--r--sys/i386/i386/busdma_machdep.c34
-rw-r--r--sys/i386/include/bus_dma.h6
-rw-r--r--sys/sparc64/include/bus.h30
-rw-r--r--sys/sparc64/include/iommuvar.h4
-rw-r--r--sys/sparc64/pci/psycho.c27
-rw-r--r--sys/sparc64/sbus/sbus.c25
-rw-r--r--sys/sparc64/sparc64/bus_machdep.c44
-rw-r--r--sys/sparc64/sparc64/iommu.c31
-rw-r--r--sys/sys/bus_dma.h6
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);
/*
OpenPOWER on IntegriCloud