PERFORCE change 158388 for review
Ulf Lilleengen
lulf at FreeBSD.org
Fri Feb 27 08:47:31 PST 2009
http://perforce.freebsd.org/chv.cgi?CH=158388
Change 158388 by lulf at lulf_carrot on 2009/02/27 16:47:01
- Use MIPS busdma as a base instead, as it seems to be a lot simpler
than the ARM code. Try to define limits according to the AVR32
segments, although not sure if it is completely correct yet.
- Add cache handling skeleton and read cache characteristics from
CONFIG1. Currently, only noops, but will be implemented next.
Affected files ...
.. //depot/projects/avr32/src/sys/avr32/avr32/busdma_machdep.c#2 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/cache.c#1 add
.. //depot/projects/avr32/src/sys/avr32/avr32/machdep.c#9 edit
.. //depot/projects/avr32/src/sys/avr32/include/cache.h#1 add
.. //depot/projects/avr32/src/sys/conf/files.avr32#9 edit
Differences ...
==== //depot/projects/avr32/src/sys/avr32/avr32/busdma_machdep.c#2 (text+ko) ====
@@ -1,7 +1,5 @@
/*-
- * Copyright (c) 2004 Olivier Houchard
- * Copyright (c) 2002 Peter Grehan
- * Copyright (c) 1997, 1998 Justin T. Gibbs.
+ * Copyright (c) 2006 Fill this file and put your name here
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,17 +23,50 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * From arm/busdma_machdep.c,v 1.44 2009/02/09 22:58:09 lulf
+ */
+
+/*-
+ * Copyright (c) 1997, 1998, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
+/* $NetBSD: bus_dma.c,v 1.17 2006/03/01 12:38:11 yamt Exp $ */
+
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * AVR32 bus dma support routines
- */
+__FBSDID("$FreeBSD: src/sys/avr32/avr32/busdma_machdep.c,v 1.4 2009/02/12 01:10:53 imp Exp $");
-#define _AVR32_BUS_DMA_PRIVATE
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
@@ -48,7 +79,6 @@
#include <sys/uio.h>
#include <sys/ktr.h>
#include <sys/kernel.h>
-#include <sys/sysctl.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
@@ -56,14 +86,9 @@
#include <machine/atomic.h>
#include <machine/bus.h>
+#include <machine/cache.h>
+#include <machine/cpu.h>
#include <machine/cpufunc.h>
-#include <machine/md_var.h>
-
-#define MAX_BPAGES 64
-#define BUS_DMA_COULD_BOUNCE BUS_DMA_BUS3
-#define BUS_DMA_MIN_ALLOC_COMP BUS_DMA_BUS4
-
-struct bounce_zone;
struct bus_dma_tag {
bus_dma_tag_t parent;
@@ -81,56 +106,12 @@
int map_count;
bus_dma_lock_t *lockfunc;
void *lockfuncarg;
- /*
- * DMA range for this tag. If the page doesn't fall within
- * one of these ranges, an error is returned. The caller
- * may then decide what to do with the transfer. If the
- * range pointer is NULL, it is ignored.
- */
- struct avr32_dma_range *ranges;
- int _nranges;
- struct bounce_zone *bounce_zone;
-};
-
-struct bounce_page {
- vm_offset_t vaddr; /* kva of bounce buffer */
- vm_offset_t vaddr_nocache; /* kva of bounce buffer uncached */
- bus_addr_t busaddr; /* Physical address */
- vm_offset_t datavaddr; /* kva of client data */
- bus_size_t datacount; /* client data count */
- STAILQ_ENTRY(bounce_page) links;
-};
-
-int busdma_swi_pending;
-
-struct bounce_zone {
- STAILQ_ENTRY(bounce_zone) links;
- STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
- int total_bpages;
- int free_bpages;
- int reserved_bpages;
- int active_bpages;
- int total_bounced;
- int total_deferred;
- int map_count;
- bus_size_t alignment;
- bus_size_t boundary;
- bus_addr_t lowaddr;
- char zoneid[8];
- char lowaddrid[20];
- struct sysctl_ctx_list sysctl_tree;
- struct sysctl_oid *sysctl_tree_top;
+ /* XXX: machine-dependent fields */
+ vm_offset_t _physbase;
+ vm_offset_t _wbase;
+ vm_offset_t _wsize;
};
-static struct mtx bounce_lock;
-static int total_bpages;
-static int busdma_zonecount;
-static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
-
-SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD, 0, "Busdma parameters");
-SYSCTL_INT(_hw_busdma, OID_AUTO, total_bpages, CTLFLAG_RD, &total_bpages, 0,
- "Total bounce pages");
-
#define DMAMAP_LINEAR 0x1
#define DMAMAP_MBUF 0x2
#define DMAMAP_UIO 0x4
@@ -138,9 +119,6 @@
#define DMAMAP_TYPE_MASK (DMAMAP_LINEAR|DMAMAP_MBUF|DMAMAP_UIO)
#define DMAMAP_COHERENT 0x8
struct bus_dmamap {
- struct bp_list bpages;
- int pagesneeded;
- int pagesreserved;
bus_dma_tag_t dmat;
int flags;
void *buffer;
@@ -148,15 +126,8 @@
void *allocbuffer;
TAILQ_ENTRY(bus_dmamap) freelist;
int len;
- STAILQ_ENTRY(bus_dmamap) links;
- bus_dmamap_callback_t *callback;
- void *callback_arg;
-
};
-static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
-static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist;
-
static TAILQ_HEAD(,bus_dmamap) dmamap_freelist =
TAILQ_HEAD_INITIALIZER(dmamap_freelist);
@@ -167,45 +138,6 @@
MTX_SYSINIT(busdma_mtx, &busdma_mtx, "busdma lock", MTX_DEF);
-static void init_bounce_pages(void *dummy);
-static int alloc_bounce_zone(bus_dma_tag_t dmat);
-static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages);
-static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
- int commit);
-static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map,
- vm_offset_t vaddr, bus_size_t size);
-static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage);
-
-/* Default tag, as most drivers provide no parent tag. */
-bus_dma_tag_t avr32_root_dma_tag;
-
-/*
- * Return true if a match is made.
- *
- * To find a match walk the chain of bus_dma_tag_t's looking for 'paddr'.
- *
- * If paddr is within the bounds of the dma tag then call the filter callback
- * to check for a match, if there is no filter callback then assume a match.
- */
-static int
-run_filter(bus_dma_tag_t dmat, bus_addr_t paddr)
-{
- int retval;
-
- retval = 0;
-
- do {
- if (((paddr > dmat->lowaddr && paddr <= dmat->highaddr)
- || ((paddr & (dmat->alignment - 1)) != 0))
- && (dmat->filter == NULL
- || (*dmat->filter)(dmat->filterarg, paddr) != 0))
- retval = 1;
-
- dmat = dmat->parent;
- } while (retval == 0 && dmat != NULL);
- return (retval);
-}
-
static void
avr32_dmamap_freelist_init(void *dummy)
{
@@ -226,34 +158,6 @@
bus_dmamap_t map, void *buf, bus_size_t buflen, struct pmap *pmap,
int flags, vm_offset_t *lastaddrp, int *segp);
-static __inline int
-_bus_dma_can_bounce(vm_offset_t lowaddr, vm_offset_t highaddr)
-{
- int i;
- for (i = 0; phys_avail[i] && phys_avail[i + 1]; i += 2) {
- if ((lowaddr >= phys_avail[i] && lowaddr <= phys_avail[i + 1])
- || (lowaddr < phys_avail[i] &&
- highaddr > phys_avail[i]))
- return (1);
- }
- return (0);
-}
-
-static __inline struct avr32_dma_range *
-_bus_dma_inrange(struct avr32_dma_range *ranges, int nranges,
- bus_addr_t curaddr)
-{
- struct avr32_dma_range *dr;
- int i;
-
- for (i = 0, dr = ranges; i < nranges; i++, dr++) {
- if (curaddr >= dr->dr_sysbase &&
- round_page(curaddr) <= (dr->dr_sysbase + dr->dr_len))
- return (dr);
- }
-
- return (NULL);
-}
/*
* Convenience function for manipulating driver locks from busdma (during
* busdma_swi, for example). Drivers that don't provide their own locks
@@ -310,7 +214,6 @@
map->flags = DMAMAP_ALLOCATED;
} else
map->flags = 0;
- STAILQ_INIT(&map->bpages);
return (map);
}
@@ -326,11 +229,6 @@
}
}
-/*
- * Allocate a device specific dma_tag.
- */
-#define SEG_NB 1024
-
int
bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
bus_size_t boundary, bus_addr_t lowaddr,
@@ -341,12 +239,16 @@
{
bus_dma_tag_t newtag;
int error = 0;
+
+ /* Basic sanity checking */
+ if (boundary != 0 && boundary < maxsegsz)
+ maxsegsz = boundary;
+
/* Return a NULL tag on failure */
*dmat = NULL;
- if (!parent)
- parent = avr32_root_dma_tag;
- newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, M_NOWAIT);
+ newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF,
+ M_ZERO | M_NOWAIT);
if (newtag == NULL) {
CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
__func__, newtag, 0, error);
@@ -356,18 +258,24 @@
newtag->parent = parent;
newtag->alignment = alignment;
newtag->boundary = boundary;
- newtag->lowaddr = trunc_page((vm_offset_t)lowaddr) + (PAGE_SIZE - 1);
- newtag->highaddr = trunc_page((vm_offset_t)highaddr) + (PAGE_SIZE - 1);
+ 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->maxsize = maxsize;
+ newtag->nsegments = nsegments;
newtag->maxsegsz = maxsegsz;
newtag->flags = flags;
newtag->ref_count = 1; /* Count ourself */
newtag->map_count = 0;
- newtag->ranges = bus_dma_get_range();
- newtag->_nranges = bus_dma_get_range_nb();
+ newtag->_wbase = 0;
+ newtag->_physbase = 0;
+ /*
+ * Currently limited to the first physical segment, should perhaps be
+ * physical size of memory, as noted in the mips code.
+ */
+ newtag->_wsize = AVR32_SEG_P2 - AVR32_SEG_P1;
if (lockfunc != NULL) {
newtag->lockfunc = lockfunc;
newtag->lockfuncarg = lockfuncarg;
@@ -375,68 +283,36 @@
newtag->lockfunc = dflt_lock;
newtag->lockfuncarg = NULL;
}
- /*
- * Take into account any restrictions imposed by our parent tag
- */
- if (parent != NULL) {
- newtag->lowaddr = min(parent->lowaddr, newtag->lowaddr);
- newtag->highaddr = max(parent->highaddr, newtag->highaddr);
+
+ /* Take into account any restrictions imposed by our parent tag */
+ if (parent != NULL) {
+ newtag->lowaddr = MIN(parent->lowaddr, newtag->lowaddr);
+ newtag->highaddr = MAX(parent->highaddr, newtag->highaddr);
if (newtag->boundary == 0)
newtag->boundary = parent->boundary;
else if (parent->boundary != 0)
- newtag->boundary = min(parent->boundary,
+ newtag->boundary = MIN(parent->boundary,
newtag->boundary);
- if ((newtag->filter != NULL) ||
- ((parent->flags & BUS_DMA_COULD_BOUNCE) != 0))
- newtag->flags |= BUS_DMA_COULD_BOUNCE;
- if (newtag->filter == NULL) {
- /*
- * Short circuit 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->filter == NULL) {
+ /*
+ * Short circuit 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 (_bus_dma_can_bounce(newtag->lowaddr, newtag->highaddr)
- || newtag->alignment > 1)
- newtag->flags |= BUS_DMA_COULD_BOUNCE;
- if (((newtag->flags & BUS_DMA_COULD_BOUNCE) != 0) &&
- (flags & BUS_DMA_ALLOCNOW) != 0) {
- struct bounce_zone *bz;
-
- /* Must bounce */
-
- if ((error = alloc_bounce_zone(newtag)) != 0) {
- free(newtag, M_DEVBUF);
- return (error);
- }
- bz = newtag->bounce_zone;
-
- if (ptoa(bz->total_bpages) < maxsize) {
- int pages;
-
- pages = atop(maxsize) - bz->total_bpages;
-
- /* Add pages to our bounce pool */
- if (alloc_bounce_pages(newtag, pages) < pages)
- error = ENOMEM;
- }
- /* Performed initial allocation */
- newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
- } else
- newtag->bounce_zone = NULL;
- if (error != 0)
+ if (error != 0) {
free(newtag, M_DEVBUF);
- else
+ } else {
*dmat = newtag;
+ }
CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
__func__, newtag, (newtag != NULL ? newtag->flags : 0), error);
-
return (error);
}
@@ -474,7 +350,6 @@
return (0);
}
-#include <sys/kdb.h>
/*
* Allocate a handle for mapping from kva/uva/physical
* address space into bus device space.
@@ -483,7 +358,9 @@
bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
{
bus_dmamap_t newmap;
+#ifdef KTR
int error = 0;
+#endif
newmap = _busdma_alloc_dmamap();
if (newmap == NULL) {
@@ -492,60 +369,13 @@
}
*mapp = newmap;
newmap->dmat = dmat;
- newmap->allocbuffer = NULL;
dmat->map_count++;
- /*
- * Bouncing might be required if the driver asks for an active
- * exclusion region, a data alignment that is stricter than 1, and/or
- * an active address boundary.
- */
- if (dmat->flags & BUS_DMA_COULD_BOUNCE) {
-
- /* Must bounce */
- struct bounce_zone *bz;
- int maxpages;
-
- if (dmat->bounce_zone == NULL) {
- if ((error = alloc_bounce_zone(dmat)) != 0) {
- _busdma_free_dmamap(newmap);
- *mapp = NULL;
- return (error);
- }
- }
- bz = dmat->bounce_zone;
-
- /* Initialize the new map */
- STAILQ_INIT(&((*mapp)->bpages));
-
- /*
- * Attempt to add pages to our pool on a per-instance
- * basis up to a sane limit.
- */
- maxpages = MAX_BPAGES;
- if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0
- || (bz->map_count > 0 && bz->total_bpages < maxpages)) {
- int pages;
-
- pages = MAX(atop(dmat->maxsize), 1);
- pages = MIN(maxpages - bz->total_bpages, pages);
- pages = MAX(pages, 1);
- if (alloc_bounce_pages(dmat, pages) < pages)
- error = ENOMEM;
-
- if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0) {
- if (error == 0)
- dmat->flags |= BUS_DMA_MIN_ALLOC_COMP;
- } else {
- error = 0;
- }
- }
- bz->map_count++;
- }
CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
__func__, dmat, dmat->flags, error);
return (0);
+
}
/*
@@ -555,21 +385,12 @@
int
bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
{
-
_busdma_free_dmamap(map);
- if (STAILQ_FIRST(&map->bpages) != NULL) {
- CTR3(KTR_BUSDMA, "%s: tag %p error %d",
- __func__, dmat, EBUSY);
- return (EBUSY);
- }
- if (dmat->bounce_zone)
- dmat->bounce_zone->map_count--;
dmat->map_count--;
CTR2(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat);
return (0);
}
-#ifdef notyet
/*
* Allocate a piece of memory that can be efficiently mapped into
* bus device space based on the constraints lited in the dma tag.
@@ -600,9 +421,7 @@
*mapp = newmap;
newmap->dmat = dmat;
- if (dmat->maxsize <= PAGE_SIZE &&
- (dmat->alignment < dmat->maxsize) &&
- !_bus_dma_can_bounce(dmat->lowaddr, dmat->highaddr)) {
+ if (dmat->maxsize <= PAGE_SIZE) {
*vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);
} else {
/*
@@ -610,8 +429,23 @@
* and handles multi-seg allocations. Nobody is doing
* multi-seg allocations yet though.
*/
+ vm_paddr_t maxphys;
+ /* XXX: Fix to use correct largest physical address. */
+ if((uint32_t)dmat->lowaddr >= (AVR32_SEG_P2 - AVR32_SEG_P1)) {
+ /* Note in the else case I just put in what was already
+ * being passed in dmat->lowaddr. I am not sure
+ * how this would have worked. Since lowaddr is in the
+ * max address postion. I would have thought that the
+ * caller would have wanted dmat->highaddr. That is
+ * presuming they are asking for physical addresses
+ * which is what contigmalloc takes. - RRS
+ */
+ maxphys = (AVR32_SEG_P2 - AVR32_SEG_P1) - 1;
+ } else {
+ maxphys = dmat->lowaddr;
+ }
*vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags,
- 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul,
+ 0ul, maxphys, dmat->alignment? dmat->alignment : 1ul,
dmat->boundary);
}
if (*vaddr == NULL) {
@@ -623,18 +457,13 @@
return (ENOMEM);
}
if (flags & BUS_DMA_COHERENT) {
- void *tmpaddr = arm_remap_nocache(
- (void *)((vm_offset_t)*vaddr &~ PAGE_MASK),
- dmat->maxsize + ((vm_offset_t)*vaddr & PAGE_MASK));
+ void *tmpaddr = (void *)*vaddr;
if (tmpaddr) {
- tmpaddr = (void *)((vm_offset_t)(tmpaddr) +
- ((vm_offset_t)*vaddr & PAGE_MASK));
+ tmpaddr = (void *)AVR32_PHYS_TO_P1(vtophys(tmpaddr));
newmap->origbuffer = *vaddr;
newmap->allocbuffer = tmpaddr;
- cpu_idcache_wbinv_range((vm_offset_t)*vaddr,
- dmat->maxsize);
- cpu_l2cache_wbinv_range((vm_offset_t)*vaddr,
+ avr32_dcache_wbinv_range((vm_offset_t)*vaddr,
dmat->maxsize);
*vaddr = tmpaddr;
} else
@@ -642,10 +471,9 @@
} else
newmap->origbuffer = newmap->allocbuffer = NULL;
return (0);
+
}
-#endif
-#ifdef notyet
/*
* Free a piece of memory and it's allocated dmamap, that was allocated
* via bus_dmamem_alloc. Make the same choice for free/contigfree.
@@ -657,11 +485,8 @@
KASSERT(map->allocbuffer == vaddr,
("Trying to freeing the wrong DMA buffer"));
vaddr = map->origbuffer;
- arm_unmap_nocache(map->allocbuffer, dmat->maxsize);
}
- if (dmat->maxsize <= PAGE_SIZE &&
- dmat->alignment < dmat->maxsize &&
- !_bus_dma_can_bounce(dmat->lowaddr, dmat->highaddr))
+ if (dmat->maxsize <= PAGE_SIZE)
free(vaddr, M_DEVBUF);
else {
contigfree(vaddr, dmat->maxsize, M_DEVBUF);
@@ -669,60 +494,7 @@
dmat->map_count--;
_busdma_free_dmamap(map);
CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
-}
-#endif
-
-static int
-_bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
- bus_size_t buflen, int flags)
-{
- vm_offset_t vaddr;
- vm_offset_t vendaddr;
- bus_addr_t paddr;
-
- if ((map->pagesneeded == 0)) {
- CTR3(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d",
- dmat->lowaddr, dmat->boundary, dmat->alignment);
- CTR2(KTR_BUSDMA, "map= %p, pagesneeded= %d",
- map, map->pagesneeded);
- /*
- * Count the number of bounce pages
- * needed in order to complete this transfer
- */
- vaddr = trunc_page((vm_offset_t)buf);
- vendaddr = (vm_offset_t)buf + buflen;
-
- while (vaddr < vendaddr) {
- paddr = pmap_kextract(vaddr);
- if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) &&
- run_filter(dmat, paddr) != 0)
- map->pagesneeded++;
- vaddr += PAGE_SIZE;
- }
- CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded);
- }
-
- /* Reserve Necessary Bounce Pages */
- if (map->pagesneeded != 0) {
- mtx_lock(&bounce_lock);
- if (flags & BUS_DMA_NOWAIT) {
- if (reserve_bounce_pages(dmat, map, 0) != 0) {
- mtx_unlock(&bounce_lock);
- return (ENOMEM);
- }
- } else {
- if (reserve_bounce_pages(dmat, map, 1) != 0) {
- /* Queue us for resources */
- STAILQ_INSERT_TAIL(&bounce_map_waitinglist,
- map, links);
- mtx_unlock(&bounce_lock);
- return (EINPROGRESS);
- }
- }
- mtx_unlock(&bounce_lock);
- }
- return (0);
}
/*
@@ -737,113 +509,45 @@
int flags, vm_offset_t *lastaddrp, int *segp)
{
bus_size_t sgsize;
- bus_addr_t curaddr, lastaddr, baddr, bmask;
+ bus_size_t bmask;
+ vm_offset_t curaddr, lastaddr;
vm_offset_t vaddr = (vm_offset_t)buf;
int seg;
int error = 0;
- pd_entry_t *pde;
- pt_entry_t pte;
- pt_entry_t *ptep;
lastaddr = *lastaddrp;
bmask = ~(dmat->boundary - 1);
- if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
- error = _bus_dmamap_count_pages(dmat, map, buf, buflen, flags);
- if (error)
- return (error);
- }
- CTR3(KTR_BUSDMA, "lowaddr= %d boundary= %d, "
- "alignment= %d", dmat->lowaddr, dmat->boundary, dmat->alignment);
-
for (seg = *segp; buflen > 0 ; ) {
/*
* Get the physical address for this segment.
- *
- * XXX Don't support checking for coherent mappings
- * XXX in user address space.
+ */
+ KASSERT(kernel_pmap == pmap, ("pmap is not kernel pmap"));
+ curaddr = pmap_kextract(vaddr);
+
+ /*
+ * If we're beyond the current DMA window, indicate
+ * that and try to fall back onto something else.
+ */
+ if (curaddr < dmat->_physbase ||
+ curaddr >= (dmat->_physbase + dmat->_wsize))
+ return (EINVAL);
+
+ /*
+ * In a valid DMA range. Translate the physical
+ * memory address to an address in the DMA window.
*/
- if (__predict_true(pmap == pmap_kernel())) {
-#ifdef notyet
- if (pmap_get_pde_pte(pmap, vaddr, &pde, &ptep) == FALSE)
- return (EFAULT);
+ curaddr = (curaddr - dmat->_physbase) + dmat->_wbase;
- if (__predict_false(pmap_pde_section(pde))) {
- if (*pde & L1_S_SUPERSEC)
- curaddr = (*pde & L1_SUP_FRAME) |
- (vaddr & L1_SUP_OFFSET);
- else
- curaddr = (*pde & L1_S_FRAME) |
- (vaddr & L1_S_OFFSET);
- if (*pde & L1_S_CACHE_MASK) {
- map->flags &=
- ~DMAMAP_COHERENT;
- }
- } else {
- pte = *ptep;
- KASSERT((pte & L2_TYPE_MASK) != L2_TYPE_INV,
- ("INV type"));
- if (__predict_false((pte & L2_TYPE_MASK)
- == L2_TYPE_L)) {
- curaddr = (pte & L2_L_FRAME) |
- (vaddr & L2_L_OFFSET);
- if (pte & L2_L_CACHE_MASK) {
- map->flags &=
- ~DMAMAP_COHERENT;
-
- }
- } else {
- curaddr = (pte & L2_S_FRAME) |
- (vaddr & L2_S_OFFSET);
- if (pte & L2_S_CACHE_MASK) {
- map->flags &=
- ~DMAMAP_COHERENT;
- }
- }
- }
-#endif
- } else {
- curaddr = pmap_extract(pmap, vaddr);
- map->flags &= ~DMAMAP_COHERENT;
- }
/*
* Compute the segment size, and adjust counts.
*/
sgsize = PAGE_SIZE - ((u_long)curaddr & PAGE_MASK);
- if (sgsize > dmat->maxsegsz)
- sgsize = dmat->maxsegsz;
if (buflen < sgsize)
sgsize = buflen;
/*
- * Make sure we don't cross any boundaries.
- */
- if (dmat->boundary > 0) {
- baddr = (curaddr + dmat->boundary) & bmask;
- if (sgsize > (baddr - curaddr))
- sgsize = (baddr - curaddr);
- }
- if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) &&
- map->pagesneeded != 0 && run_filter(dmat, curaddr))
- curaddr = add_bounce_page(dmat, map, vaddr, sgsize);
-
- if (dmat->ranges) {
- struct avr32_dma_range *dr;
-
- dr = _bus_dma_inrange(dmat->ranges, dmat->_nranges,
- curaddr);
- if (dr == NULL)
- return (EINVAL);
- /*
- * In a valid DMA range. Translate the physical
- * memory address to an address in the DMA window.
- */
- curaddr = (curaddr - dr->dr_sysbase) + dr->dr_busbase;
-
- }
-
- /*
* Insert chunk into a segment, coalescing with
* the previous segment if possible.
*/
@@ -875,8 +579,9 @@
* Did we fit?
*/
if (buflen != 0)
- error = EFBIG; /* XXX better return value here? */
- return (error);
+ error = EFBIG;
+
+ return error;
}
/*
@@ -897,8 +602,6 @@
KASSERT(dmat != NULL, ("dmatag is NULL"));
KASSERT(map != NULL, ("dmamap is NULL"));
- map->callback = callback;
- map->callback_arg = callback_arg;
map->flags &= ~DMAMAP_TYPE_MASK;
map->flags |= DMAMAP_LINEAR|DMAMAP_COHERENT;
map->buffer = buf;
@@ -906,8 +609,7 @@
error = bus_dmamap_load_buffer(dmat,
dm_segments, map, buf, buflen, kernel_pmap,
flags, &lastaddr, &nsegs);
- if (error == EINPROGRESS)
- return (error);
+
if (error)
(*callback)(callback_arg, NULL, 0, error);
else
@@ -916,7 +618,8 @@
CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
__func__, dmat, dmat->flags, nsegs + 1, error);
- return (error);
+ return (0);
+
}
/*
@@ -940,6 +643,7 @@
map->flags |= DMAMAP_MBUF | DMAMAP_COHERENT;
map->buffer = m0;
map->len = 0;
+
if (m0->m_pkthdr.len <= dmat->maxsize) {
vm_offset_t lastaddr = 0;
struct mbuf *m;
@@ -948,7 +652,7 @@
if (m->m_len > 0) {
error = bus_dmamap_load_buffer(dmat,
dm_segments, map, m->m_data, m->m_len,
- pmap_kernel(), flags, &lastaddr, &nsegs);
+ kernel_pmap, flags, &lastaddr, &nsegs);
map->len += m->m_len;
}
}
@@ -977,14 +681,16 @@
int flags)
{
int error = 0;
+
M_ASSERTPKTHDR(m0);
flags |= BUS_DMA_NOWAIT;
*nsegs = -1;
map->flags &= ~DMAMAP_TYPE_MASK;
map->flags |= DMAMAP_MBUF | DMAMAP_COHERENT;
- map->buffer = m0;
+ map->buffer = m0;
map->len = 0;
+
if (m0->m_pkthdr.len <= dmat->maxsize) {
vm_offset_t lastaddr = 0;
struct mbuf *m;
@@ -992,9 +698,8 @@
for (m = m0; m != NULL && error == 0; m = m->m_next) {
if (m->m_len > 0) {
error = bus_dmamap_load_buffer(dmat, segs, map,
- m->m_data, m->m_len,
- pmap_kernel(), flags, &lastaddr,
- nsegs);
+ m->m_data, m->m_len,
+ kernel_pmap, flags, &lastaddr, nsegs);
map->len += m->m_len;
}
}
@@ -1002,11 +707,12 @@
error = EINVAL;
}
- /* XXX FIXME: Having to increment nsegs is really annoying */
++*nsegs;
CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
__func__, dmat, dmat->flags, error, *nsegs);
+
return (error);
+
}
/*
@@ -1017,64 +723,9 @@
bus_dmamap_callback2_t *callback, void *callback_arg,
int flags)
{
- vm_offset_t lastaddr = 0;
-#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT
- bus_dma_segment_t dm_segments[dmat->nsegments];
-#else
- bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS];
-#endif
- int nsegs, i, error;
- bus_size_t resid;
- struct iovec *iov;
- struct pmap *pmap;
- resid = uio->uio_resid;
- iov = uio->uio_iov;
- map->flags &= ~DMAMAP_TYPE_MASK;
- map->flags |= DMAMAP_UIO|DMAMAP_COHERENT;
- map->buffer = uio;
- map->len = 0;
-
- if (uio->uio_segflg == UIO_USERSPACE) {
- KASSERT(uio->uio_td != NULL,
- ("bus_dmamap_load_uio: USERSPACE but no proc"));
- pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace);
- } else
- pmap = kernel_pmap;
-
- error = 0;
- nsegs = -1;
- for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) {
- /*
- * Now at the first iovec to load. Load each iovec
- * until we have exhausted the residual count.
- */
- bus_size_t minlen =
- resid < iov[i].iov_len ? resid : iov[i].iov_len;
- caddr_t addr = (caddr_t) iov[i].iov_base;
-
- if (minlen > 0) {
- error = bus_dmamap_load_buffer(dmat, dm_segments, map,
- addr, minlen, pmap, flags, &lastaddr, &nsegs);
-
- map->len += minlen;
- resid -= minlen;
- }
- }
-
- if (error) {
- /*
- * force "no valid mappings" on error in callback.
- */
- (*callback)(callback_arg, dm_segments, 0, 0, error);
- } else {
- (*callback)(callback_arg, dm_segments, nsegs+1,
- uio->uio_resid, error);
- }
-
- CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
- __func__, dmat, dmat->flags, error, nsegs + 1);
- return (error);
+ panic("Unimplemented %s at %s:%d\n", __func__, __FILE__, __LINE__);
+ return (0);
}
/*
@@ -1083,113 +734,33 @@
void
_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
{
- struct bounce_page *bpage;
- map->flags &= ~DMAMAP_TYPE_MASK;
- while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
- STAILQ_REMOVE_HEAD(&map->bpages, links);
- free_bounce_page(dmat, bpage);
- }
return;
}
-static void
+static __inline void
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list