From owner-svn-src-head@FreeBSD.ORG Sun Oct 27 22:05:12 2013 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 4B5A7F7F; Sun, 27 Oct 2013 22:05:12 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 381BE2065; Sun, 27 Oct 2013 22:05:12 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r9RM5CEu052750; Sun, 27 Oct 2013 22:05:12 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r9RM5BVG052740; Sun, 27 Oct 2013 22:05:11 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201310272205.r9RM5BVG052740@svn.freebsd.org> From: Konstantin Belousov Date: Sun, 27 Oct 2013 22:05:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r257230 - in head/sys: conf x86/include x86/x86 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 27 Oct 2013 22:05:12 -0000 Author: kib Date: Sun Oct 27 22:05:10 2013 New Revision: 257230 URL: http://svnweb.freebsd.org/changeset/base/257230 Log: Add a virtual table for the busdma methods on x86, to allow different busdma implementations to coexist. Copy busdma_machdep.c to busdma_bounce.c, which is still a single implementation of the busdma interface on x86 for now. The busdma_machdep.c only contains common and dispatch code. Tested by: pho (as part of the larger patch) Sponsored by: The FreeBSD Foundation MFC after: 1 month Added: head/sys/x86/include/busdma_impl.h (contents, props changed) head/sys/x86/x86/busdma_bounce.c - copied, changed from r257229, head/sys/x86/x86/busdma_machdep.c Modified: head/sys/conf/files.amd64 head/sys/conf/files.i386 head/sys/conf/files.pc98 head/sys/x86/x86/busdma_machdep.c Modified: head/sys/conf/files.amd64 ============================================================================== --- head/sys/conf/files.amd64 Sun Oct 27 21:49:52 2013 (r257229) +++ head/sys/conf/files.amd64 Sun Oct 27 22:05:10 2013 (r257230) @@ -541,6 +541,7 @@ x86/isa/nmi.c standard x86/isa/orm.c optional isa x86/pci/pci_bus.c optional pci x86/pci/qpi.c optional pci +x86/x86/busdma_bounce.c standard x86/x86/busdma_machdep.c standard x86/x86/dump_machdep.c standard x86/x86/fdt_machdep.c optional fdt Modified: head/sys/conf/files.i386 ============================================================================== --- head/sys/conf/files.i386 Sun Oct 27 21:49:52 2013 (r257229) +++ head/sys/conf/files.i386 Sun Oct 27 22:05:10 2013 (r257230) @@ -564,6 +564,7 @@ x86/isa/nmi.c standard x86/isa/orm.c optional isa x86/pci/pci_bus.c optional pci x86/pci/qpi.c optional pci +x86/x86/busdma_bounce.c standard x86/x86/busdma_machdep.c standard x86/x86/dump_machdep.c standard x86/x86/fdt_machdep.c optional fdt Modified: head/sys/conf/files.pc98 ============================================================================== --- head/sys/conf/files.pc98 Sun Oct 27 21:49:52 2013 (r257229) +++ head/sys/conf/files.pc98 Sun Oct 27 22:05:10 2013 (r257230) @@ -247,6 +247,7 @@ x86/isa/atpic.c optional atpic x86/isa/clock.c standard x86/isa/isa.c optional isa x86/pci/pci_bus.c optional pci +x86/x86/busdma_bounce.c standard x86/x86/busdma_machdep.c standard x86/x86/dump_machdep.c standard x86/x86/intr_machdep.c standard Added: head/sys/x86/include/busdma_impl.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/x86/include/busdma_impl.h Sun Oct 27 22:05:10 2013 (r257230) @@ -0,0 +1,97 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef __X86_BUSDMA_IMPL_H +#define __X86_BUSDMA_IMPL_H + +struct bus_dma_tag_common { + struct bus_dma_impl *impl; + struct bus_dma_tag_common *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; + bus_dma_lock_t *lockfunc; + void *lockfuncarg; + int ref_count; +}; + +struct bus_dma_impl { + int (*tag_create)(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, int nsegments, + bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, + void *lockfuncarg, bus_dma_tag_t *dmat); + int (*tag_destroy)(bus_dma_tag_t dmat); + int (*map_create)(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp); + int (*map_destroy)(bus_dma_tag_t dmat, bus_dmamap_t map); + int (*mem_alloc)(bus_dma_tag_t dmat, void** vaddr, int flags, + bus_dmamap_t *mapp); + void (*mem_free)(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map); + int (*load_ma)(bus_dma_tag_t dmat, bus_dmamap_t map, + struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags, + bus_dma_segment_t *segs, int *segp); + int (*load_phys)(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_paddr_t buf, bus_size_t buflen, int flags, + bus_dma_segment_t *segs, int *segp); + int (*load_buffer)(bus_dma_tag_t dmat, bus_dmamap_t map, + void *buf, bus_size_t buflen, pmap_t pmap, int flags, + bus_dma_segment_t *segs, int *segp); + void (*map_waitok)(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, + void *callback_arg); + bus_dma_segment_t *(*map_complete)(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error); + void (*map_unload)(bus_dma_tag_t dmat, bus_dmamap_t map); + void (*map_sync)(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmasync_op_t op); +}; + +void busdma_lock_mutex(void *arg, bus_dma_lock_op_t op); +void bus_dma_dflt_lock(void *arg, bus_dma_lock_op_t op); +int bus_dma_run_filter(struct bus_dma_tag_common *dmat, bus_addr_t paddr); +int common_bus_dma_tag_create(struct bus_dma_tag_common *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, + int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, + void *lockfuncarg, size_t sz, void **dmat); + +extern struct bus_dma_impl bus_dma_bounce_impl; + +#endif Copied and modified: head/sys/x86/x86/busdma_bounce.c (from r257229, head/sys/x86/x86/busdma_machdep.c) ============================================================================== --- head/sys/x86/x86/busdma_machdep.c Sun Oct 27 21:49:52 2013 (r257229, copy source) +++ head/sys/x86/x86/busdma_bounce.c Sun Oct 27 22:05:10 2013 (r257230) @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #ifdef __i386__ #define MAX_BPAGES 512 @@ -63,21 +64,8 @@ __FBSDID("$FreeBSD$"); 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; + struct bus_dma_tag_common common; int map_count; - bus_dma_lock_t *lockfunc; - void *lockfuncarg; bus_dma_segment_t *segments; struct bounce_zone *bounce_zone; }; @@ -160,158 +148,43 @@ static int _bus_dmamap_reserve_pages(bus #endif /* - * 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. - */ -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); -} - -/* - * Convenience function for manipulating driver locks from busdma (during - * busdma_swi, for example). Drivers that don't provide their own locks - * should specify &Giant to dmat->lockfuncarg. Drivers that use their own - * non-mutex locking scheme don't have to use this at all. - */ -void -busdma_lock_mutex(void *arg, bus_dma_lock_op_t op) -{ - struct mtx *dmtx; - - dmtx = (struct mtx *)arg; - switch (op) { - case BUS_DMA_LOCK: - mtx_lock(dmtx); - break; - case BUS_DMA_UNLOCK: - mtx_unlock(dmtx); - break; - default: - panic("Unknown operation 0x%x for busdma_lock_mutex!", op); - } -} - -/* - * dflt_lock should never get called. It gets put into the dma tag when - * lockfunc == NULL, which is only valid if the maps that are associated - * with the tag are meant to never be defered. - * XXX Should have a way to identify which driver is responsible here. - */ -static void -dflt_lock(void *arg, bus_dma_lock_op_t op) -{ - panic("driver error: busdma dflt_lock called"); -} - -/* * Allocate a device specific dma_tag. */ -int -bus_dma_tag_create(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, int nsegments, - bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, - void *lockfuncarg, bus_dma_tag_t *dmat) +static int +bounce_bus_dma_tag_create(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, + int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, + void *lockfuncarg, bus_dma_tag_t *dmat) { bus_dma_tag_t newtag; - int error = 0; - - /* Basic sanity checking */ - if (boundary != 0 && boundary < maxsegsz) - maxsegsz = boundary; - - if (maxsegsz == 0) { - return (EINVAL); - } + int error; - /* Return a NULL tag on failure */ *dmat = NULL; + error = common_bus_dma_tag_create(parent != NULL ? &parent->common : + NULL, alignment, boundary, lowaddr, highaddr, filter, filterarg, + maxsize, nsegments, maxsegsz, flags, lockfunc, lockfuncarg, + sizeof (struct bus_dma_tag), (void **)&newtag); + if (error != 0) + return (error); - 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, ENOMEM); - 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->common.impl = &bus_dma_bounce_impl; newtag->map_count = 0; - if (lockfunc != NULL) { - newtag->lockfunc = lockfunc; - newtag->lockfuncarg = lockfuncarg; - } else { - newtag->lockfunc = dflt_lock; - newtag->lockfuncarg = NULL; - } newtag->segments = 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); - if (newtag->boundary == 0) - newtag->boundary = parent->boundary; - else if (parent->boundary != 0) - 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->parent != NULL) - atomic_add_int(&parent->ref_count, 1); - } - - if (newtag->lowaddr < ptoa((vm_paddr_t)Maxmem) - || newtag->alignment > 1) - newtag->flags |= BUS_DMA_COULD_BOUNCE; + if (parent != NULL && ((newtag->common.filter != NULL) || + ((parent->common.flags & BUS_DMA_COULD_BOUNCE) != 0))) + newtag->common.flags |= BUS_DMA_COULD_BOUNCE; + + if (newtag->common.lowaddr < ptoa((vm_paddr_t)Maxmem) || + newtag->common.alignment > 1) + newtag->common.flags |= BUS_DMA_COULD_BOUNCE; - if (((newtag->flags & BUS_DMA_COULD_BOUNCE) != 0) && + if (((newtag->common.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); @@ -328,41 +201,38 @@ bus_dma_tag_create(bus_dma_tag_t parent, error = ENOMEM; } /* Performed initial allocation */ - newtag->flags |= BUS_DMA_MIN_ALLOC_COMP; - } + newtag->common.flags |= BUS_DMA_MIN_ALLOC_COMP; + } else + error = 0; - 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); + __func__, newtag, (newtag != NULL ? newtag->common.flags : 0), + error); return (error); } -int -bus_dma_tag_destroy(bus_dma_tag_t dmat) +static int +bounce_bus_dma_tag_destroy(bus_dma_tag_t dmat) { - bus_dma_tag_t dmat_copy; + bus_dma_tag_t dmat_copy, parent; int error; error = 0; dmat_copy = dmat; 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) { + parent = (bus_dma_tag_t)dmat->common.parent; + atomic_subtract_int(&dmat->common.ref_count, 1); + if (dmat->common.ref_count == 0) { if (dmat->segments != NULL) free(dmat->segments, M_DEVBUF); free(dmat, M_DEVBUF); @@ -385,17 +255,18 @@ out: * Allocate a handle for mapping from kva/uva/physical * address space into bus device space. */ -int -bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) +static int +bounce_bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) { - int error; + struct bounce_zone *bz; + int error, maxpages, pages; error = 0; if (dmat->segments == NULL) { dmat->segments = (bus_dma_segment_t *)malloc( - sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, - M_NOWAIT); + sizeof(bus_dma_segment_t) * dmat->common.nsegments, + M_DEVBUF, M_NOWAIT); if (dmat->segments == NULL) { CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, ENOMEM); @@ -408,12 +279,8 @@ bus_dmamap_create(bus_dma_tag_t dmat, in * exclusion region, a data alignment that is stricter than 1, and/or * an active address boundary. */ - if (dmat->flags & BUS_DMA_COULD_BOUNCE) { - + if (dmat->common.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) return (error); @@ -421,7 +288,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, in bz = dmat->bounce_zone; *mapp = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF, - M_NOWAIT | M_ZERO); + M_NOWAIT | M_ZERO); if (*mapp == NULL) { CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, ENOMEM); @@ -435,26 +302,26 @@ bus_dmamap_create(bus_dma_tag_t dmat, in * Attempt to add pages to our pool on a per-instance * basis up to a sane limit. */ - if (dmat->alignment > 1) + if (dmat->common.alignment > 1) maxpages = MAX_BPAGES; else - maxpages = MIN(MAX_BPAGES, Maxmem -atop(dmat->lowaddr)); - 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); + maxpages = MIN(MAX_BPAGES, Maxmem - + atop(dmat->common.lowaddr)); + if ((dmat->common.flags & BUS_DMA_MIN_ALLOC_COMP) == 0 || + (bz->map_count > 0 && bz->total_bpages < maxpages)) { + pages = MAX(atop(dmat->common.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 { + if ((dmat->common.flags & BUS_DMA_MIN_ALLOC_COMP) + == 0) { + if (error == 0) { + dmat->common.flags |= + BUS_DMA_MIN_ALLOC_COMP; + } + } else error = 0; - } } bz->map_count++; } else { @@ -463,7 +330,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, in if (error == 0) dmat->map_count++; CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", - __func__, dmat, dmat->flags, error); + __func__, dmat, dmat->common.flags, error); return (error); } @@ -471,9 +338,10 @@ bus_dmamap_create(bus_dma_tag_t dmat, in * Destroy a handle for mapping from kva/uva/physical * address space into bus device space. */ -int -bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) +static int +bounce_bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) { + if (map != NULL && map != &nobounce_dmamap && map != &contig_dmamap) { if (STAILQ_FIRST(&map->bpages) != NULL) { CTR3(KTR_BUSDMA, "%s: tag %p error %d", @@ -495,9 +363,9 @@ bus_dmamap_destroy(bus_dma_tag_t dmat, b * 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(bus_dma_tag_t dmat, void** vaddr, int flags, - bus_dmamap_t *mapp) +static int +bounce_bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, + bus_dmamap_t *mapp) { vm_memattr_t attr; int mflags; @@ -512,11 +380,11 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi if (dmat->segments == NULL) { dmat->segments = (bus_dma_segment_t *)malloc( - sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, - mflags); + sizeof(bus_dma_segment_t) * dmat->common.nsegments, + M_DEVBUF, mflags); if (dmat->segments == NULL) { CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", - __func__, dmat, dmat->flags, ENOMEM); + __func__, dmat, dmat->common.flags, ENOMEM); return (ENOMEM); } } @@ -535,33 +403,36 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi * * In the meantime, we'll warn the user if malloc gets it wrong. */ - if ((dmat->maxsize <= PAGE_SIZE) && - (dmat->alignment < dmat->maxsize) && - dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem) && + if ((dmat->common.maxsize <= PAGE_SIZE) && + (dmat->common.alignment < dmat->common.maxsize) && + dmat->common.lowaddr >= ptoa((vm_paddr_t)Maxmem) && attr == VM_MEMATTR_DEFAULT) { - *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags); - } else if (dmat->nsegments >= btoc(dmat->maxsize) && - dmat->alignment <= PAGE_SIZE && - (dmat->boundary == 0 || dmat->boundary >= dmat->lowaddr)) { + *vaddr = malloc(dmat->common.maxsize, M_DEVBUF, mflags); + } else if (dmat->common.nsegments >= btoc(dmat->common.maxsize) && + dmat->common.alignment <= PAGE_SIZE && + (dmat->common.boundary == 0 || + dmat->common.boundary >= dmat->common.lowaddr)) { /* Page-based multi-segment allocations allowed */ - *vaddr = (void *)kmem_alloc_attr(kernel_arena, dmat->maxsize, - mflags, 0ul, dmat->lowaddr, attr); + *vaddr = (void *)kmem_alloc_attr(kernel_arena, + dmat->common.maxsize, mflags, 0ul, dmat->common.lowaddr, + attr); *mapp = &contig_dmamap; } else { - *vaddr = (void *)kmem_alloc_contig(kernel_arena, dmat->maxsize, - mflags, 0ul, dmat->lowaddr, dmat->alignment ? - dmat->alignment : 1ul, dmat->boundary, attr); + *vaddr = (void *)kmem_alloc_contig(kernel_arena, + dmat->common.maxsize, mflags, 0ul, dmat->common.lowaddr, + dmat->common.alignment != 0 ? dmat->common.alignment : 1ul, + dmat->common.boundary, attr); *mapp = &contig_dmamap; } if (*vaddr == NULL) { CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", - __func__, dmat, dmat->flags, ENOMEM); + __func__, dmat, dmat->common.flags, ENOMEM); return (ENOMEM); - } else if (vtophys(*vaddr) & (dmat->alignment - 1)) { + } else if (vtophys(*vaddr) & (dmat->common.alignment - 1)) { printf("bus_dmamem_alloc failed to align memory properly.\n"); } CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", - __func__, dmat, dmat->flags, 0); + __func__, dmat, dmat->common.flags, 0); return (0); } @@ -569,8 +440,8 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi * 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) +static void +bounce_bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) { /* * dmamem does not need to be bounced, so the map should be @@ -582,8 +453,10 @@ bus_dmamem_free(bus_dma_tag_t dmat, void if (map == NULL) free(vaddr, M_DEVBUF); else - kmem_free(kernel_arena, (vm_offset_t)vaddr, dmat->maxsize); - CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags); + kmem_free(kernel_arena, (vm_offset_t)vaddr, + dmat->common.maxsize); + CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, + dmat->common.flags); } static void @@ -600,8 +473,8 @@ _bus_dmamap_count_phys(bus_dma_tag_t dma */ curaddr = buf; while (buflen != 0) { - sgsize = MIN(buflen, dmat->maxsegsz); - if (run_filter(dmat, curaddr)) { + sgsize = MIN(buflen, dmat->common.maxsegsz); + if (bus_dma_run_filter(&dmat->common, curaddr)) { sgsize = MIN(sgsize, PAGE_SIZE); map->pagesneeded++; } @@ -619,11 +492,13 @@ _bus_dmamap_count_pages(bus_dma_tag_t dm vm_offset_t vaddr; vm_offset_t vendaddr; bus_addr_t paddr; + bus_size_t sg_len; if ((map != &nobounce_dmamap && map->pagesneeded == 0)) { CTR4(KTR_BUSDMA, "lowaddr= %d Maxmem= %d, boundary= %d, " - "alignment= %d", dmat->lowaddr, ptoa((vm_paddr_t)Maxmem), - dmat->boundary, dmat->alignment); + "alignment= %d", dmat->common.lowaddr, + ptoa((vm_paddr_t)Maxmem), + dmat->common.boundary, dmat->common.alignment); CTR3(KTR_BUSDMA, "map= %p, nobouncemap= %p, pagesneeded= %d", map, &nobounce_dmamap, map->pagesneeded); /* @@ -634,15 +509,14 @@ _bus_dmamap_count_pages(bus_dma_tag_t dm vendaddr = (vm_offset_t)buf + buflen; while (vaddr < vendaddr) { - bus_size_t sg_len; - sg_len = PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK); if (pmap == kernel_pmap) paddr = pmap_kextract(vaddr); else paddr = pmap_extract(pmap, vaddr); - if (run_filter(dmat, paddr) != 0) { - sg_len = roundup2(sg_len, dmat->alignment); + if (bus_dma_run_filter(&dmat->common, paddr) != 0) { + sg_len = roundup2(sg_len, + dmat->common.alignment); map->pagesneeded++; } vaddr += sg_len; @@ -680,7 +554,7 @@ _bus_dmamap_reserve_pages(bus_dma_tag_t */ static int _bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr, - bus_size_t sgsize, bus_dma_segment_t *segs, int *segp) + bus_size_t sgsize, bus_dma_segment_t *segs, int *segp) { bus_addr_t baddr, bmask; int seg; @@ -688,9 +562,9 @@ _bus_dmamap_addseg(bus_dma_tag_t dmat, b /* * Make sure we don't cross any boundaries. */ - bmask = ~(dmat->boundary - 1); - if (dmat->boundary > 0) { - baddr = (curaddr + dmat->boundary) & bmask; + bmask = ~(dmat->common.boundary - 1); + if (dmat->common.boundary > 0) { + baddr = (curaddr + dmat->common.boundary) & bmask; if (sgsize > (baddr - curaddr)) sgsize = (baddr - curaddr); } @@ -706,12 +580,12 @@ _bus_dmamap_addseg(bus_dma_tag_t dmat, b segs[seg].ds_len = sgsize; } else { if (curaddr == segs[seg].ds_addr + segs[seg].ds_len && - (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && - (dmat->boundary == 0 || + (segs[seg].ds_len + sgsize) <= dmat->common.maxsegsz && + (dmat->common.boundary == 0 || (segs[seg].ds_addr & bmask) == (curaddr & bmask))) segs[seg].ds_len += sgsize; else { - if (++seg >= dmat->nsegments) + if (++seg >= dmat->common.nsegments) return (0); segs[seg].ds_addr = curaddr; segs[seg].ds_len = sgsize; @@ -725,13 +599,10 @@ _bus_dmamap_addseg(bus_dma_tag_t dmat, b * Utility function to load a physical buffer. segp contains * the starting segment on entrace, and the ending segment on exit. */ -int -_bus_dmamap_load_phys(bus_dma_tag_t dmat, - bus_dmamap_t map, - vm_paddr_t buf, bus_size_t buflen, - int flags, - bus_dma_segment_t *segs, - int *segp) +static int +bounce_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_paddr_t buf, bus_size_t buflen, int flags, bus_dma_segment_t *segs, + int *segp) { bus_size_t sgsize; bus_addr_t curaddr; @@ -743,7 +614,7 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat if (segs == NULL) segs = dmat->segments; - if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { + if ((dmat->common.flags & BUS_DMA_COULD_BOUNCE) != 0) { _bus_dmamap_count_phys(dmat, map, buf, buflen, flags); if (map->pagesneeded != 0) { error = _bus_dmamap_reserve_pages(dmat, map, flags); @@ -754,12 +625,13 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat while (buflen > 0) { curaddr = buf; - sgsize = MIN(buflen, dmat->maxsegsz); - if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) && - map->pagesneeded != 0 && run_filter(dmat, curaddr)) { + sgsize = MIN(buflen, dmat->common.maxsegsz); + if (((dmat->common.flags & BUS_DMA_COULD_BOUNCE) != 0) && + map->pagesneeded != 0 && + bus_dma_run_filter(&dmat->common, curaddr)) { sgsize = MIN(sgsize, PAGE_SIZE); curaddr = add_bounce_page(dmat, map, 0, curaddr, - sgsize); + sgsize); } sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, segp); @@ -779,16 +651,12 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat * Utility function to load a linear buffer. segp contains * the starting segment on entrace, and the ending segment on exit. */ -int -_bus_dmamap_load_buffer(bus_dma_tag_t dmat, - bus_dmamap_t map, - void *buf, bus_size_t buflen, - pmap_t pmap, - int flags, - bus_dma_segment_t *segs, - int *segp) +static int +bounce_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, + bus_size_t buflen, pmap_t pmap, int flags, bus_dma_segment_t *segs, + int *segp) { - bus_size_t sgsize; + bus_size_t sgsize, max_sgsize; bus_addr_t curaddr; vm_offset_t vaddr; int error; @@ -799,7 +667,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm if (segs == NULL) segs = dmat->segments; - if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { + if ((dmat->common.flags & BUS_DMA_COULD_BOUNCE) != 0) { _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags); if (map->pagesneeded != 0) { error = _bus_dmamap_reserve_pages(dmat, map, flags); @@ -809,10 +677,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm } vaddr = (vm_offset_t)buf; - while (buflen > 0) { - bus_size_t max_sgsize; - /* * Get the physical address for this segment. */ @@ -824,19 +689,20 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm /* * Compute the segment size, and adjust counts. */ - max_sgsize = MIN(buflen, dmat->maxsegsz); + max_sgsize = MIN(buflen, dmat->common.maxsegsz); sgsize = PAGE_SIZE - ((vm_offset_t)curaddr & PAGE_MASK); - if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) && - map->pagesneeded != 0 && run_filter(dmat, curaddr)) { - sgsize = roundup2(sgsize, dmat->alignment); + if (((dmat->common.flags & BUS_DMA_COULD_BOUNCE) != 0) && + map->pagesneeded != 0 && + bus_dma_run_filter(&dmat->common, curaddr)) { + sgsize = roundup2(sgsize, dmat->common.alignment); sgsize = MIN(sgsize, max_sgsize); curaddr = add_bounce_page(dmat, map, vaddr, curaddr, - sgsize); + sgsize); } else { sgsize = MIN(sgsize, max_sgsize); } sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, - segp); + segp); if (sgsize == 0) break; vaddr += sgsize; @@ -849,32 +715,22 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */ } -int -_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map, - struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags, - bus_dma_segment_t *segs, int *segp) +static void +bounce_bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg) { - return (bus_dmamap_load_ma_triv(dmat, map, ma, tlen, ma_offs, flags, - segs, segp)); -} - -void -__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, - struct memdesc *mem, bus_dmamap_callback_t *callback, - void *callback_arg) -{ - if (map != NULL) { - map->mem = *mem; - map->dmat = dmat; - map->callback = callback; - map->callback_arg = callback_arg; - } + if (map == NULL) + return; + map->mem = *mem; + map->dmat = dmat; + map->callback = callback; + map->callback_arg = callback_arg; } -bus_dma_segment_t * -_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, - bus_dma_segment_t *segs, int nsegs, int error) +static bus_dma_segment_t * +bounce_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error) { if (segs == NULL) @@ -885,8 +741,8 @@ _bus_dmamap_complete(bus_dma_tag_t dmat, /* * Release the mapping held by map. */ -void -_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) +static void +bounce_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) { struct bounce_page *bpage; @@ -896,8 +752,9 @@ _bus_dmamap_unload(bus_dma_tag_t dmat, b } } -void -_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) +static void +bounce_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmasync_op_t op) { struct bounce_page *bpage; @@ -908,33 +765,36 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus * the caches on broken hardware */ CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x " - "performing bounce", __func__, dmat, dmat->flags, op); + "performing bounce", __func__, dmat, + dmat->common.flags, op); - if (op & BUS_DMASYNC_PREWRITE) { + if ((op & BUS_DMASYNC_PREWRITE) != 0) { while (bpage != NULL) { - if (bpage->datavaddr != 0) + if (bpage->datavaddr != 0) { bcopy((void *)bpage->datavaddr, - (void *)bpage->vaddr, - bpage->datacount); - else + (void *)bpage->vaddr, + bpage->datacount); + } else { physcopyout(bpage->dataaddr, - (void *)bpage->vaddr, - bpage->datacount); + (void *)bpage->vaddr, + bpage->datacount); + } bpage = STAILQ_NEXT(bpage, links); } dmat->bounce_zone->total_bounced++; } - if (op & BUS_DMASYNC_POSTREAD) { + if ((op & BUS_DMASYNC_POSTREAD) != 0) { while (bpage != NULL) { - if (bpage->datavaddr != 0) + if (bpage->datavaddr != 0) { bcopy((void *)bpage->vaddr, - (void *)bpage->datavaddr, - bpage->datacount); - else + (void *)bpage->datavaddr, + bpage->datacount); + } else { physcopyin((void *)bpage->vaddr, - bpage->dataaddr, - bpage->datacount); + bpage->dataaddr, + bpage->datacount); + } bpage = STAILQ_NEXT(bpage, links); } dmat->bounce_zone->total_bounced++; @@ -980,8 +840,8 @@ alloc_bounce_zone(bus_dma_tag_t dmat) /* Check to see if we already have a suitable zone */ STAILQ_FOREACH(bz, &bounce_zone_list, links) { - if ((dmat->alignment <= bz->alignment) - && (dmat->lowaddr >= bz->lowaddr)) { + if ((dmat->common.alignment <= bz->alignment) && + (dmat->common.lowaddr >= bz->lowaddr)) { dmat->bounce_zone = bz; return (0); } @@ -995,8 +855,8 @@ alloc_bounce_zone(bus_dma_tag_t dmat) bz->free_bpages = 0; bz->reserved_bpages = 0; bz->active_bpages = 0; - bz->lowaddr = dmat->lowaddr; - bz->alignment = MAX(dmat->alignment, PAGE_SIZE); + bz->lowaddr = dmat->common.lowaddr; + bz->alignment = MAX(dmat->common.alignment, PAGE_SIZE); bz->map_count = 0; snprintf(bz->zoneid, 8, "zone%d", busdma_zonecount); busdma_zonecount++; @@ -1134,7 +994,7 @@ add_bounce_page(bus_dma_tag_t dmat, bus_ bz->active_bpages++; mtx_unlock(&bounce_lock); - if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) { + if (dmat->common.flags & BUS_DMA_KEEP_PG_OFFSET) { /* Page offset needs to be preserved. */ bpage->vaddr |= vaddr & PAGE_MASK; bpage->busaddr |= vaddr & PAGE_MASK; @@ -1155,7 +1015,7 @@ free_bounce_page(bus_dma_tag_t dmat, str bz = dmat->bounce_zone; bpage->datavaddr = 0; bpage->datacount = 0; - if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) { + if (dmat->common.flags & BUS_DMA_KEEP_PG_OFFSET) { /* * Reset the bounce page to start at offset 0. Other uses * of this bounce page may need to store a full page of @@ -1173,7 +1033,7 @@ free_bounce_page(bus_dma_tag_t dmat, str if (reserve_bounce_pages(map->dmat, map, 1) == 0) { STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links); STAILQ_INSERT_TAIL(&bounce_map_callbacklist, - map, links); + map, links); busdma_swi_pending = 1; bz->total_deferred++; swi_sched(vm_ih, 0); @@ -1193,12 +1053,28 @@ busdma_swi(void) STAILQ_REMOVE_HEAD(&bounce_map_callbacklist, links); mtx_unlock(&bounce_lock); dmat = map->dmat; - (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK); + (dmat->common.lockfunc)(dmat->common.lockfuncarg, BUS_DMA_LOCK); bus_dmamap_load_mem(map->dmat, map, &map->mem, - map->callback, map->callback_arg, - BUS_DMA_WAITOK); - (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK); + map->callback, map->callback_arg, BUS_DMA_WAITOK); + (dmat->common.lockfunc)(dmat->common.lockfuncarg, + BUS_DMA_UNLOCK); mtx_lock(&bounce_lock); } mtx_unlock(&bounce_lock); } + +struct bus_dma_impl bus_dma_bounce_impl = { + .tag_create = bounce_bus_dma_tag_create, + .tag_destroy = bounce_bus_dma_tag_destroy, *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***