Date: Fri, 27 Feb 2009 16:47:30 GMT From: Ulf Lilleengen <lulf@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 158388 for review Message-ID: <200902271647.n1RGlUAS024049@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=158388 Change 158388 by lulf@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) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902271647.n1RGlUAS024049>