aboutsummaryrefslogtreecommitdiff
path: root/sys/arm/arm/busdma_machdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arm/arm/busdma_machdep.c')
-rw-r--r--sys/arm/arm/busdma_machdep.c104
1 files changed, 23 insertions, 81 deletions
diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c
index 2540e15f75c5..44bc96bed734 100644
--- a/sys/arm/arm/busdma_machdep.c
+++ b/sys/arm/arm/busdma_machdep.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2012-2015 Ian Lepore
* Copyright (c) 2010 Mark Tinguely
@@ -32,9 +32,6 @@
* From i386/busdma_machdep.c 191438 2009-04-23 20:24:19Z jhb
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
@@ -80,18 +77,14 @@ struct bounce_page;
struct bounce_zone;
struct bus_dma_tag {
- bus_dma_tag_t parent;
bus_size_t alignment;
bus_addr_t boundary;
bus_addr_t lowaddr;
bus_addr_t highaddr;
- bus_dma_filter_t *filter;
- void *filterarg;
bus_size_t maxsize;
u_int nsegments;
bus_size_t maxsegsz;
int flags;
- int ref_count;
int map_count;
bus_dma_lock_t *lockfunc;
void *lockfuncarg;
@@ -151,6 +144,7 @@ struct bus_dmamap {
struct memdesc mem;
bus_dmamap_callback_t *callback;
void *callback_arg;
+ __sbintime_t queued_time;
int flags;
#define DMAMAP_COHERENT (1 << 0)
#define DMAMAP_DMAMEM_ALLOC (1 << 1)
@@ -175,6 +169,7 @@ MALLOC_DEFINE(M_BUSDMA, "busdma", "busdma metadata");
#define dmat_alignment(dmat) ((dmat)->alignment)
#define dmat_flags(dmat) ((dmat)->flags)
+#define dmat_highaddr(dmat) ((dmat)->highaddr)
#define dmat_lowaddr(dmat) ((dmat)->lowaddr)
#define dmat_lockfunc(dmat) ((dmat)->lockfunc)
#define dmat_lockfuncarg(dmat) ((dmat)->lockfuncarg)
@@ -245,7 +240,7 @@ SYSINIT(busdma, SI_SUB_KMEM+1, SI_ORDER_FIRST, busdma_init, NULL);
* express, so we take a fast out.
*/
static int
-exclusion_bounce_check(vm_offset_t lowaddr, vm_offset_t highaddr)
+exclusion_bounce_check(bus_addr_t lowaddr, bus_addr_t highaddr)
{
int i;
@@ -336,11 +331,7 @@ might_bounce(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t addr,
*
* Bouncing can be triggered by DMA that doesn't begin and end on cacheline
* boundaries, or doesn't begin on an alignment boundary, or falls within the
- * exclusion zone of any tag in the ancestry chain.
- *
- * For exclusions, walk the chain of tags comparing paddr to the exclusion zone
- * within each tag. If the tag has a filter function, use it to decide whether
- * the DMA needs to bounce, otherwise any DMA within the zone bounces.
+ * exclusion zone of the tag.
*/
static int
must_bounce(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t paddr,
@@ -351,27 +342,11 @@ must_bounce(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t paddr,
return (1);
/*
- * The tag already contains ancestors' alignment restrictions so this
- * check doesn't need to be inside the loop.
+ * Check the tag's exclusion zone.
*/
- if (alignment_bounce(dmat, paddr))
+ if (exclusion_bounce(dmat) && addr_needs_bounce(dmat, paddr))
return (1);
- /*
- * Even though each tag has an exclusion zone that is a superset of its
- * own and all its ancestors' exclusions, the exclusion zone of each tag
- * up the chain must be checked within the loop, because the busdma
- * rules say the filter function is called only when the address lies
- * within the low-highaddr range of the tag that filterfunc belongs to.
- */
- while (dmat != NULL && exclusion_bounce(dmat)) {
- if ((paddr >= dmat->lowaddr && paddr <= dmat->highaddr) &&
- (dmat->filter == NULL ||
- dmat->filter(dmat->filterarg, paddr) != 0))
- return (1);
- dmat = dmat->parent;
- }
-
return (0);
}
@@ -400,6 +375,10 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
/* Return a NULL tag on failure */
*dmat = NULL;
+ /* Filters are no longer supported. */
+ if (filter != NULL || filterarg != NULL)
+ return (EINVAL);
+
newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_BUSDMA,
M_ZERO | M_NOWAIT);
if (newtag == NULL) {
@@ -408,19 +387,15 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
return (ENOMEM);
}
- newtag->parent = parent;
newtag->alignment = alignment;
newtag->boundary = boundary;
newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1);
newtag->highaddr = trunc_page((vm_paddr_t)highaddr) +
(PAGE_SIZE - 1);
- newtag->filter = filter;
- newtag->filterarg = filterarg;
newtag->maxsize = maxsize;
newtag->nsegments = nsegments;
newtag->maxsegsz = maxsegsz;
newtag->flags = flags;
- newtag->ref_count = 1; /* Count ourself */
newtag->map_count = 0;
if (lockfunc != NULL) {
newtag->lockfunc = lockfunc;
@@ -442,17 +417,6 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
else if (parent->boundary != 0)
newtag->boundary = MIN(parent->boundary,
newtag->boundary);
- if (newtag->filter == NULL) {
- /*
- * Short circuit to looking at our parent directly
- * since we have encapsulated all of its information
- */
- newtag->filter = parent->filter;
- newtag->filterarg = parent->filterarg;
- newtag->parent = parent->parent;
- }
- if (newtag->parent != NULL)
- atomic_add_int(&parent->ref_count, 1);
}
if (exclusion_bounce_check(newtag->lowaddr, newtag->highaddr))
@@ -512,7 +476,6 @@ bus_dma_template_clone(bus_dma_template_t *t, bus_dma_tag_t dmat)
if (t == NULL || dmat == NULL)
return;
- t->parent = dmat->parent;
t->alignment = dmat->alignment;
t->boundary = dmat->boundary;
t->lowaddr = dmat->lowaddr;
@@ -535,39 +498,17 @@ bus_dma_tag_set_domain(bus_dma_tag_t dmat, int domain)
int
bus_dma_tag_destroy(bus_dma_tag_t dmat)
{
-#ifdef KTR
- bus_dma_tag_t dmat_copy = dmat;
-#endif
- int error;
-
- error = 0;
+ int error = 0;
if (dmat != NULL) {
if (dmat->map_count != 0) {
error = EBUSY;
goto out;
}
-
- while (dmat != NULL) {
- bus_dma_tag_t parent;
-
- parent = dmat->parent;
- atomic_subtract_int(&dmat->ref_count, 1);
- if (dmat->ref_count == 0) {
- atomic_subtract_32(&tags_total, 1);
- free(dmat, M_BUSDMA);
- /*
- * Last reference count, so
- * release our reference
- * count on our parent.
- */
- dmat = parent;
- } else
- dmat = NULL;
- }
+ free(dmat, M_BUSDMA);
}
out:
- CTR3(KTR_BUSDMA, "%s tag %p error %d", __func__, dmat_copy, error);
+ CTR3(KTR_BUSDMA, "%s tag %p error %d", __func__, dmat, error);
return (error);
}
@@ -776,10 +717,10 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddr, int flags,
howmany(dmat->maxsize, MIN(dmat->maxsegsz, PAGE_SIZE)) &&
dmat->alignment <= PAGE_SIZE &&
(dmat->boundary % PAGE_SIZE) == 0) {
- *vaddr = (void *)kmem_alloc_attr(dmat->maxsize, mflags, 0,
+ *vaddr = kmem_alloc_attr(dmat->maxsize, mflags, 0,
dmat->lowaddr, memattr);
} else {
- *vaddr = (void *)kmem_alloc_contig(dmat->maxsize, mflags, 0,
+ *vaddr = kmem_alloc_contig(dmat->maxsize, mflags, 0,
dmat->lowaddr, dmat->alignment, dmat->boundary, memattr);
}
if (*vaddr == NULL) {
@@ -822,7 +763,7 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
!exclusion_bounce(dmat))
uma_zfree(bufzone->umazone, vaddr);
else
- kmem_free((vm_offset_t)vaddr, dmat->maxsize);
+ kmem_free(vaddr, dmat->maxsize);
dmat->map_count--;
if (map->flags & DMAMAP_COHERENT)
@@ -871,6 +812,7 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, pmap_t pmap, bus_dmamap_t map,
vm_offset_t vaddr;
vm_offset_t vendaddr;
bus_addr_t paddr;
+ bus_size_t sg_len;
if (map->pagesneeded == 0) {
CTR5(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d"
@@ -885,16 +827,16 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, pmap_t pmap, bus_dmamap_t map,
vendaddr = (vm_offset_t)buf + buflen;
while (vaddr < vendaddr) {
+ sg_len = MIN(vendaddr - vaddr,
+ (PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK)));
+ sg_len = MIN(sg_len, dmat->maxsegsz);
if (__predict_true(pmap == kernel_pmap))
paddr = pmap_kextract(vaddr);
else
paddr = pmap_extract(pmap, vaddr);
- if (must_bounce(dmat, map, paddr,
- min(vendaddr - vaddr, (PAGE_SIZE - ((vm_offset_t)vaddr &
- PAGE_MASK)))) != 0) {
+ if (must_bounce(dmat, map, paddr, sg_len) != 0)
map->pagesneeded++;
- }
- vaddr += (PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK));
+ vaddr += sg_len;
}
CTR1(KTR_BUSDMA, "pagesneeded= %d", map->pagesneeded);
}