]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/arm/arm/busdma_machdep-v6.c
MFC r257228:
[FreeBSD/stable/10.git] / sys / arm / arm / busdma_machdep-v6.c
1 /*-
2  * Copyright (c) 2012 Ian Lepore
3  * Copyright (c) 2010 Mark Tinguely
4  * Copyright (c) 2004 Olivier Houchard
5  * Copyright (c) 2002 Peter Grehan
6  * Copyright (c) 1997, 1998 Justin T. Gibbs.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions, and the following disclaimer,
14  *    without modification, immediately at the beginning of the file.
15  * 2. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
22  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  *  From i386/busdma_machdep.c 191438 2009-04-23 20:24:19Z jhb
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #define _ARM32_BUS_DMA_PRIVATE
37 #include <sys/param.h>
38 #include <sys/kdb.h>
39 #include <ddb/ddb.h>
40 #include <ddb/db_output.h>
41 #include <sys/systm.h>
42 #include <sys/malloc.h>
43 #include <sys/bus.h>
44 #include <sys/busdma_bufalloc.h>
45 #include <sys/interrupt.h>
46 #include <sys/kernel.h>
47 #include <sys/ktr.h>
48 #include <sys/lock.h>
49 #include <sys/memdesc.h>
50 #include <sys/proc.h>
51 #include <sys/mutex.h>
52 #include <sys/sysctl.h>
53 #include <sys/uio.h>
54
55 #include <vm/vm.h>
56 #include <vm/vm_page.h>
57 #include <vm/vm_map.h>
58 #include <vm/vm_extern.h>
59 #include <vm/vm_kern.h>
60
61 #include <machine/atomic.h>
62 #include <machine/bus.h>
63 #include <machine/cpufunc.h>
64 #include <machine/md_var.h>
65
66 #define MAX_BPAGES 64
67 #define BUS_DMA_COULD_BOUNCE    BUS_DMA_BUS3
68 #define BUS_DMA_MIN_ALLOC_COMP  BUS_DMA_BUS4
69
70 struct bounce_zone;
71
72 struct bus_dma_tag {
73         bus_dma_tag_t     parent;
74         bus_size_t        alignment;
75         bus_size_t        boundary;
76         bus_addr_t        lowaddr;
77         bus_addr_t        highaddr;
78         bus_dma_filter_t *filter;
79         void             *filterarg;
80         bus_size_t        maxsize;
81         u_int             nsegments;
82         bus_size_t        maxsegsz;
83         int               flags;
84         int               ref_count;
85         int               map_count;
86         bus_dma_lock_t   *lockfunc;
87         void             *lockfuncarg;
88         struct bounce_zone *bounce_zone;
89         /*
90          * DMA range for this tag.  If the page doesn't fall within
91          * one of these ranges, an error is returned.  The caller
92          * may then decide what to do with the transfer.  If the
93          * range pointer is NULL, it is ignored.
94          */
95         struct arm32_dma_range  *ranges;
96         int                     _nranges;
97         /*
98          * Most tags need one or two segments, and can use the local tagsegs
99          * array.  For tags with a larger limit, we'll allocate a bigger array
100          * on first use.
101          */
102         bus_dma_segment_t       *segments;
103         bus_dma_segment_t       tagsegs[2];
104
105
106 };
107
108 struct bounce_page {
109         vm_offset_t     vaddr;          /* kva of bounce buffer */
110         bus_addr_t      busaddr;        /* Physical address */
111         vm_offset_t     datavaddr;      /* kva of client data */
112         bus_addr_t      dataaddr;       /* client physical address */
113         bus_size_t      datacount;      /* client data count */
114         STAILQ_ENTRY(bounce_page) links;
115 };
116
117 struct sync_list {
118         vm_offset_t     vaddr;          /* kva of bounce buffer */
119         bus_addr_t      busaddr;        /* Physical address */
120         bus_size_t      datacount;      /* client data count */
121 };
122
123 int busdma_swi_pending;
124
125 struct bounce_zone {
126         STAILQ_ENTRY(bounce_zone) links;
127         STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
128         int             total_bpages;
129         int             free_bpages;
130         int             reserved_bpages;
131         int             active_bpages;
132         int             total_bounced;
133         int             total_deferred;
134         int             map_count;
135         bus_size_t      alignment;
136         bus_addr_t      lowaddr;
137         char            zoneid[8];
138         char            lowaddrid[20];
139         struct sysctl_ctx_list sysctl_tree;
140         struct sysctl_oid *sysctl_tree_top;
141 };
142
143 static struct mtx bounce_lock;
144 static int total_bpages;
145 static int busdma_zonecount;
146 static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
147
148 SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD, 0, "Busdma parameters");
149 SYSCTL_INT(_hw_busdma, OID_AUTO, total_bpages, CTLFLAG_RD, &total_bpages, 0,
150            "Total bounce pages");
151
152 struct bus_dmamap {
153         struct bp_list         bpages;
154         int                    pagesneeded;
155         int                    pagesreserved;
156         bus_dma_tag_t          dmat;
157         struct memdesc         mem;
158         pmap_t                 pmap;
159         bus_dmamap_callback_t *callback;
160         void                  *callback_arg;
161         int                   flags;
162 #define DMAMAP_COHERENT         (1 << 0)
163         STAILQ_ENTRY(bus_dmamap) links;
164         int                    sync_count;
165         struct sync_list       slist[];
166 };
167
168 static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
169 static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist;
170
171 static void init_bounce_pages(void *dummy);
172 static int alloc_bounce_zone(bus_dma_tag_t dmat);
173 static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages);
174 static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
175                                 int commit);
176 static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map,
177                                   vm_offset_t vaddr, bus_addr_t addr,
178                                   bus_size_t size);
179 static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage);
180 int run_filter(bus_dma_tag_t dmat, bus_addr_t paddr, bus_size_t size, int coherent);
181 static void _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
182     void *buf, bus_size_t buflen, int flags);
183 static void _bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map,
184     vm_paddr_t buf, bus_size_t buflen, int flags);
185 static int _bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
186     int flags);
187
188 static busdma_bufalloc_t coherent_allocator;    /* Cache of coherent buffers */
189 static busdma_bufalloc_t standard_allocator;    /* Cache of standard buffers */
190 static void
191 busdma_init(void *dummy)
192 {
193         int uma_flags;
194
195         uma_flags = 0;
196
197         /* Create a cache of buffers in standard (cacheable) memory. */
198         standard_allocator = busdma_bufalloc_create("buffer", 
199             arm_dcache_align,   /* minimum_alignment */
200             NULL,               /* uma_alloc func */ 
201             NULL,               /* uma_free func */
202             uma_flags);         /* uma_zcreate_flags */
203
204 #ifdef INVARIANTS
205         /* 
206          * Force UMA zone to allocate service structures like
207          * slabs using own allocator. uma_debug code performs
208          * atomic ops on uma_slab_t fields and safety of this
209          * operation is not guaranteed for write-back caches
210          */
211         uma_flags = UMA_ZONE_OFFPAGE;
212 #endif
213         /*
214          * Create a cache of buffers in uncacheable memory, to implement the
215          * BUS_DMA_COHERENT (and potentially BUS_DMA_NOCACHE) flag.
216          */
217         coherent_allocator = busdma_bufalloc_create("coherent",
218             arm_dcache_align,   /* minimum_alignment */
219             busdma_bufalloc_alloc_uncacheable, 
220             busdma_bufalloc_free_uncacheable, 
221             uma_flags); /* uma_zcreate_flags */
222 }
223
224 /*
225  * This init historically used SI_SUB_VM, but now the init code requires
226  * malloc(9) using M_DEVBUF memory, which is set up later than SI_SUB_VM, by
227  * SI_SUB_KMEM and SI_ORDER_SECOND, so we'll go right after that by using
228  * SI_SUB_KMEM and SI_ORDER_THIRD.
229  */
230 SYSINIT(busdma, SI_SUB_KMEM, SI_ORDER_THIRD, busdma_init, NULL);
231
232 static __inline int
233 _bus_dma_can_bounce(vm_offset_t lowaddr, vm_offset_t highaddr)
234 {
235         int i;
236         for (i = 0; phys_avail[i] && phys_avail[i + 1]; i += 2) {
237                 if ((lowaddr >= phys_avail[i] && lowaddr <= phys_avail[i + 1])
238                     || (lowaddr < phys_avail[i] &&
239                     highaddr > phys_avail[i]))
240                         return (1);
241         }
242         return (0);
243 }
244
245 static __inline struct arm32_dma_range *
246 _bus_dma_inrange(struct arm32_dma_range *ranges, int nranges,
247     bus_addr_t curaddr)
248 {
249         struct arm32_dma_range *dr;
250         int i;
251
252         for (i = 0, dr = ranges; i < nranges; i++, dr++) {
253                 if (curaddr >= dr->dr_sysbase &&
254                     round_page(curaddr) <= (dr->dr_sysbase + dr->dr_len))
255                         return (dr);
256         }
257
258         return (NULL);
259 }
260
261 /*
262  * Return true if a match is made.
263  *
264  * To find a match walk the chain of bus_dma_tag_t's looking for 'paddr'.
265  *
266  * If paddr is within the bounds of the dma tag then call the filter callback
267  * to check for a match, if there is no filter callback then assume a match.
268  */
269 int
270 run_filter(bus_dma_tag_t dmat, bus_addr_t paddr, bus_size_t size, int coherent)
271 {
272         int retval;
273
274         retval = 0;
275
276         do {
277                 if (((paddr > dmat->lowaddr && paddr <= dmat->highaddr)
278                  || ((paddr & (dmat->alignment - 1)) != 0) ||
279                  (!coherent && (size & arm_dcache_align_mask)) ||
280                  (!coherent && (paddr & arm_dcache_align_mask)))
281                  && (dmat->filter == NULL
282                   || (*dmat->filter)(dmat->filterarg, paddr) != 0))
283                         retval = 1;
284
285                 dmat = dmat->parent;
286         } while (retval == 0 && dmat != NULL);
287         return (retval);
288 }
289
290 /*
291  * Convenience function for manipulating driver locks from busdma (during
292  * busdma_swi, for example).  Drivers that don't provide their own locks
293  * should specify &Giant to dmat->lockfuncarg.  Drivers that use their own
294  * non-mutex locking scheme don't have to use this at all.
295  */
296 void
297 busdma_lock_mutex(void *arg, bus_dma_lock_op_t op)
298 {
299         struct mtx *dmtx;
300
301         dmtx = (struct mtx *)arg;
302         switch (op) {
303         case BUS_DMA_LOCK:
304                 mtx_lock(dmtx);
305                 break;
306         case BUS_DMA_UNLOCK:
307                 mtx_unlock(dmtx);
308                 break;
309         default:
310                 panic("Unknown operation 0x%x for busdma_lock_mutex!", op);
311         }
312 }
313
314 /*
315  * dflt_lock should never get called.  It gets put into the dma tag when
316  * lockfunc == NULL, which is only valid if the maps that are associated
317  * with the tag are meant to never be defered.
318  * XXX Should have a way to identify which driver is responsible here.
319  */
320 static void
321 dflt_lock(void *arg, bus_dma_lock_op_t op)
322 {
323         panic("driver error: busdma dflt_lock called");
324 }
325
326 /*
327  * Allocate a device specific dma_tag.
328  */
329 int
330 bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
331                    bus_size_t boundary, bus_addr_t lowaddr,
332                    bus_addr_t highaddr, bus_dma_filter_t *filter,
333                    void *filterarg, bus_size_t maxsize, int nsegments,
334                    bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
335                    void *lockfuncarg, bus_dma_tag_t *dmat)
336 {
337         bus_dma_tag_t newtag;
338         int error = 0;
339
340 #if 0
341         if (!parent)
342                 parent = arm_root_dma_tag;
343 #endif
344
345         /* Basic sanity checking */
346         if (boundary != 0 && boundary < maxsegsz)
347                 maxsegsz = boundary;
348
349         /* Return a NULL tag on failure */
350         *dmat = NULL;
351
352         if (maxsegsz == 0) {
353                 return (EINVAL);
354         }
355
356         newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF,
357             M_ZERO | M_NOWAIT);
358         if (newtag == NULL) {
359                 CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
360                     __func__, newtag, 0, error);
361                 return (ENOMEM);
362         }
363
364         newtag->parent = parent;
365         newtag->alignment = alignment;
366         newtag->boundary = boundary;
367         newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1);
368         newtag->highaddr = trunc_page((vm_paddr_t)highaddr) +
369             (PAGE_SIZE - 1);
370         newtag->filter = filter;
371         newtag->filterarg = filterarg;
372         newtag->maxsize = maxsize;
373         newtag->nsegments = nsegments;
374         newtag->maxsegsz = maxsegsz;
375         newtag->flags = flags;
376         newtag->ref_count = 1; /* Count ourself */
377         newtag->map_count = 0;
378         newtag->ranges = bus_dma_get_range();
379         newtag->_nranges = bus_dma_get_range_nb();
380         if (lockfunc != NULL) {
381                 newtag->lockfunc = lockfunc;
382                 newtag->lockfuncarg = lockfuncarg;
383         } else {
384                 newtag->lockfunc = dflt_lock;
385                 newtag->lockfuncarg = NULL;
386         }
387         /*
388          * If all the segments we need fit into the local tagsegs array, set the
389          * pointer now.  Otherwise NULL the pointer and an array of segments
390          * will be allocated later, on first use.  We don't pre-allocate now
391          * because some tags exist just to pass contraints to children in the
392          * device hierarchy, and they tend to use BUS_SPACE_UNRESTRICTED and we
393          * sure don't want to try to allocate an array for that.
394          */
395         if (newtag->nsegments <= nitems(newtag->tagsegs))
396                 newtag->segments = newtag->tagsegs;
397         else
398                 newtag->segments = NULL;
399
400         /* Take into account any restrictions imposed by our parent tag */
401         if (parent != NULL) {
402                 newtag->lowaddr = MIN(parent->lowaddr, newtag->lowaddr);
403                 newtag->highaddr = MAX(parent->highaddr, newtag->highaddr);
404                 if (newtag->boundary == 0)
405                         newtag->boundary = parent->boundary;
406                 else if (parent->boundary != 0)
407                         newtag->boundary = MIN(parent->boundary,
408                                                newtag->boundary);
409                 if ((newtag->filter != NULL) ||
410                     ((parent->flags & BUS_DMA_COULD_BOUNCE) != 0))
411                         newtag->flags |= BUS_DMA_COULD_BOUNCE;
412                 if (newtag->filter == NULL) {
413                         /*
414                          * Short circuit looking at our parent directly
415                          * since we have encapsulated all of its information
416                          */
417                         newtag->filter = parent->filter;
418                         newtag->filterarg = parent->filterarg;
419                         newtag->parent = parent->parent;
420                 }
421                 if (newtag->parent != NULL)
422                         atomic_add_int(&parent->ref_count, 1);
423         }
424
425         if (_bus_dma_can_bounce(newtag->lowaddr, newtag->highaddr)
426          || newtag->alignment > 1)
427                 newtag->flags |= BUS_DMA_COULD_BOUNCE;
428
429         /*
430          * Any request can auto-bounce due to cacheline alignment, in addition
431          * to any alignment or boundary specifications in the tag, so if the
432          * ALLOCNOW flag is set, there's always work to do.
433          */
434         if ((flags & BUS_DMA_ALLOCNOW) != 0) {
435                 struct bounce_zone *bz;
436                 /*
437                  * Round size up to a full page, and add one more page because
438                  * there can always be one more boundary crossing than the
439                  * number of pages in a transfer.
440                  */
441                 maxsize = roundup2(maxsize, PAGE_SIZE) + PAGE_SIZE;
442                 
443                 if ((error = alloc_bounce_zone(newtag)) != 0) {
444                         free(newtag, M_DEVBUF);
445                         return (error);
446                 }
447                 bz = newtag->bounce_zone;
448
449                 if (ptoa(bz->total_bpages) < maxsize) {
450                         int pages;
451
452                         pages = atop(maxsize) - bz->total_bpages;
453
454                         /* Add pages to our bounce pool */
455                         if (alloc_bounce_pages(newtag, pages) < pages)
456                                 error = ENOMEM;
457                 }
458                 /* Performed initial allocation */
459                 newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
460         } else
461                 newtag->bounce_zone = NULL;
462
463         if (error != 0) {
464                 free(newtag, M_DEVBUF);
465         } else {
466                 *dmat = newtag;
467         }
468         CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
469             __func__, newtag, (newtag != NULL ? newtag->flags : 0), error);
470         return (error);
471 }
472
473 int
474 bus_dma_tag_destroy(bus_dma_tag_t dmat)
475 {
476         bus_dma_tag_t dmat_copy;
477         int error;
478
479         error = 0;
480         dmat_copy = dmat;
481
482         if (dmat != NULL) {
483
484                 if (dmat->map_count != 0) {
485                         error = EBUSY;
486                         goto out;
487                 }
488
489                 while (dmat != NULL) {
490                         bus_dma_tag_t parent;
491
492                         parent = dmat->parent;
493                         atomic_subtract_int(&dmat->ref_count, 1);
494                         if (dmat->ref_count == 0) {
495                                 if (dmat->segments != NULL &&
496                                     dmat->segments != dmat->tagsegs)
497                                         free(dmat->segments, M_DEVBUF);
498                                 free(dmat, M_DEVBUF);
499                                 /*
500                                  * Last reference count, so
501                                  * release our reference
502                                  * count on our parent.
503                                  */
504                                 dmat = parent;
505                         } else
506                                 dmat = NULL;
507                 }
508         }
509 out:
510         CTR3(KTR_BUSDMA, "%s tag %p error %d", __func__, dmat_copy, error);
511         return (error);
512 }
513
514 static int allocate_bz_and_pages(bus_dma_tag_t dmat, bus_dmamap_t mapp)
515 {
516         struct bounce_zone *bz;
517         int maxpages;
518         int error;
519                 
520         if (dmat->bounce_zone == NULL)
521                 if ((error = alloc_bounce_zone(dmat)) != 0)
522                         return (error);
523         bz = dmat->bounce_zone;
524         /* Initialize the new map */
525         STAILQ_INIT(&(mapp->bpages));
526
527         /*
528          * Attempt to add pages to our pool on a per-instance basis up to a sane
529          * limit.  Even if the tag isn't flagged as COULD_BOUNCE due to
530          * alignment and boundary constraints, it could still auto-bounce due to
531          * cacheline alignment, which requires at most two bounce pages.
532          */
533         if (dmat->flags & BUS_DMA_COULD_BOUNCE)
534                 maxpages = MAX_BPAGES;
535         else
536                 maxpages = 2 * bz->map_count;
537         if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0
538             || (bz->map_count > 0 && bz->total_bpages < maxpages)) {
539                 int pages;
540                 
541                 pages = atop(roundup2(dmat->maxsize, PAGE_SIZE)) + 1;
542                 pages = MIN(maxpages - bz->total_bpages, pages);
543                 pages = MAX(pages, 2);
544                 if (alloc_bounce_pages(dmat, pages) < pages)
545                         return (ENOMEM);
546                 
547                 if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0)
548                         dmat->flags |= BUS_DMA_MIN_ALLOC_COMP;
549         }
550         bz->map_count++;
551         return (0);
552 }
553
554 /*
555  * Allocate a handle for mapping from kva/uva/physical
556  * address space into bus device space.
557  */
558 int
559 bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
560 {
561         int mapsize;
562         int error = 0;
563
564         mapsize = sizeof(**mapp) + (sizeof(struct sync_list) * dmat->nsegments);
565         *mapp = (bus_dmamap_t)malloc(mapsize, M_DEVBUF, M_NOWAIT | M_ZERO);
566         if (*mapp == NULL) {
567                 CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, ENOMEM);
568                 return (ENOMEM);
569         }
570         (*mapp)->sync_count = 0;
571
572         if (dmat->segments == NULL) {
573                 dmat->segments = (bus_dma_segment_t *)malloc(
574                     sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
575                     M_NOWAIT);
576                 if (dmat->segments == NULL) {
577                         CTR3(KTR_BUSDMA, "%s: tag %p error %d",
578                             __func__, dmat, ENOMEM);
579                         free(*mapp, M_DEVBUF);
580                         *mapp = NULL;
581                         return (ENOMEM);
582                 }
583         }
584         /*
585          * Bouncing might be required if the driver asks for an active
586          * exclusion region, a data alignment that is stricter than 1, and/or
587          * an active address boundary.
588          */
589         error = allocate_bz_and_pages(dmat, *mapp);
590         if (error != 0) {
591                 free(*mapp, M_DEVBUF);
592                 *mapp = NULL;
593                 return (error);
594         }
595         return (error);
596 }
597
598 /*
599  * Destroy a handle for mapping from kva/uva/physical
600  * address space into bus device space.
601  */
602 int
603 bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
604 {
605         if (STAILQ_FIRST(&map->bpages) != NULL || map->sync_count != 0) {
606                 CTR3(KTR_BUSDMA, "%s: tag %p error %d",
607                     __func__, dmat, EBUSY);
608                 return (EBUSY);
609         }
610         if (dmat->bounce_zone)
611                 dmat->bounce_zone->map_count--;
612         free(map, M_DEVBUF);
613         dmat->map_count--;
614         CTR2(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat);
615         return (0);
616 }
617
618
619 /*
620  * Allocate a piece of memory that can be efficiently mapped into
621  * bus device space based on the constraints lited in the dma tag.
622  * A dmamap to for use with dmamap_load is also allocated.
623  */
624 int
625 bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
626                  bus_dmamap_t *mapp)
627 {
628         busdma_bufalloc_t ba;
629         struct busdma_bufzone *bufzone;
630         vm_memattr_t memattr;
631         int mflags;
632         int mapsize;
633         int error;
634
635         if (flags & BUS_DMA_NOWAIT)
636                 mflags = M_NOWAIT;
637         else
638                 mflags = M_WAITOK;
639
640         /* ARM non-snooping caches need a map for the VA cache sync structure */
641
642         mapsize = sizeof(**mapp) + (sizeof(struct sync_list) * dmat->nsegments);
643         *mapp = (bus_dmamap_t)malloc(mapsize, M_DEVBUF, M_NOWAIT | M_ZERO);
644         if (*mapp == NULL) {
645                 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
646                     __func__, dmat, dmat->flags, ENOMEM);
647                 return (ENOMEM);
648         }
649
650         (*mapp)->sync_count = 0;
651         /* We may need bounce pages, even for allocated memory */
652         error = allocate_bz_and_pages(dmat, *mapp);
653         if (error != 0) {
654                 free(*mapp, M_DEVBUF);
655                 *mapp = NULL;
656                 return (error);
657         }
658
659         if (dmat->segments == NULL) {
660                 dmat->segments = (bus_dma_segment_t *)malloc(
661                     sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
662                     mflags);
663                 if (dmat->segments == NULL) {
664                         CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
665                             __func__, dmat, dmat->flags, ENOMEM);
666                         free(*mapp, M_DEVBUF);
667                         *mapp = NULL;
668                         return (ENOMEM);
669                 }
670         }
671
672         if (flags & BUS_DMA_ZERO)
673                 mflags |= M_ZERO;
674         if (flags & BUS_DMA_COHERENT) {
675                 memattr = VM_MEMATTR_UNCACHEABLE;
676                 ba = coherent_allocator;
677                 (*mapp)->flags |= DMAMAP_COHERENT;
678         } else {
679                 memattr = VM_MEMATTR_DEFAULT;
680                 ba = standard_allocator;
681                 (*mapp)->flags = 0;
682         }
683
684         /*
685          * Try to find a bufzone in the allocator that holds a cache of buffers
686          * of the right size for this request.  If the buffer is too big to be
687          * held in the allocator cache, this returns NULL.
688          */
689         bufzone = busdma_bufalloc_findzone(ba, dmat->maxsize);
690
691         /*
692          * Allocate the buffer from the uma(9) allocator if...
693          *  - It's small enough to be in the allocator (bufzone not NULL).
694          *  - The alignment constraint isn't larger than the allocation size
695          *    (the allocator aligns buffers to their size boundaries).
696          *  - There's no need to handle lowaddr/highaddr exclusion zones.
697          * else allocate non-contiguous pages if...
698          *  - The page count that could get allocated doesn't exceed nsegments.
699          *  - The alignment constraint isn't larger than a page boundary.
700          *  - There are no boundary-crossing constraints.
701          * else allocate a block of contiguous pages because one or more of the
702          * constraints is something that only the contig allocator can fulfill.
703          */
704         if (bufzone != NULL && dmat->alignment <= bufzone->size &&
705             !_bus_dma_can_bounce(dmat->lowaddr, dmat->highaddr)) {
706                 *vaddr = uma_zalloc(bufzone->umazone, mflags);
707         } else if (dmat->nsegments >= btoc(dmat->maxsize) &&
708             dmat->alignment <= PAGE_SIZE && dmat->boundary == 0) {
709                 *vaddr = (void *)kmem_alloc_attr(kernel_arena, dmat->maxsize,
710                     mflags, 0, dmat->lowaddr, memattr);
711         } else {
712                 *vaddr = (void *)kmem_alloc_contig(kernel_arena, dmat->maxsize,
713                     mflags, 0, dmat->lowaddr, dmat->alignment, dmat->boundary,
714                     memattr);
715         }
716
717
718         if (*vaddr == NULL) {
719                 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
720                     __func__, dmat, dmat->flags, ENOMEM);
721                 free(*mapp, M_DEVBUF);
722                 *mapp = NULL;
723                 return (ENOMEM);
724         } else if ((uintptr_t)*vaddr & (dmat->alignment - 1)) {
725                 printf("bus_dmamem_alloc failed to align memory properly.\n");
726         }
727         dmat->map_count++;
728
729         CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
730             __func__, dmat, dmat->flags, 0);
731         return (0);
732 }
733
734 /*
735  * Free a piece of memory and it's allociated dmamap, that was allocated
736  * via bus_dmamem_alloc.  Make the same choice for free/contigfree.
737  */
738 void
739 bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
740 {
741         struct busdma_bufzone *bufzone;
742         busdma_bufalloc_t ba;
743
744         if (map->flags & DMAMAP_COHERENT)
745                 ba = coherent_allocator;
746         else
747                 ba = standard_allocator;
748
749         /* Be careful not to access map from here on. */
750
751         bufzone = busdma_bufalloc_findzone(ba, dmat->maxsize);
752
753         if (bufzone != NULL && dmat->alignment <= bufzone->size &&
754             !_bus_dma_can_bounce(dmat->lowaddr, dmat->highaddr))
755                 uma_zfree(bufzone->umazone, vaddr);
756         else
757                 kmem_free(kernel_arena, (vm_offset_t)vaddr, dmat->maxsize);
758
759         dmat->map_count--;
760         free(map, M_DEVBUF);
761         CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
762 }
763
764 static void
765 _bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf,
766     bus_size_t buflen, int flags)
767 {
768         bus_addr_t curaddr;
769         bus_size_t sgsize;
770
771         if (map->pagesneeded == 0) {
772                 CTR5(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d"
773                     " map= %p, pagesneeded= %d",
774                     dmat->lowaddr, dmat->boundary, dmat->alignment,
775                     map, map->pagesneeded);
776                 /*
777                  * Count the number of bounce pages
778                  * needed in order to complete this transfer
779                  */
780                 curaddr = buf;
781                 while (buflen != 0) {
782                         sgsize = MIN(buflen, dmat->maxsegsz);
783                         if (run_filter(dmat, curaddr, sgsize, 
784                             map->flags & DMAMAP_COHERENT) != 0) {
785                                 sgsize = MIN(sgsize, PAGE_SIZE);
786                                 map->pagesneeded++;
787                         }
788                         curaddr += sgsize;
789                         buflen -= sgsize;
790                 }
791                 CTR1(KTR_BUSDMA, "pagesneeded= %d", map->pagesneeded);
792         }
793 }
794
795 static void
796 _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
797     void *buf, bus_size_t buflen, int flags)
798 {
799         vm_offset_t vaddr;
800         vm_offset_t vendaddr;
801         bus_addr_t paddr;
802
803         if (map->pagesneeded == 0) {
804                 CTR5(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d"
805                     " map= %p, pagesneeded= %d",
806                     dmat->lowaddr, dmat->boundary, dmat->alignment,
807                     map, map->pagesneeded);
808                 /*
809                  * Count the number of bounce pages
810                  * needed in order to complete this transfer
811                  */
812                 vaddr = (vm_offset_t)buf;
813                 vendaddr = (vm_offset_t)buf + buflen;
814
815                 while (vaddr < vendaddr) {
816                         if (__predict_true(map->pmap == kernel_pmap))
817                                 paddr = pmap_kextract(vaddr);
818                         else
819                                 paddr = pmap_extract(map->pmap, vaddr);
820                         if (run_filter(dmat, paddr,
821                             min(vendaddr - vaddr, 
822                             (PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK))),
823                             map->flags & DMAMAP_COHERENT) != 0) {
824                                 map->pagesneeded++;
825                         }
826                         vaddr += (PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK));
827
828                 }
829                 CTR1(KTR_BUSDMA, "pagesneeded= %d", map->pagesneeded);
830         }
831 }
832
833 static int
834 _bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags)
835 {
836
837         /* Reserve Necessary Bounce Pages */
838         mtx_lock(&bounce_lock);
839         if (flags & BUS_DMA_NOWAIT) {
840                 if (reserve_bounce_pages(dmat, map, 0) != 0) {
841                         map->pagesneeded = 0;
842                         mtx_unlock(&bounce_lock);
843                         return (ENOMEM);
844                 }
845         } else {
846                 if (reserve_bounce_pages(dmat, map, 1) != 0) {
847                         /* Queue us for resources */
848                         STAILQ_INSERT_TAIL(&bounce_map_waitinglist, map, links);
849                         mtx_unlock(&bounce_lock);
850                         return (EINPROGRESS);
851                 }
852         }
853         mtx_unlock(&bounce_lock);
854
855         return (0);
856 }
857
858 /*
859  * Add a single contiguous physical range to the segment list.
860  */
861 static int
862 _bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr,
863                    bus_size_t sgsize, bus_dma_segment_t *segs, int *segp)
864 {
865         bus_addr_t baddr, bmask;
866         int seg;
867
868         /*
869          * Make sure we don't cross any boundaries.
870          */
871         bmask = ~(dmat->boundary - 1);
872         if (dmat->boundary > 0) {
873                 baddr = (curaddr + dmat->boundary) & bmask;
874                 if (sgsize > (baddr - curaddr))
875                         sgsize = (baddr - curaddr);
876         }
877
878         if (dmat->ranges) {
879                 struct arm32_dma_range *dr;
880
881                 dr = _bus_dma_inrange(dmat->ranges, dmat->_nranges,
882                     curaddr);
883                 if (dr == NULL) {
884                         _bus_dmamap_unload(dmat, map);
885                         return (0);
886                 }
887                 /*
888                  * In a valid DMA range.  Translate the physical
889                  * memory address to an address in the DMA window.
890                  */
891                 curaddr = (curaddr - dr->dr_sysbase) + dr->dr_busbase;
892         }
893
894         /*
895          * Insert chunk into a segment, coalescing with
896          * previous segment if possible.
897          */
898         seg = *segp;
899         if (seg == -1) {
900                 seg = 0;
901                 segs[seg].ds_addr = curaddr;
902                 segs[seg].ds_len = sgsize;
903         } else {
904                 if (curaddr == segs[seg].ds_addr + segs[seg].ds_len &&
905                     (segs[seg].ds_len + sgsize) <= dmat->maxsegsz &&
906                     (dmat->boundary == 0 ||
907                      (segs[seg].ds_addr & bmask) == (curaddr & bmask)))
908                         segs[seg].ds_len += sgsize;
909                 else {
910                         if (++seg >= dmat->nsegments)
911                                 return (0);
912                         segs[seg].ds_addr = curaddr;
913                         segs[seg].ds_len = sgsize;
914                 }
915         }
916         *segp = seg;
917         return (sgsize);
918 }
919
920 /*
921  * Utility function to load a physical buffer.  segp contains
922  * the starting segment on entrace, and the ending segment on exit.
923  */
924 int
925 _bus_dmamap_load_phys(bus_dma_tag_t dmat,
926                       bus_dmamap_t map,
927                       vm_paddr_t buf, bus_size_t buflen,
928                       int flags,
929                       bus_dma_segment_t *segs,
930                       int *segp)
931 {
932         bus_addr_t curaddr;
933         bus_size_t sgsize;
934         int error;
935
936         if (segs == NULL)
937                 segs = dmat->segments;
938
939         if (((map->flags & DMAMAP_COHERENT) == 0) ||
940             (dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
941                 _bus_dmamap_count_phys(dmat, map, buf, buflen, flags);
942                 if (map->pagesneeded != 0) {
943                         error = _bus_dmamap_reserve_pages(dmat, map, flags);
944                         if (error)
945                                 return (error);
946                 }
947         }
948
949         while (buflen > 0) {
950                 curaddr = buf;
951                 sgsize = MIN(buflen, dmat->maxsegsz);
952                 if ((((map->flags & DMAMAP_COHERENT) == 0) ||
953                     ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0)) &&
954                     map->pagesneeded != 0 && run_filter(dmat, curaddr,
955                     sgsize, map->flags & DMAMAP_COHERENT)) {
956                         sgsize = MIN(sgsize, PAGE_SIZE);
957                         curaddr = add_bounce_page(dmat, map, 0, curaddr,
958                                                   sgsize);
959                 }
960                 sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
961                     segp);
962                 if (sgsize == 0)
963                         break;
964                 buf += sgsize;
965                 buflen -= sgsize;
966         }
967
968         /*
969          * Did we fit?
970          */
971         if (buflen != 0) {
972                 _bus_dmamap_unload(dmat, map);
973                 return (EFBIG); /* XXX better return value here? */
974         }
975         return (0);
976 }
977
978 int
979 _bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map,
980     struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
981     bus_dma_segment_t *segs, int *segp)
982 {
983
984         return (bus_dmamap_load_ma_triv(dmat, map, ma, tlen, ma_offs, flags,
985             segs, segp));
986 }
987
988 /*
989  * Utility function to load a linear buffer.  segp contains
990  * the starting segment on entrace, and the ending segment on exit.
991  */
992 int
993 _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
994                         bus_dmamap_t map,
995                         void *buf, bus_size_t buflen,
996                         pmap_t pmap,
997                         int flags,
998                         bus_dma_segment_t *segs,
999                         int *segp)
1000 {
1001         bus_size_t sgsize;
1002         bus_addr_t curaddr;
1003         vm_offset_t vaddr;
1004         struct sync_list *sl;
1005         int error;
1006
1007         if (segs == NULL)
1008                 segs = dmat->segments;
1009
1010         map->pmap = pmap;
1011
1012         if (!(map->flags & DMAMAP_COHERENT) ||
1013             (dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
1014                 _bus_dmamap_count_pages(dmat, map, buf, buflen, flags);
1015                 if (map->pagesneeded != 0) {
1016                         error = _bus_dmamap_reserve_pages(dmat, map, flags);
1017                         if (error)
1018                                 return (error);
1019                 }
1020         }
1021
1022         sl = NULL;
1023         vaddr = (vm_offset_t)buf;
1024
1025         while (buflen > 0) {
1026                 /*
1027                  * Get the physical address for this segment.
1028                  */
1029                 if (__predict_true(map->pmap == kernel_pmap))
1030                         curaddr = pmap_kextract(vaddr);
1031                 else
1032                         curaddr = pmap_extract(map->pmap, vaddr);
1033
1034                 /*
1035                  * Compute the segment size, and adjust counts.
1036                  */
1037                 sgsize = PAGE_SIZE - ((u_long)curaddr & PAGE_MASK);
1038                 if (sgsize > dmat->maxsegsz)
1039                         sgsize = dmat->maxsegsz;
1040                 if (buflen < sgsize)
1041                         sgsize = buflen;
1042
1043                 if ((((map->flags & DMAMAP_COHERENT) == 0) ||
1044                     ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0)) &&
1045                     map->pagesneeded != 0 && run_filter(dmat, curaddr,
1046                     sgsize, map->flags & DMAMAP_COHERENT)) {
1047                         curaddr = add_bounce_page(dmat, map, vaddr, curaddr,
1048                                                   sgsize);
1049                 } else {
1050                         sl = &map->slist[map->sync_count - 1];
1051                         if (map->sync_count == 0 ||
1052 #ifdef ARM_L2_PIPT
1053                             curaddr != sl->busaddr + sl->datacount ||
1054 #endif
1055                             vaddr != sl->vaddr + sl->datacount) {
1056                                 if (++map->sync_count > dmat->nsegments)
1057                                         goto cleanup;
1058                                 sl++;
1059                                 sl->vaddr = vaddr;
1060                                 sl->datacount = sgsize;
1061                                 sl->busaddr = curaddr;
1062                         } else
1063                                 sl->datacount += sgsize;
1064                 }
1065                 sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
1066                                             segp);
1067                 if (sgsize == 0)
1068                         break;
1069                 vaddr += sgsize;
1070                 buflen -= sgsize;
1071         }
1072
1073 cleanup:
1074         /*
1075          * Did we fit?
1076          */
1077         if (buflen != 0) {
1078                 _bus_dmamap_unload(dmat, map);
1079                 return (EFBIG); /* XXX better return value here? */
1080         }
1081         return (0);
1082 }
1083
1084
1085 void
1086 __bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
1087                     struct memdesc *mem, bus_dmamap_callback_t *callback,
1088                     void *callback_arg)
1089 {
1090
1091         map->mem = *mem;
1092         map->dmat = dmat;
1093         map->callback = callback;
1094         map->callback_arg = callback_arg;
1095 }
1096
1097 bus_dma_segment_t *
1098 _bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map,
1099                      bus_dma_segment_t *segs, int nsegs, int error)
1100 {
1101
1102         if (segs == NULL)
1103                 segs = dmat->segments;
1104         return (segs);
1105 }
1106
1107 /*
1108  * Release the mapping held by map.
1109  */
1110 void
1111 _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
1112 {
1113         struct bounce_page *bpage;
1114         struct bounce_zone *bz;
1115
1116         if ((bz = dmat->bounce_zone) != NULL) {
1117                 while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
1118                         STAILQ_REMOVE_HEAD(&map->bpages, links);
1119                         free_bounce_page(dmat, bpage);
1120                 }
1121
1122                 bz = dmat->bounce_zone;
1123                 bz->free_bpages += map->pagesreserved;
1124                 bz->reserved_bpages -= map->pagesreserved;
1125                 map->pagesreserved = 0;
1126                 map->pagesneeded = 0;
1127         }
1128         map->sync_count = 0;
1129 }
1130
1131 #ifdef notyetbounceuser
1132         /* If busdma uses user pages, then the interrupt handler could
1133          * be use the kernel vm mapping. Both bounce pages and sync list
1134          * do not cross page boundaries.
1135          * Below is a rough sequence that a person would do to fix the
1136          * user page reference in the kernel vmspace. This would be
1137          * done in the dma post routine.
1138          */
1139 void
1140 _bus_dmamap_fix_user(vm_offset_t buf, bus_size_t len,
1141                         pmap_t pmap, int op)
1142 {
1143         bus_size_t sgsize;
1144         bus_addr_t curaddr;
1145         vm_offset_t va;
1146
1147                 /* each synclist entry is contained within a single page.
1148                  *
1149                  * this would be needed if BUS_DMASYNC_POSTxxxx was implemented
1150                 */
1151         curaddr = pmap_extract(pmap, buf);
1152         va = pmap_dma_map(curaddr);
1153         switch (op) {
1154         case SYNC_USER_INV:
1155                 cpu_dcache_wb_range(va, sgsize);
1156                 break;
1157
1158         case SYNC_USER_COPYTO:
1159                 bcopy((void *)va, (void *)bounce, sgsize);
1160                 break;
1161
1162         case SYNC_USER_COPYFROM:
1163                 bcopy((void *) bounce, (void *)va, sgsize);
1164                 break;
1165
1166         default:
1167                 break;
1168         }
1169
1170         pmap_dma_unmap(va);
1171 }
1172 #endif
1173
1174 #ifdef ARM_L2_PIPT
1175 #define l2cache_wb_range(va, pa, size) cpu_l2cache_wb_range(pa, size)
1176 #define l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range(pa, size)
1177 #define l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range(pa, size)
1178 #else
1179 #define l2cache_wb_range(va, pa, size) cpu_l2cache_wb_range(va, size)
1180 #define l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range(va, size)
1181 #define l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range(va, size)
1182 #endif
1183
1184 void
1185 _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
1186 {
1187         struct bounce_page *bpage;
1188         struct sync_list *sl, *end;
1189         /*
1190          * If the buffer was from user space, it is possible that this is not
1191          * the same vm map, especially on a POST operation.  It's not clear that
1192          * dma on userland buffers can work at all right now, certainly not if a
1193          * partial cacheline flush has to be handled.  To be safe, until we're
1194          * able to test direct userland dma, panic on a map mismatch.
1195          */
1196         if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
1197                 if (!pmap_dmap_iscurrent(map->pmap))
1198                         panic("_bus_dmamap_sync: wrong user map for bounce sync.");
1199                 /* Handle data bouncing. */
1200                 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
1201                     "performing bounce", __func__, dmat, dmat->flags, op);
1202
1203                 if (op & BUS_DMASYNC_PREWRITE) {
1204                         while (bpage != NULL) {
1205                                 if (bpage->datavaddr != 0)
1206                                         bcopy((void *)bpage->datavaddr,
1207                                               (void *)bpage->vaddr,
1208                                               bpage->datacount);
1209                                 else
1210                                         physcopyout(bpage->dataaddr,
1211                                               (void *)bpage->vaddr,
1212                                               bpage->datacount);
1213                                 cpu_dcache_wb_range((vm_offset_t)bpage->vaddr,
1214                                         bpage->datacount);
1215                                 l2cache_wb_range((vm_offset_t)bpage->vaddr,
1216                                     (vm_offset_t)bpage->busaddr, 
1217                                     bpage->datacount);
1218                                 bpage = STAILQ_NEXT(bpage, links);
1219                         }
1220                         dmat->bounce_zone->total_bounced++;
1221                 }
1222
1223                 if (op & BUS_DMASYNC_POSTREAD) {
1224                         while (bpage != NULL) {
1225                                 vm_offset_t startv;
1226                                 vm_paddr_t startp;
1227                                 int len;
1228
1229                                 startv = bpage->vaddr &~ arm_dcache_align_mask;
1230                                 startp = bpage->busaddr &~ arm_dcache_align_mask;
1231                                 len = bpage->datacount;
1232                                 
1233                                 if (startv != bpage->vaddr)
1234                                         len += bpage->vaddr & arm_dcache_align_mask;
1235                                 if (len & arm_dcache_align_mask) 
1236                                         len = (len -
1237                                             (len & arm_dcache_align_mask)) +
1238                                             arm_dcache_align;
1239                                 cpu_dcache_inv_range(startv, len);
1240                                 l2cache_inv_range(startv, startp, len);
1241                                 if (bpage->datavaddr != 0)
1242                                         bcopy((void *)bpage->vaddr,
1243                                               (void *)bpage->datavaddr,
1244                                               bpage->datacount);
1245                                 else
1246                                         physcopyin((void *)bpage->vaddr,
1247                                               bpage->dataaddr,
1248                                               bpage->datacount);
1249                                 bpage = STAILQ_NEXT(bpage, links);
1250                         }
1251                         dmat->bounce_zone->total_bounced++;
1252                 }
1253         }
1254         if (map->flags & DMAMAP_COHERENT)
1255                 return;
1256
1257         if (map->sync_count != 0) {
1258                 if (!pmap_dmap_iscurrent(map->pmap))
1259                         panic("_bus_dmamap_sync: wrong user map for sync.");
1260                 /* ARM caches are not self-snooping for dma */
1261
1262                 sl = &map->slist[0];
1263                 end = &map->slist[map->sync_count];
1264                 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
1265                     "performing sync", __func__, dmat, dmat->flags, op);
1266
1267                 switch (op) {
1268                 case BUS_DMASYNC_PREWRITE:
1269                         while (sl != end) {
1270                             cpu_dcache_wb_range(sl->vaddr, sl->datacount);
1271                             l2cache_wb_range(sl->vaddr, sl->busaddr,
1272                                 sl->datacount);
1273                             sl++;
1274                         }
1275                         break;
1276
1277                 case BUS_DMASYNC_PREREAD:
1278                         while (sl != end) {
1279                                 cpu_dcache_inv_range(sl->vaddr, sl->datacount);
1280                                 l2cache_inv_range(sl->vaddr, sl->busaddr, 
1281                                     sl->datacount);
1282                                 sl++;
1283                         }
1284                         break;
1285
1286                 case BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD:
1287                         while (sl != end) {
1288                                 cpu_dcache_wbinv_range(sl->vaddr, sl->datacount);
1289                                 l2cache_wbinv_range(sl->vaddr,
1290                                     sl->busaddr, sl->datacount);
1291                                 sl++;
1292                         }
1293                         break;
1294
1295                 case BUS_DMASYNC_POSTREAD:
1296                 case BUS_DMASYNC_POSTWRITE:
1297                 case BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE:
1298                         break;
1299                 default:
1300                         panic("unsupported combination of sync operations: 0x%08x\n", op);
1301                         break;
1302                 }
1303         }
1304 }
1305
1306 static void
1307 init_bounce_pages(void *dummy __unused)
1308 {
1309
1310         total_bpages = 0;
1311         STAILQ_INIT(&bounce_zone_list);
1312         STAILQ_INIT(&bounce_map_waitinglist);
1313         STAILQ_INIT(&bounce_map_callbacklist);
1314         mtx_init(&bounce_lock, "bounce pages lock", NULL, MTX_DEF);
1315 }
1316 SYSINIT(bpages, SI_SUB_LOCK, SI_ORDER_ANY, init_bounce_pages, NULL);
1317
1318 static struct sysctl_ctx_list *
1319 busdma_sysctl_tree(struct bounce_zone *bz)
1320 {
1321         return (&bz->sysctl_tree);
1322 }
1323
1324 static struct sysctl_oid *
1325 busdma_sysctl_tree_top(struct bounce_zone *bz)
1326 {
1327         return (bz->sysctl_tree_top);
1328 }
1329
1330 static int
1331 alloc_bounce_zone(bus_dma_tag_t dmat)
1332 {
1333         struct bounce_zone *bz;
1334
1335         /* Check to see if we already have a suitable zone */
1336         STAILQ_FOREACH(bz, &bounce_zone_list, links) {
1337                 if ((dmat->alignment <= bz->alignment)
1338                  && (dmat->lowaddr >= bz->lowaddr)) {
1339                         dmat->bounce_zone = bz;
1340                         return (0);
1341                 }
1342         }
1343
1344         if ((bz = (struct bounce_zone *)malloc(sizeof(*bz), M_DEVBUF,
1345             M_NOWAIT | M_ZERO)) == NULL)
1346                 return (ENOMEM);
1347
1348         STAILQ_INIT(&bz->bounce_page_list);
1349         bz->free_bpages = 0;
1350         bz->reserved_bpages = 0;
1351         bz->active_bpages = 0;
1352         bz->lowaddr = dmat->lowaddr;
1353         bz->alignment = MAX(dmat->alignment, PAGE_SIZE);
1354         bz->map_count = 0;
1355         snprintf(bz->zoneid, 8, "zone%d", busdma_zonecount);
1356         busdma_zonecount++;
1357         snprintf(bz->lowaddrid, 18, "%#jx", (uintmax_t)bz->lowaddr);
1358         STAILQ_INSERT_TAIL(&bounce_zone_list, bz, links);
1359         dmat->bounce_zone = bz;
1360
1361         sysctl_ctx_init(&bz->sysctl_tree);
1362         bz->sysctl_tree_top = SYSCTL_ADD_NODE(&bz->sysctl_tree,
1363             SYSCTL_STATIC_CHILDREN(_hw_busdma), OID_AUTO, bz->zoneid,
1364             CTLFLAG_RD, 0, "");
1365         if (bz->sysctl_tree_top == NULL) {
1366                 sysctl_ctx_free(&bz->sysctl_tree);
1367                 return (0);     /* XXX error code? */
1368         }
1369
1370         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1371             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1372             "total_bpages", CTLFLAG_RD, &bz->total_bpages, 0,
1373             "Total bounce pages");
1374         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1375             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1376             "free_bpages", CTLFLAG_RD, &bz->free_bpages, 0,
1377             "Free bounce pages");
1378         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1379             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1380             "reserved_bpages", CTLFLAG_RD, &bz->reserved_bpages, 0,
1381             "Reserved bounce pages");
1382         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1383             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1384             "active_bpages", CTLFLAG_RD, &bz->active_bpages, 0,
1385             "Active bounce pages");
1386         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1387             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1388             "total_bounced", CTLFLAG_RD, &bz->total_bounced, 0,
1389             "Total bounce requests");
1390         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1391             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1392             "total_deferred", CTLFLAG_RD, &bz->total_deferred, 0,
1393             "Total bounce requests that were deferred");
1394         SYSCTL_ADD_STRING(busdma_sysctl_tree(bz),
1395             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1396             "lowaddr", CTLFLAG_RD, bz->lowaddrid, 0, "");
1397         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1398             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1399             "alignment", CTLFLAG_RD, &bz->alignment, 0, "");
1400
1401         return (0);
1402 }
1403
1404 static int
1405 alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages)
1406 {
1407         struct bounce_zone *bz;
1408         int count;
1409
1410         bz = dmat->bounce_zone;
1411         count = 0;
1412         while (numpages > 0) {
1413                 struct bounce_page *bpage;
1414
1415                 bpage = (struct bounce_page *)malloc(sizeof(*bpage), M_DEVBUF,
1416                                                      M_NOWAIT | M_ZERO);
1417
1418                 if (bpage == NULL)
1419                         break;
1420                 bpage->vaddr = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF,
1421                                                          M_NOWAIT, 0ul,
1422                                                          bz->lowaddr,
1423                                                          PAGE_SIZE,
1424                                                          0);
1425                 if (bpage->vaddr == 0) {
1426                         free(bpage, M_DEVBUF);
1427                         break;
1428                 }
1429                 bpage->busaddr = pmap_kextract(bpage->vaddr);
1430                 mtx_lock(&bounce_lock);
1431                 STAILQ_INSERT_TAIL(&bz->bounce_page_list, bpage, links);
1432                 total_bpages++;
1433                 bz->total_bpages++;
1434                 bz->free_bpages++;
1435                 mtx_unlock(&bounce_lock);
1436                 count++;
1437                 numpages--;
1438         }
1439         return (count);
1440 }
1441
1442 static int
1443 reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit)
1444 {
1445         struct bounce_zone *bz;
1446         int pages;
1447
1448         mtx_assert(&bounce_lock, MA_OWNED);
1449         bz = dmat->bounce_zone;
1450         pages = MIN(bz->free_bpages, map->pagesneeded - map->pagesreserved);
1451         if (commit == 0 && map->pagesneeded > (map->pagesreserved + pages))
1452                 return (map->pagesneeded - (map->pagesreserved + pages));
1453         bz->free_bpages -= pages;
1454         bz->reserved_bpages += pages;
1455         map->pagesreserved += pages;
1456         pages = map->pagesneeded - map->pagesreserved;
1457
1458         return (pages);
1459 }
1460
1461 static bus_addr_t
1462 add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr,
1463                 bus_addr_t addr, bus_size_t size)
1464 {
1465         struct bounce_zone *bz;
1466         struct bounce_page *bpage;
1467
1468         KASSERT(dmat->bounce_zone != NULL, ("no bounce zone in dma tag"));
1469         KASSERT(map != NULL,
1470             ("add_bounce_page: bad map %p", map));
1471
1472         bz = dmat->bounce_zone;
1473         if (map->pagesneeded == 0)
1474                 panic("add_bounce_page: map doesn't need any pages");
1475         map->pagesneeded--;
1476
1477         if (map->pagesreserved == 0)
1478                 panic("add_bounce_page: map doesn't need any pages");
1479         map->pagesreserved--;
1480
1481         mtx_lock(&bounce_lock);
1482         bpage = STAILQ_FIRST(&bz->bounce_page_list);
1483         if (bpage == NULL)
1484                 panic("add_bounce_page: free page list is empty");
1485
1486         STAILQ_REMOVE_HEAD(&bz->bounce_page_list, links);
1487         bz->reserved_bpages--;
1488         bz->active_bpages++;
1489         mtx_unlock(&bounce_lock);
1490
1491         if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
1492                 /* Page offset needs to be preserved. */
1493                 bpage->vaddr |= vaddr & PAGE_MASK;
1494                 bpage->busaddr |= vaddr & PAGE_MASK;
1495         }
1496         bpage->datavaddr = vaddr;
1497         bpage->dataaddr = addr;
1498         bpage->datacount = size;
1499         STAILQ_INSERT_TAIL(&(map->bpages), bpage, links);
1500         return (bpage->busaddr);
1501 }
1502
1503 static void
1504 free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
1505 {
1506         struct bus_dmamap *map;
1507         struct bounce_zone *bz;
1508
1509         bz = dmat->bounce_zone;
1510         bpage->datavaddr = 0;
1511         bpage->datacount = 0;
1512         if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
1513                 /*
1514                  * Reset the bounce page to start at offset 0.  Other uses
1515                  * of this bounce page may need to store a full page of
1516                  * data and/or assume it starts on a page boundary.
1517                  */
1518                 bpage->vaddr &= ~PAGE_MASK;
1519                 bpage->busaddr &= ~PAGE_MASK;
1520         }
1521
1522         mtx_lock(&bounce_lock);
1523         STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
1524         bz->free_bpages++;
1525         bz->active_bpages--;
1526         if ((map = STAILQ_FIRST(&bounce_map_waitinglist)) != NULL) {
1527                 if (reserve_bounce_pages(map->dmat, map, 1) == 0) {
1528                         STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links);
1529                         STAILQ_INSERT_TAIL(&bounce_map_callbacklist,
1530                                            map, links);
1531                         busdma_swi_pending = 1;
1532                         bz->total_deferred++;
1533                         swi_sched(vm_ih, 0);
1534                 }
1535         }
1536         mtx_unlock(&bounce_lock);
1537 }
1538
1539 void
1540 busdma_swi(void)
1541 {
1542         bus_dma_tag_t dmat;
1543         struct bus_dmamap *map;
1544
1545         mtx_lock(&bounce_lock);
1546         while ((map = STAILQ_FIRST(&bounce_map_callbacklist)) != NULL) {
1547                 STAILQ_REMOVE_HEAD(&bounce_map_callbacklist, links);
1548                 mtx_unlock(&bounce_lock);
1549                 dmat = map->dmat;
1550                 (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK);
1551                 bus_dmamap_load_mem(map->dmat, map, &map->mem, map->callback,
1552                                     map->callback_arg, BUS_DMA_WAITOK);
1553                 (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK);
1554                 mtx_lock(&bounce_lock);
1555         }
1556         mtx_unlock(&bounce_lock);
1557 }