]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/arm/arm/busdma_machdep-v6.c
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[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         else
429                 maxsize = 2; /* Need at most 2 bounce pages for unaligned access on cache line boundaries */
430
431         if ((flags & BUS_DMA_ALLOCNOW) != 0) {
432                 struct bounce_zone *bz;
433
434                 /* Must bounce */
435
436                 if ((error = alloc_bounce_zone(newtag)) != 0) {
437                         free(newtag, M_DEVBUF);
438                         return (error);
439                 }
440                 bz = newtag->bounce_zone;
441
442                 if (ptoa(bz->total_bpages) < maxsize) {
443                         int pages;
444
445                         pages = atop(maxsize) - bz->total_bpages;
446
447                         /* Add pages to our bounce pool */
448                         if (alloc_bounce_pages(newtag, pages) < pages)
449                                 error = ENOMEM;
450                 }
451                 /* Performed initial allocation */
452                 newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
453         } else
454                 newtag->bounce_zone = NULL;
455
456         if (error != 0) {
457                 free(newtag, M_DEVBUF);
458         } else {
459                 *dmat = newtag;
460         }
461         CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
462             __func__, newtag, (newtag != NULL ? newtag->flags : 0), error);
463         return (error);
464 }
465
466 int
467 bus_dma_tag_destroy(bus_dma_tag_t dmat)
468 {
469         bus_dma_tag_t dmat_copy;
470         int error;
471
472         error = 0;
473         dmat_copy = dmat;
474
475         if (dmat != NULL) {
476
477                 if (dmat->map_count != 0) {
478                         error = EBUSY;
479                         goto out;
480                 }
481
482                 while (dmat != NULL) {
483                         bus_dma_tag_t parent;
484
485                         parent = dmat->parent;
486                         atomic_subtract_int(&dmat->ref_count, 1);
487                         if (dmat->ref_count == 0) {
488                                 if (dmat->segments != NULL &&
489                                     dmat->segments != dmat->tagsegs)
490                                         free(dmat->segments, M_DEVBUF);
491                                 free(dmat, M_DEVBUF);
492                                 /*
493                                  * Last reference count, so
494                                  * release our reference
495                                  * count on our parent.
496                                  */
497                                 dmat = parent;
498                         } else
499                                 dmat = NULL;
500                 }
501         }
502 out:
503         CTR3(KTR_BUSDMA, "%s tag %p error %d", __func__, dmat_copy, error);
504         return (error);
505 }
506
507 static int allocate_bz_and_pages(bus_dma_tag_t dmat, bus_dmamap_t mapp)
508 {
509         struct bounce_zone *bz;
510         int maxpages;
511         int error;
512                 
513         if (dmat->bounce_zone == NULL)
514                 if ((error = alloc_bounce_zone(dmat)) != 0)
515                         return (error);
516         bz = dmat->bounce_zone;
517         /* Initialize the new map */
518         STAILQ_INIT(&(mapp->bpages));
519
520         /*
521          * Attempt to add pages to our pool on a per-instance
522          * basis up to a sane limit.
523          */
524         if (dmat->flags & BUS_DMA_COULD_BOUNCE)
525                 maxpages = MAX_BPAGES;
526         else
527                 maxpages = 2 * bz->map_count; /* Only need at most 2 pages for buffers unaligned on cache line boundaries */
528         if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0
529             || (bz->map_count > 0 && bz->total_bpages < maxpages)) {
530                 int pages;
531                 
532                 pages = MAX(atop(dmat->maxsize), 1);
533                 pages = MIN(maxpages - bz->total_bpages, pages);
534                 pages = MAX(pages, 1);
535                 if (alloc_bounce_pages(dmat, pages) < pages)
536                         return (ENOMEM);
537                 
538                 if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0)
539                         dmat->flags |= BUS_DMA_MIN_ALLOC_COMP;
540         }
541         bz->map_count++;
542         return (0);
543 }
544
545 /*
546  * Allocate a handle for mapping from kva/uva/physical
547  * address space into bus device space.
548  */
549 int
550 bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
551 {
552         int mapsize;
553         int error = 0;
554
555         mapsize = sizeof(**mapp) + (sizeof(struct sync_list) * dmat->nsegments);
556         *mapp = (bus_dmamap_t)malloc(mapsize, M_DEVBUF, M_NOWAIT | M_ZERO);
557         if (*mapp == NULL) {
558                 CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, ENOMEM);
559                 return (ENOMEM);
560         }
561         (*mapp)->sync_count = 0;
562
563         if (dmat->segments == NULL) {
564                 dmat->segments = (bus_dma_segment_t *)malloc(
565                     sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
566                     M_NOWAIT);
567                 if (dmat->segments == NULL) {
568                         CTR3(KTR_BUSDMA, "%s: tag %p error %d",
569                             __func__, dmat, ENOMEM);
570                         free(*mapp, M_DEVBUF);
571                         *mapp = NULL;
572                         return (ENOMEM);
573                 }
574         }
575         /*
576          * Bouncing might be required if the driver asks for an active
577          * exclusion region, a data alignment that is stricter than 1, and/or
578          * an active address boundary.
579          */
580         error = allocate_bz_and_pages(dmat, *mapp);
581         if (error != 0) {
582                 free(*mapp, M_DEVBUF);
583                 *mapp = NULL;
584                 return (error);
585         }
586         return (error);
587 }
588
589 /*
590  * Destroy a handle for mapping from kva/uva/physical
591  * address space into bus device space.
592  */
593 int
594 bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
595 {
596         if (STAILQ_FIRST(&map->bpages) != NULL || map->sync_count != 0) {
597                 CTR3(KTR_BUSDMA, "%s: tag %p error %d",
598                     __func__, dmat, EBUSY);
599                 return (EBUSY);
600         }
601         if (dmat->bounce_zone)
602                 dmat->bounce_zone->map_count--;
603         free(map, M_DEVBUF);
604         dmat->map_count--;
605         CTR2(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat);
606         return (0);
607 }
608
609
610 /*
611  * Allocate a piece of memory that can be efficiently mapped into
612  * bus device space based on the constraints lited in the dma tag.
613  * A dmamap to for use with dmamap_load is also allocated.
614  */
615 int
616 bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
617                  bus_dmamap_t *mapp)
618 {
619         busdma_bufalloc_t ba;
620         struct busdma_bufzone *bufzone;
621         vm_memattr_t memattr;
622         int mflags;
623         int mapsize;
624         int error;
625
626         if (flags & BUS_DMA_NOWAIT)
627                 mflags = M_NOWAIT;
628         else
629                 mflags = M_WAITOK;
630
631         /* ARM non-snooping caches need a map for the VA cache sync structure */
632
633         mapsize = sizeof(**mapp) + (sizeof(struct sync_list) * dmat->nsegments);
634         *mapp = (bus_dmamap_t)malloc(mapsize, M_DEVBUF, M_NOWAIT | M_ZERO);
635         if (*mapp == NULL) {
636                 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
637                     __func__, dmat, dmat->flags, ENOMEM);
638                 return (ENOMEM);
639         }
640
641         (*mapp)->sync_count = 0;
642         /* We may need bounce pages, even for allocated memory */
643         error = allocate_bz_and_pages(dmat, *mapp);
644         if (error != 0) {
645                 free(*mapp, M_DEVBUF);
646                 *mapp = NULL;
647                 return (error);
648         }
649
650         if (dmat->segments == NULL) {
651                 dmat->segments = (bus_dma_segment_t *)malloc(
652                     sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
653                     mflags);
654                 if (dmat->segments == NULL) {
655                         CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
656                             __func__, dmat, dmat->flags, ENOMEM);
657                         free(*mapp, M_DEVBUF);
658                         *mapp = NULL;
659                         return (ENOMEM);
660                 }
661         }
662
663         if (flags & BUS_DMA_ZERO)
664                 mflags |= M_ZERO;
665         if (flags & BUS_DMA_COHERENT) {
666                 memattr = VM_MEMATTR_UNCACHEABLE;
667                 ba = coherent_allocator;
668                 (*mapp)->flags |= DMAMAP_COHERENT;
669         } else {
670                 memattr = VM_MEMATTR_DEFAULT;
671                 ba = standard_allocator;
672                 (*mapp)->flags = 0;
673         }
674
675         /*
676          * Try to find a bufzone in the allocator that holds a cache of buffers
677          * of the right size for this request.  If the buffer is too big to be
678          * held in the allocator cache, this returns NULL.
679          */
680         bufzone = busdma_bufalloc_findzone(ba, dmat->maxsize);
681
682         /*
683          * Allocate the buffer from the uma(9) allocator if...
684          *  - It's small enough to be in the allocator (bufzone not NULL).
685          *  - The alignment constraint isn't larger than the allocation size
686          *    (the allocator aligns buffers to their size boundaries).
687          *  - There's no need to handle lowaddr/highaddr exclusion zones.
688          * else allocate non-contiguous pages if...
689          *  - The page count that could get allocated doesn't exceed nsegments.
690          *  - The alignment constraint isn't larger than a page boundary.
691          *  - There are no boundary-crossing constraints.
692          * else allocate a block of contiguous pages because one or more of the
693          * constraints is something that only the contig allocator can fulfill.
694          */
695         if (bufzone != NULL && dmat->alignment <= bufzone->size &&
696             !_bus_dma_can_bounce(dmat->lowaddr, dmat->highaddr)) {
697                 *vaddr = uma_zalloc(bufzone->umazone, mflags);
698         } else if (dmat->nsegments >= btoc(dmat->maxsize) &&
699             dmat->alignment <= PAGE_SIZE && dmat->boundary == 0) {
700                 *vaddr = (void *)kmem_alloc_attr(kernel_arena, dmat->maxsize,
701                     mflags, 0, dmat->lowaddr, memattr);
702         } else {
703                 *vaddr = (void *)kmem_alloc_contig(kernel_arena, dmat->maxsize,
704                     mflags, 0, dmat->lowaddr, dmat->alignment, dmat->boundary,
705                     memattr);
706         }
707
708
709         if (*vaddr == NULL) {
710                 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
711                     __func__, dmat, dmat->flags, ENOMEM);
712                 free(*mapp, M_DEVBUF);
713                 *mapp = NULL;
714                 return (ENOMEM);
715         } else if ((uintptr_t)*vaddr & (dmat->alignment - 1)) {
716                 printf("bus_dmamem_alloc failed to align memory properly.\n");
717         }
718         dmat->map_count++;
719
720         CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
721             __func__, dmat, dmat->flags, 0);
722         return (0);
723 }
724
725 /*
726  * Free a piece of memory and it's allociated dmamap, that was allocated
727  * via bus_dmamem_alloc.  Make the same choice for free/contigfree.
728  */
729 void
730 bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
731 {
732         struct busdma_bufzone *bufzone;
733         busdma_bufalloc_t ba;
734
735         if (map->flags & DMAMAP_COHERENT)
736                 ba = coherent_allocator;
737         else
738                 ba = standard_allocator;
739
740         /* Be careful not to access map from here on. */
741
742         bufzone = busdma_bufalloc_findzone(ba, dmat->maxsize);
743
744         if (bufzone != NULL && dmat->alignment <= bufzone->size &&
745             !_bus_dma_can_bounce(dmat->lowaddr, dmat->highaddr))
746                 uma_zfree(bufzone->umazone, vaddr);
747         else
748                 kmem_free(kernel_arena, (vm_offset_t)vaddr, dmat->maxsize);
749
750         dmat->map_count--;
751         free(map, M_DEVBUF);
752         CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
753 }
754
755 static void
756 _bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf,
757     bus_size_t buflen, int flags)
758 {
759         bus_addr_t curaddr;
760         bus_size_t sgsize;
761
762         if (map->pagesneeded == 0) {
763                 CTR5(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d"
764                     " map= %p, pagesneeded= %d",
765                     dmat->lowaddr, dmat->boundary, dmat->alignment,
766                     map, map->pagesneeded);
767                 /*
768                  * Count the number of bounce pages
769                  * needed in order to complete this transfer
770                  */
771                 curaddr = buf;
772                 while (buflen != 0) {
773                         sgsize = MIN(buflen, dmat->maxsegsz);
774                         if (run_filter(dmat, curaddr, sgsize, 
775                             map->flags & DMAMAP_COHERENT) != 0) {
776                                 sgsize = MIN(sgsize, PAGE_SIZE);
777                                 map->pagesneeded++;
778                         }
779                         curaddr += sgsize;
780                         buflen -= sgsize;
781                 }
782                 CTR1(KTR_BUSDMA, "pagesneeded= %d", map->pagesneeded);
783         }
784 }
785
786 static void
787 _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
788     void *buf, bus_size_t buflen, int flags)
789 {
790         vm_offset_t vaddr;
791         vm_offset_t vendaddr;
792         bus_addr_t paddr;
793
794         if (map->pagesneeded == 0) {
795                 CTR5(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d"
796                     " map= %p, pagesneeded= %d",
797                     dmat->lowaddr, dmat->boundary, dmat->alignment,
798                     map, map->pagesneeded);
799                 /*
800                  * Count the number of bounce pages
801                  * needed in order to complete this transfer
802                  */
803                 vaddr = (vm_offset_t)buf;
804                 vendaddr = (vm_offset_t)buf + buflen;
805
806                 while (vaddr < vendaddr) {
807                         if (__predict_true(map->pmap == kernel_pmap))
808                                 paddr = pmap_kextract(vaddr);
809                         else
810                                 paddr = pmap_extract(map->pmap, vaddr);
811                         if (run_filter(dmat, paddr,
812                             min(vendaddr - vaddr, 
813                             (PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK))),
814                             map->flags & DMAMAP_COHERENT) != 0) {
815                                 map->pagesneeded++;
816                         }
817                         vaddr += (PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK));
818
819                 }
820                 CTR1(KTR_BUSDMA, "pagesneeded= %d", map->pagesneeded);
821         }
822 }
823
824 static int
825 _bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags)
826 {
827
828         /* Reserve Necessary Bounce Pages */
829         mtx_lock(&bounce_lock);
830         if (flags & BUS_DMA_NOWAIT) {
831                 if (reserve_bounce_pages(dmat, map, 0) != 0) {
832                         map->pagesneeded = 0;
833                         mtx_unlock(&bounce_lock);
834                         return (ENOMEM);
835                 }
836         } else {
837                 if (reserve_bounce_pages(dmat, map, 1) != 0) {
838                         /* Queue us for resources */
839                         STAILQ_INSERT_TAIL(&bounce_map_waitinglist, map, links);
840                         mtx_unlock(&bounce_lock);
841                         return (EINPROGRESS);
842                 }
843         }
844         mtx_unlock(&bounce_lock);
845
846         return (0);
847 }
848
849 /*
850  * Add a single contiguous physical range to the segment list.
851  */
852 static int
853 _bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr,
854                    bus_size_t sgsize, bus_dma_segment_t *segs, int *segp)
855 {
856         bus_addr_t baddr, bmask;
857         int seg;
858
859         /*
860          * Make sure we don't cross any boundaries.
861          */
862         bmask = ~(dmat->boundary - 1);
863         if (dmat->boundary > 0) {
864                 baddr = (curaddr + dmat->boundary) & bmask;
865                 if (sgsize > (baddr - curaddr))
866                         sgsize = (baddr - curaddr);
867         }
868
869         if (dmat->ranges) {
870                 struct arm32_dma_range *dr;
871
872                 dr = _bus_dma_inrange(dmat->ranges, dmat->_nranges,
873                     curaddr);
874                 if (dr == NULL) {
875                         _bus_dmamap_unload(dmat, map);
876                         return (0);
877                 }
878                 /*
879                  * In a valid DMA range.  Translate the physical
880                  * memory address to an address in the DMA window.
881                  */
882                 curaddr = (curaddr - dr->dr_sysbase) + dr->dr_busbase;
883         }
884
885         /*
886          * Insert chunk into a segment, coalescing with
887          * previous segment if possible.
888          */
889         seg = *segp;
890         if (seg == -1) {
891                 seg = 0;
892                 segs[seg].ds_addr = curaddr;
893                 segs[seg].ds_len = sgsize;
894         } else {
895                 if (curaddr == segs[seg].ds_addr + segs[seg].ds_len &&
896                     (segs[seg].ds_len + sgsize) <= dmat->maxsegsz &&
897                     (dmat->boundary == 0 ||
898                      (segs[seg].ds_addr & bmask) == (curaddr & bmask)))
899                         segs[seg].ds_len += sgsize;
900                 else {
901                         if (++seg >= dmat->nsegments)
902                                 return (0);
903                         segs[seg].ds_addr = curaddr;
904                         segs[seg].ds_len = sgsize;
905                 }
906         }
907         *segp = seg;
908         return (sgsize);
909 }
910
911 /*
912  * Utility function to load a physical buffer.  segp contains
913  * the starting segment on entrace, and the ending segment on exit.
914  */
915 int
916 _bus_dmamap_load_phys(bus_dma_tag_t dmat,
917                       bus_dmamap_t map,
918                       vm_paddr_t buf, bus_size_t buflen,
919                       int flags,
920                       bus_dma_segment_t *segs,
921                       int *segp)
922 {
923         bus_addr_t curaddr;
924         bus_size_t sgsize;
925         int error;
926
927         if (segs == NULL)
928                 segs = dmat->segments;
929
930         if (((map->flags & DMAMAP_COHERENT) == 0) ||
931             (dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
932                 _bus_dmamap_count_phys(dmat, map, buf, buflen, flags);
933                 if (map->pagesneeded != 0) {
934                         error = _bus_dmamap_reserve_pages(dmat, map, flags);
935                         if (error)
936                                 return (error);
937                 }
938         }
939
940         while (buflen > 0) {
941                 curaddr = buf;
942                 sgsize = MIN(buflen, dmat->maxsegsz);
943                 if ((((map->flags & DMAMAP_COHERENT) == 0) ||
944                     ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0)) &&
945                     map->pagesneeded != 0 && run_filter(dmat, curaddr,
946                     sgsize, map->flags & DMAMAP_COHERENT)) {
947                         sgsize = MIN(sgsize, PAGE_SIZE);
948                         curaddr = add_bounce_page(dmat, map, 0, curaddr,
949                                                   sgsize);
950                 }
951                 sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
952                     segp);
953                 if (sgsize == 0)
954                         break;
955                 buf += sgsize;
956                 buflen -= sgsize;
957         }
958
959         /*
960          * Did we fit?
961          */
962         if (buflen != 0) {
963                 _bus_dmamap_unload(dmat, map);
964                 return (EFBIG); /* XXX better return value here? */
965         }
966         return (0);
967 }
968
969 /*
970  * Utility function to load a linear buffer.  segp contains
971  * the starting segment on entrace, and the ending segment on exit.
972  */
973 int
974 _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
975                         bus_dmamap_t map,
976                         void *buf, bus_size_t buflen,
977                         pmap_t pmap,
978                         int flags,
979                         bus_dma_segment_t *segs,
980                         int *segp)
981 {
982         bus_size_t sgsize;
983         bus_addr_t curaddr;
984         vm_offset_t vaddr;
985         struct sync_list *sl;
986         int error;
987
988         if (segs == NULL)
989                 segs = dmat->segments;
990
991         map->pmap = pmap;
992
993         if (!(map->flags & DMAMAP_COHERENT) ||
994             (dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
995                 _bus_dmamap_count_pages(dmat, map, buf, buflen, flags);
996                 if (map->pagesneeded != 0) {
997                         error = _bus_dmamap_reserve_pages(dmat, map, flags);
998                         if (error)
999                                 return (error);
1000                 }
1001         }
1002
1003         sl = NULL;
1004         vaddr = (vm_offset_t)buf;
1005
1006         while (buflen > 0) {
1007                 /*
1008                  * Get the physical address for this segment.
1009                  */
1010                 if (__predict_true(map->pmap == kernel_pmap))
1011                         curaddr = pmap_kextract(vaddr);
1012                 else
1013                         curaddr = pmap_extract(map->pmap, vaddr);
1014
1015                 /*
1016                  * Compute the segment size, and adjust counts.
1017                  */
1018                 sgsize = PAGE_SIZE - ((u_long)curaddr & PAGE_MASK);
1019                 if (sgsize > dmat->maxsegsz)
1020                         sgsize = dmat->maxsegsz;
1021                 if (buflen < sgsize)
1022                         sgsize = buflen;
1023
1024                 if ((((map->flags & DMAMAP_COHERENT) == 0) ||
1025                     ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0)) &&
1026                     map->pagesneeded != 0 && run_filter(dmat, curaddr,
1027                     sgsize, map->flags & DMAMAP_COHERENT)) {
1028                         curaddr = add_bounce_page(dmat, map, vaddr, curaddr,
1029                                                   sgsize);
1030                 } else {
1031                         sl = &map->slist[map->sync_count - 1];
1032                         if (map->sync_count == 0 ||
1033 #ifdef ARM_L2_PIPT
1034                             curaddr != sl->busaddr + sl->datacount ||
1035 #endif
1036                             vaddr != sl->vaddr + sl->datacount) {
1037                                 if (++map->sync_count > dmat->nsegments)
1038                                         goto cleanup;
1039                                 sl++;
1040                                 sl->vaddr = vaddr;
1041                                 sl->datacount = sgsize;
1042                                 sl->busaddr = curaddr;
1043                         } else
1044                                 sl->datacount += sgsize;
1045                 }
1046                 sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
1047                                             segp);
1048                 if (sgsize == 0)
1049                         break;
1050                 vaddr += sgsize;
1051                 buflen -= sgsize;
1052         }
1053
1054 cleanup:
1055         /*
1056          * Did we fit?
1057          */
1058         if (buflen != 0) {
1059                 _bus_dmamap_unload(dmat, map);
1060                 return (EFBIG); /* XXX better return value here? */
1061         }
1062         return (0);
1063 }
1064
1065
1066 void
1067 __bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
1068                     struct memdesc *mem, bus_dmamap_callback_t *callback,
1069                     void *callback_arg)
1070 {
1071
1072         map->mem = *mem;
1073         map->dmat = dmat;
1074         map->callback = callback;
1075         map->callback_arg = callback_arg;
1076 }
1077
1078 bus_dma_segment_t *
1079 _bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map,
1080                      bus_dma_segment_t *segs, int nsegs, int error)
1081 {
1082
1083         if (segs == NULL)
1084                 segs = dmat->segments;
1085         return (segs);
1086 }
1087
1088 /*
1089  * Release the mapping held by map.
1090  */
1091 void
1092 _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
1093 {
1094         struct bounce_page *bpage;
1095         struct bounce_zone *bz;
1096
1097         if ((bz = dmat->bounce_zone) != NULL) {
1098                 while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
1099                         STAILQ_REMOVE_HEAD(&map->bpages, links);
1100                         free_bounce_page(dmat, bpage);
1101                 }
1102
1103                 bz = dmat->bounce_zone;
1104                 bz->free_bpages += map->pagesreserved;
1105                 bz->reserved_bpages -= map->pagesreserved;
1106                 map->pagesreserved = 0;
1107                 map->pagesneeded = 0;
1108         }
1109         map->sync_count = 0;
1110 }
1111
1112 #ifdef notyetbounceuser
1113         /* If busdma uses user pages, then the interrupt handler could
1114          * be use the kernel vm mapping. Both bounce pages and sync list
1115          * do not cross page boundaries.
1116          * Below is a rough sequence that a person would do to fix the
1117          * user page reference in the kernel vmspace. This would be
1118          * done in the dma post routine.
1119          */
1120 void
1121 _bus_dmamap_fix_user(vm_offset_t buf, bus_size_t len,
1122                         pmap_t pmap, int op)
1123 {
1124         bus_size_t sgsize;
1125         bus_addr_t curaddr;
1126         vm_offset_t va;
1127
1128                 /* each synclist entry is contained within a single page.
1129                  *
1130                  * this would be needed if BUS_DMASYNC_POSTxxxx was implemented
1131                 */
1132         curaddr = pmap_extract(pmap, buf);
1133         va = pmap_dma_map(curaddr);
1134         switch (op) {
1135         case SYNC_USER_INV:
1136                 cpu_dcache_wb_range(va, sgsize);
1137                 break;
1138
1139         case SYNC_USER_COPYTO:
1140                 bcopy((void *)va, (void *)bounce, sgsize);
1141                 break;
1142
1143         case SYNC_USER_COPYFROM:
1144                 bcopy((void *) bounce, (void *)va, sgsize);
1145                 break;
1146
1147         default:
1148                 break;
1149         }
1150
1151         pmap_dma_unmap(va);
1152 }
1153 #endif
1154
1155 #ifdef ARM_L2_PIPT
1156 #define l2cache_wb_range(va, pa, size) cpu_l2cache_wb_range(pa, size)
1157 #define l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range(pa, size)
1158 #define l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range(pa, size)
1159 #else
1160 #define l2cache_wb_range(va, pa, size) cpu_l2cache_wb_range(va, size)
1161 #define l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range(va, size)
1162 #define l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range(va, size)
1163 #endif
1164
1165 void
1166 _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
1167 {
1168         struct bounce_page *bpage;
1169         struct sync_list *sl, *end;
1170         /*
1171          * If the buffer was from user space, it is possible that this is not
1172          * the same vm map, especially on a POST operation.  It's not clear that
1173          * dma on userland buffers can work at all right now, certainly not if a
1174          * partial cacheline flush has to be handled.  To be safe, until we're
1175          * able to test direct userland dma, panic on a map mismatch.
1176          */
1177         if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
1178                 if (!pmap_dmap_iscurrent(map->pmap))
1179                         panic("_bus_dmamap_sync: wrong user map for bounce sync.");
1180                 /* Handle data bouncing. */
1181                 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
1182                     "performing bounce", __func__, dmat, dmat->flags, op);
1183
1184                 if (op & BUS_DMASYNC_PREWRITE) {
1185                         while (bpage != NULL) {
1186                                 if (bpage->datavaddr != 0)
1187                                         bcopy((void *)bpage->datavaddr,
1188                                               (void *)bpage->vaddr,
1189                                               bpage->datacount);
1190                                 else
1191                                         physcopyout(bpage->dataaddr,
1192                                               (void *)bpage->vaddr,
1193                                               bpage->datacount);
1194                                 cpu_dcache_wb_range((vm_offset_t)bpage->vaddr,
1195                                         bpage->datacount);
1196                                 l2cache_wb_range((vm_offset_t)bpage->vaddr,
1197                                     (vm_offset_t)bpage->busaddr, 
1198                                     bpage->datacount);
1199                                 bpage = STAILQ_NEXT(bpage, links);
1200                         }
1201                         dmat->bounce_zone->total_bounced++;
1202                 }
1203
1204                 if (op & BUS_DMASYNC_POSTREAD) {
1205                         while (bpage != NULL) {
1206                                 vm_offset_t startv;
1207                                 vm_paddr_t startp;
1208                                 int len;
1209
1210                                 startv = bpage->vaddr &~ arm_dcache_align_mask;
1211                                 startp = bpage->busaddr &~ arm_dcache_align_mask;
1212                                 len = bpage->datacount;
1213                                 
1214                                 if (startv != bpage->vaddr)
1215                                         len += bpage->vaddr & arm_dcache_align_mask;
1216                                 if (len & arm_dcache_align_mask) 
1217                                         len = (len -
1218                                             (len & arm_dcache_align_mask)) +
1219                                             arm_dcache_align;
1220                                 cpu_dcache_inv_range(startv, len);
1221                                 l2cache_inv_range(startv, startp, len);
1222                                 if (bpage->datavaddr != 0)
1223                                         bcopy((void *)bpage->vaddr,
1224                                               (void *)bpage->datavaddr,
1225                                               bpage->datacount);
1226                                 else
1227                                         physcopyin((void *)bpage->vaddr,
1228                                               bpage->dataaddr,
1229                                               bpage->datacount);
1230                                 bpage = STAILQ_NEXT(bpage, links);
1231                         }
1232                         dmat->bounce_zone->total_bounced++;
1233                 }
1234         }
1235         if (map->flags & DMAMAP_COHERENT)
1236                 return;
1237
1238         if (map->sync_count != 0) {
1239                 if (!pmap_dmap_iscurrent(map->pmap))
1240                         panic("_bus_dmamap_sync: wrong user map for sync.");
1241                 /* ARM caches are not self-snooping for dma */
1242
1243                 sl = &map->slist[0];
1244                 end = &map->slist[map->sync_count];
1245                 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
1246                     "performing sync", __func__, dmat, dmat->flags, op);
1247
1248                 switch (op) {
1249                 case BUS_DMASYNC_PREWRITE:
1250                         while (sl != end) {
1251                             cpu_dcache_wb_range(sl->vaddr, sl->datacount);
1252                             l2cache_wb_range(sl->vaddr, sl->busaddr,
1253                                 sl->datacount);
1254                             sl++;
1255                         }
1256                         break;
1257
1258                 case BUS_DMASYNC_PREREAD:
1259                         while (sl != end) {
1260                                 cpu_dcache_inv_range(sl->vaddr, sl->datacount);
1261                                 l2cache_inv_range(sl->vaddr, sl->busaddr, 
1262                                     sl->datacount);
1263                                 sl++;
1264                         }
1265                         break;
1266
1267                 case BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD:
1268                         while (sl != end) {
1269                                 cpu_dcache_wbinv_range(sl->vaddr, sl->datacount);
1270                                 l2cache_wbinv_range(sl->vaddr,
1271                                     sl->busaddr, sl->datacount);
1272                                 sl++;
1273                         }
1274                         break;
1275
1276                 default:
1277                         break;
1278                 }
1279         }
1280 }
1281
1282 static void
1283 init_bounce_pages(void *dummy __unused)
1284 {
1285
1286         total_bpages = 0;
1287         STAILQ_INIT(&bounce_zone_list);
1288         STAILQ_INIT(&bounce_map_waitinglist);
1289         STAILQ_INIT(&bounce_map_callbacklist);
1290         mtx_init(&bounce_lock, "bounce pages lock", NULL, MTX_DEF);
1291 }
1292 SYSINIT(bpages, SI_SUB_LOCK, SI_ORDER_ANY, init_bounce_pages, NULL);
1293
1294 static struct sysctl_ctx_list *
1295 busdma_sysctl_tree(struct bounce_zone *bz)
1296 {
1297         return (&bz->sysctl_tree);
1298 }
1299
1300 static struct sysctl_oid *
1301 busdma_sysctl_tree_top(struct bounce_zone *bz)
1302 {
1303         return (bz->sysctl_tree_top);
1304 }
1305
1306 static int
1307 alloc_bounce_zone(bus_dma_tag_t dmat)
1308 {
1309         struct bounce_zone *bz;
1310
1311         /* Check to see if we already have a suitable zone */
1312         STAILQ_FOREACH(bz, &bounce_zone_list, links) {
1313                 if ((dmat->alignment <= bz->alignment)
1314                  && (dmat->lowaddr >= bz->lowaddr)) {
1315                         dmat->bounce_zone = bz;
1316                         return (0);
1317                 }
1318         }
1319
1320         if ((bz = (struct bounce_zone *)malloc(sizeof(*bz), M_DEVBUF,
1321             M_NOWAIT | M_ZERO)) == NULL)
1322                 return (ENOMEM);
1323
1324         STAILQ_INIT(&bz->bounce_page_list);
1325         bz->free_bpages = 0;
1326         bz->reserved_bpages = 0;
1327         bz->active_bpages = 0;
1328         bz->lowaddr = dmat->lowaddr;
1329         bz->alignment = MAX(dmat->alignment, PAGE_SIZE);
1330         bz->map_count = 0;
1331         snprintf(bz->zoneid, 8, "zone%d", busdma_zonecount);
1332         busdma_zonecount++;
1333         snprintf(bz->lowaddrid, 18, "%#jx", (uintmax_t)bz->lowaddr);
1334         STAILQ_INSERT_TAIL(&bounce_zone_list, bz, links);
1335         dmat->bounce_zone = bz;
1336
1337         sysctl_ctx_init(&bz->sysctl_tree);
1338         bz->sysctl_tree_top = SYSCTL_ADD_NODE(&bz->sysctl_tree,
1339             SYSCTL_STATIC_CHILDREN(_hw_busdma), OID_AUTO, bz->zoneid,
1340             CTLFLAG_RD, 0, "");
1341         if (bz->sysctl_tree_top == NULL) {
1342                 sysctl_ctx_free(&bz->sysctl_tree);
1343                 return (0);     /* XXX error code? */
1344         }
1345
1346         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1347             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1348             "total_bpages", CTLFLAG_RD, &bz->total_bpages, 0,
1349             "Total bounce pages");
1350         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1351             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1352             "free_bpages", CTLFLAG_RD, &bz->free_bpages, 0,
1353             "Free bounce pages");
1354         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1355             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1356             "reserved_bpages", CTLFLAG_RD, &bz->reserved_bpages, 0,
1357             "Reserved bounce pages");
1358         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1359             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1360             "active_bpages", CTLFLAG_RD, &bz->active_bpages, 0,
1361             "Active bounce pages");
1362         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1363             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1364             "total_bounced", CTLFLAG_RD, &bz->total_bounced, 0,
1365             "Total bounce requests");
1366         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1367             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1368             "total_deferred", CTLFLAG_RD, &bz->total_deferred, 0,
1369             "Total bounce requests that were deferred");
1370         SYSCTL_ADD_STRING(busdma_sysctl_tree(bz),
1371             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1372             "lowaddr", CTLFLAG_RD, bz->lowaddrid, 0, "");
1373         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1374             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1375             "alignment", CTLFLAG_RD, &bz->alignment, 0, "");
1376
1377         return (0);
1378 }
1379
1380 static int
1381 alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages)
1382 {
1383         struct bounce_zone *bz;
1384         int count;
1385
1386         bz = dmat->bounce_zone;
1387         count = 0;
1388         while (numpages > 0) {
1389                 struct bounce_page *bpage;
1390
1391                 bpage = (struct bounce_page *)malloc(sizeof(*bpage), M_DEVBUF,
1392                                                      M_NOWAIT | M_ZERO);
1393
1394                 if (bpage == NULL)
1395                         break;
1396                 bpage->vaddr = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF,
1397                                                          M_NOWAIT, 0ul,
1398                                                          bz->lowaddr,
1399                                                          PAGE_SIZE,
1400                                                          0);
1401                 if (bpage->vaddr == 0) {
1402                         free(bpage, M_DEVBUF);
1403                         break;
1404                 }
1405                 bpage->busaddr = pmap_kextract(bpage->vaddr);
1406                 mtx_lock(&bounce_lock);
1407                 STAILQ_INSERT_TAIL(&bz->bounce_page_list, bpage, links);
1408                 total_bpages++;
1409                 bz->total_bpages++;
1410                 bz->free_bpages++;
1411                 mtx_unlock(&bounce_lock);
1412                 count++;
1413                 numpages--;
1414         }
1415         return (count);
1416 }
1417
1418 static int
1419 reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit)
1420 {
1421         struct bounce_zone *bz;
1422         int pages;
1423
1424         mtx_assert(&bounce_lock, MA_OWNED);
1425         bz = dmat->bounce_zone;
1426         pages = MIN(bz->free_bpages, map->pagesneeded - map->pagesreserved);
1427         if (commit == 0 && map->pagesneeded > (map->pagesreserved + pages))
1428                 return (map->pagesneeded - (map->pagesreserved + pages));
1429         bz->free_bpages -= pages;
1430         bz->reserved_bpages += pages;
1431         map->pagesreserved += pages;
1432         pages = map->pagesneeded - map->pagesreserved;
1433
1434         return (pages);
1435 }
1436
1437 static bus_addr_t
1438 add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr,
1439                 bus_addr_t addr, bus_size_t size)
1440 {
1441         struct bounce_zone *bz;
1442         struct bounce_page *bpage;
1443
1444         KASSERT(dmat->bounce_zone != NULL, ("no bounce zone in dma tag"));
1445         KASSERT(map != NULL,
1446             ("add_bounce_page: bad map %p", map));
1447
1448         bz = dmat->bounce_zone;
1449         if (map->pagesneeded == 0)
1450                 panic("add_bounce_page: map doesn't need any pages");
1451         map->pagesneeded--;
1452
1453         if (map->pagesreserved == 0)
1454                 panic("add_bounce_page: map doesn't need any pages");
1455         map->pagesreserved--;
1456
1457         mtx_lock(&bounce_lock);
1458         bpage = STAILQ_FIRST(&bz->bounce_page_list);
1459         if (bpage == NULL)
1460                 panic("add_bounce_page: free page list is empty");
1461
1462         STAILQ_REMOVE_HEAD(&bz->bounce_page_list, links);
1463         bz->reserved_bpages--;
1464         bz->active_bpages++;
1465         mtx_unlock(&bounce_lock);
1466
1467         if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
1468                 /* Page offset needs to be preserved. */
1469                 bpage->vaddr |= vaddr & PAGE_MASK;
1470                 bpage->busaddr |= vaddr & PAGE_MASK;
1471         }
1472         bpage->datavaddr = vaddr;
1473         bpage->dataaddr = addr;
1474         bpage->datacount = size;
1475         STAILQ_INSERT_TAIL(&(map->bpages), bpage, links);
1476         return (bpage->busaddr);
1477 }
1478
1479 static void
1480 free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
1481 {
1482         struct bus_dmamap *map;
1483         struct bounce_zone *bz;
1484
1485         bz = dmat->bounce_zone;
1486         bpage->datavaddr = 0;
1487         bpage->datacount = 0;
1488         if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
1489                 /*
1490                  * Reset the bounce page to start at offset 0.  Other uses
1491                  * of this bounce page may need to store a full page of
1492                  * data and/or assume it starts on a page boundary.
1493                  */
1494                 bpage->vaddr &= ~PAGE_MASK;
1495                 bpage->busaddr &= ~PAGE_MASK;
1496         }
1497
1498         mtx_lock(&bounce_lock);
1499         STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
1500         bz->free_bpages++;
1501         bz->active_bpages--;
1502         if ((map = STAILQ_FIRST(&bounce_map_waitinglist)) != NULL) {
1503                 if (reserve_bounce_pages(map->dmat, map, 1) == 0) {
1504                         STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links);
1505                         STAILQ_INSERT_TAIL(&bounce_map_callbacklist,
1506                                            map, links);
1507                         busdma_swi_pending = 1;
1508                         bz->total_deferred++;
1509                         swi_sched(vm_ih, 0);
1510                 }
1511         }
1512         mtx_unlock(&bounce_lock);
1513 }
1514
1515 void
1516 busdma_swi(void)
1517 {
1518         bus_dma_tag_t dmat;
1519         struct bus_dmamap *map;
1520
1521         mtx_lock(&bounce_lock);
1522         while ((map = STAILQ_FIRST(&bounce_map_callbacklist)) != NULL) {
1523                 STAILQ_REMOVE_HEAD(&bounce_map_callbacklist, links);
1524                 mtx_unlock(&bounce_lock);
1525                 dmat = map->dmat;
1526                 (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK);
1527                 bus_dmamap_load_mem(map->dmat, map, &map->mem, map->callback,
1528                                     map->callback_arg, BUS_DMA_WAITOK);
1529                 (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK);
1530                 mtx_lock(&bounce_lock);
1531         }
1532         mtx_unlock(&bounce_lock);
1533 }