]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/powerpc/powerpc/busdma_machdep.c
MFV r362082:
[FreeBSD/FreeBSD.git] / sys / powerpc / powerpc / busdma_machdep.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 1997, 1998 Justin T. Gibbs.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions, and the following disclaimer,
12  *    without modification, immediately at the beginning of the file.
13  * 2. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 /*
30  * From amd64/busdma_machdep.c, r204214
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/bus.h>
40 #include <sys/interrupt.h>
41 #include <sys/kernel.h>
42 #include <sys/ktr.h>
43 #include <sys/lock.h>
44 #include <sys/proc.h>
45 #include <sys/memdesc.h>
46 #include <sys/mutex.h>
47 #include <sys/sysctl.h>
48 #include <sys/uio.h>
49
50 #include <vm/vm.h>
51 #include <vm/vm_extern.h>
52 #include <vm/vm_kern.h>
53 #include <vm/vm_page.h>
54 #include <vm/vm_map.h>
55
56 #include <machine/atomic.h>
57 #include <machine/bus.h>
58 #include <machine/cpufunc.h>
59 #include <machine/md_var.h>
60
61 #include "iommu_if.h"
62
63 #define MAX_BPAGES MIN(8192, physmem/40)
64
65 struct bounce_zone;
66
67 struct bus_dma_tag {
68         bus_dma_tag_t     parent;
69         bus_size_t        alignment;
70         bus_addr_t        boundary;
71         bus_addr_t        lowaddr;
72         bus_addr_t        highaddr;
73         bus_dma_filter_t *filter;
74         void             *filterarg;
75         bus_size_t        maxsize;
76         bus_size_t        maxsegsz;
77         u_int             nsegments;
78         int               flags;
79         int               ref_count;
80         int               map_count;
81         bus_dma_lock_t   *lockfunc;
82         void             *lockfuncarg;
83         struct bounce_zone *bounce_zone;
84         device_t          iommu;
85         void             *iommu_cookie;
86 };
87
88 struct bounce_page {
89         vm_offset_t     vaddr;          /* kva of bounce buffer */
90         bus_addr_t      busaddr;        /* Physical address */
91         vm_offset_t     datavaddr;      /* kva of client data */
92         vm_page_t       datapage;       /* physical page of client data */
93         vm_offset_t     dataoffs;       /* page offset of client data */
94         bus_size_t      datacount;      /* client data count */
95         STAILQ_ENTRY(bounce_page) links;
96 };
97
98 int busdma_swi_pending;
99
100 struct bounce_zone {
101         STAILQ_ENTRY(bounce_zone) links;
102         STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
103         int             total_bpages;
104         int             free_bpages;
105         int             reserved_bpages;
106         int             active_bpages;
107         int             total_bounced;
108         int             total_deferred;
109         int             map_count;
110         bus_size_t      alignment;
111         bus_addr_t      lowaddr;
112         char            zoneid[8];
113         char            lowaddrid[20];
114         struct sysctl_ctx_list sysctl_tree;
115         struct sysctl_oid *sysctl_tree_top;
116 };
117
118 static struct mtx bounce_lock;
119 static int total_bpages;
120 static int busdma_zonecount;
121 static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
122
123 static SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
124     "Busdma parameters");
125 SYSCTL_INT(_hw_busdma, OID_AUTO, total_bpages, CTLFLAG_RD, &total_bpages, 0,
126            "Total bounce pages");
127
128 struct bus_dmamap {
129         struct bp_list         bpages;
130         int                    pagesneeded;
131         int                    pagesreserved;
132         bus_dma_tag_t          dmat;
133         struct memdesc         mem;
134         bus_dma_segment_t     *segments;
135         int                    nsegs;
136         bus_dmamap_callback_t *callback;
137         void                  *callback_arg;
138         STAILQ_ENTRY(bus_dmamap) links;
139         int                    contigalloc;
140 };
141
142 static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
143 static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist;
144
145 static void init_bounce_pages(void *dummy);
146 static int alloc_bounce_zone(bus_dma_tag_t dmat);
147 static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages);
148 static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
149                                 int commit);
150 static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map,
151                                   vm_offset_t vaddr, bus_addr_t addr,
152                                   bus_size_t size);
153 static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage);
154 static __inline int run_filter(bus_dma_tag_t dmat, bus_addr_t paddr);
155
156 /*
157  * Return true if a match is made.
158  *
159  * To find a match walk the chain of bus_dma_tag_t's looking for 'paddr'.
160  *
161  * If paddr is within the bounds of the dma tag then call the filter callback
162  * to check for a match, if there is no filter callback then assume a match.
163  */
164 static __inline int
165 run_filter(bus_dma_tag_t dmat, bus_addr_t paddr)
166 {
167         int retval;
168
169         retval = 0;
170
171         do {
172                 if (dmat->filter == NULL && dmat->iommu == NULL &&
173                     paddr > dmat->lowaddr && paddr <= dmat->highaddr)
174                         retval = 1;
175                 if (dmat->filter == NULL &&
176                     (paddr & (dmat->alignment - 1)) != 0)
177                         retval = 1;
178                 if (dmat->filter != NULL &&
179                     (*dmat->filter)(dmat->filterarg, paddr) != 0)
180                         retval = 1;
181
182                 dmat = dmat->parent;            
183         } while (retval == 0 && dmat != NULL);
184         return (retval);
185 }
186
187 /*
188  * Convenience function for manipulating driver locks from busdma (during
189  * busdma_swi, for example).  Drivers that don't provide their own locks
190  * should specify &Giant to dmat->lockfuncarg.  Drivers that use their own
191  * non-mutex locking scheme don't have to use this at all.
192  */
193 void
194 busdma_lock_mutex(void *arg, bus_dma_lock_op_t op)
195 {
196         struct mtx *dmtx;
197
198         dmtx = (struct mtx *)arg;
199         switch (op) {
200         case BUS_DMA_LOCK:
201                 mtx_lock(dmtx);
202                 break;
203         case BUS_DMA_UNLOCK:
204                 mtx_unlock(dmtx);
205                 break;
206         default:
207                 panic("Unknown operation 0x%x for busdma_lock_mutex!", op);
208         }
209 }
210
211 /*
212  * dflt_lock should never get called.  It gets put into the dma tag when
213  * lockfunc == NULL, which is only valid if the maps that are associated
214  * with the tag are meant to never be defered.
215  * XXX Should have a way to identify which driver is responsible here.
216  */
217 static void
218 dflt_lock(void *arg, bus_dma_lock_op_t op)
219 {
220         panic("driver error: busdma dflt_lock called");
221 }
222
223 #define BUS_DMA_COULD_BOUNCE    BUS_DMA_BUS3
224 #define BUS_DMA_MIN_ALLOC_COMP  BUS_DMA_BUS4
225 /*
226  * Allocate a device specific dma_tag.
227  */
228 int
229 bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
230                    bus_addr_t boundary, bus_addr_t lowaddr,
231                    bus_addr_t highaddr, bus_dma_filter_t *filter,
232                    void *filterarg, bus_size_t maxsize, int nsegments,
233                    bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
234                    void *lockfuncarg, bus_dma_tag_t *dmat)
235 {
236         bus_dma_tag_t newtag;
237         int error = 0;
238
239         /* Basic sanity checking */
240         if (boundary != 0 && boundary < maxsegsz)
241                 maxsegsz = boundary;
242
243         if (maxsegsz == 0) {
244                 return (EINVAL);
245         }
246
247         /* Return a NULL tag on failure */
248         *dmat = NULL;
249
250         newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF,
251             M_ZERO | M_NOWAIT);
252         if (newtag == NULL) {
253                 CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
254                     __func__, newtag, 0, error);
255                 return (ENOMEM);
256         }
257
258         newtag->parent = parent;
259         newtag->alignment = alignment;
260         newtag->boundary = boundary;
261         newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1);
262         newtag->highaddr = trunc_page((vm_paddr_t)highaddr) + (PAGE_SIZE - 1);
263         newtag->filter = filter;
264         newtag->filterarg = filterarg;
265         newtag->maxsize = maxsize;
266         newtag->nsegments = nsegments;
267         newtag->maxsegsz = maxsegsz;
268         newtag->flags = flags;
269         newtag->ref_count = 1; /* Count ourself */
270         newtag->map_count = 0;
271         if (lockfunc != NULL) {
272                 newtag->lockfunc = lockfunc;
273                 newtag->lockfuncarg = lockfuncarg;
274         } else {
275                 newtag->lockfunc = dflt_lock;
276                 newtag->lockfuncarg = NULL;
277         }
278
279         /* Take into account any restrictions imposed by our parent tag */
280         if (parent != NULL) {
281                 newtag->lowaddr = MIN(parent->lowaddr, newtag->lowaddr);
282                 newtag->highaddr = MAX(parent->highaddr, newtag->highaddr);
283                 if (newtag->boundary == 0)
284                         newtag->boundary = parent->boundary;
285                 else if (parent->boundary != 0)
286                         newtag->boundary = MIN(parent->boundary,
287                                                newtag->boundary);
288                 if (newtag->filter == NULL) {
289                         /*
290                          * Short circuit looking at our parent directly
291                          * since we have encapsulated all of its information
292                          */
293                         newtag->filter = parent->filter;
294                         newtag->filterarg = parent->filterarg;
295                         newtag->parent = parent->parent;
296                 }
297                 if (newtag->parent != NULL)
298                         atomic_add_int(&parent->ref_count, 1);
299                 newtag->iommu = parent->iommu;
300                 newtag->iommu_cookie = parent->iommu_cookie;
301         }
302
303         if (newtag->lowaddr < ptoa((vm_paddr_t)Maxmem) && newtag->iommu == NULL)
304                 newtag->flags |= BUS_DMA_COULD_BOUNCE;
305
306         if (newtag->alignment > 1)
307                 newtag->flags |= BUS_DMA_COULD_BOUNCE;
308
309         if (((newtag->flags & BUS_DMA_COULD_BOUNCE) != 0) &&
310             (flags & BUS_DMA_ALLOCNOW) != 0) {
311                 struct bounce_zone *bz;
312
313                 /* Must bounce */
314
315                 if ((error = alloc_bounce_zone(newtag)) != 0) {
316                         free(newtag, M_DEVBUF);
317                         return (error);
318                 }
319                 bz = newtag->bounce_zone;
320
321                 if (ptoa(bz->total_bpages) < maxsize) {
322                         int pages;
323
324                         pages = atop(maxsize) - bz->total_bpages;
325
326                         /* Add pages to our bounce pool */
327                         if (alloc_bounce_pages(newtag, pages) < pages)
328                                 error = ENOMEM;
329                 }
330                 /* Performed initial allocation */
331                 newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
332         }
333         
334         if (error != 0) {
335                 free(newtag, M_DEVBUF);
336         } else {
337                 *dmat = newtag;
338         }
339         CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
340             __func__, newtag, (newtag != NULL ? newtag->flags : 0), error);
341         return (error);
342 }
343
344 void
345 bus_dma_template_init(bus_dma_tag_template_t *t, bus_dma_tag_t parent)
346 {
347
348         if (t == NULL)
349                 return;
350
351         t->parent = parent;
352         t->alignment = 1;
353         t->boundary = 0;
354         t->lowaddr = t->highaddr = BUS_SPACE_MAXADDR;
355         t->maxsize = t->maxsegsize = BUS_SPACE_MAXSIZE;
356         t->nsegments = BUS_SPACE_UNRESTRICTED;
357         t->lockfunc = NULL;
358         t->lockfuncarg = NULL;
359         t->flags = 0;
360 }
361
362 int
363 bus_dma_template_tag(bus_dma_tag_template_t *t, bus_dma_tag_t *dmat)
364 {
365
366         if (t == NULL || dmat == NULL)
367                 return (EINVAL);
368
369         return (bus_dma_tag_create(t->parent, t->alignment, t->boundary,
370             t->lowaddr, t->highaddr, NULL, NULL, t->maxsize,
371             t->nsegments, t->maxsegsize, t->flags, t->lockfunc, t->lockfuncarg,
372             dmat));
373 }
374
375 void
376 bus_dma_template_clone(bus_dma_tag_template_t *t, bus_dma_tag_t dmat)
377 {
378
379         if (t == NULL || dmat == NULL)
380                 return;
381
382         t->parent = dmat->parent;
383         t->alignment = dmat->alignment;
384         t->boundary = dmat->boundary;
385         t->lowaddr = dmat->lowaddr;
386         t->highaddr = dmat->highaddr;
387         t->maxsize = dmat->maxsize;
388         t->nsegments = dmat->nsegments;
389         t->maxsegsize = dmat->maxsegsz;
390         t->flags = dmat->flags;
391         t->lockfunc = dmat->lockfunc;
392         t->lockfuncarg = dmat->lockfuncarg;
393 }
394
395 int
396 bus_dma_tag_set_domain(bus_dma_tag_t dmat, int domain)
397 {
398
399         return (0);
400 }
401
402 int
403 bus_dma_tag_destroy(bus_dma_tag_t dmat)
404 {
405         bus_dma_tag_t dmat_copy __unused;
406         int error;
407
408         error = 0;
409         dmat_copy = dmat;
410
411         if (dmat != NULL) {
412
413                 if (dmat->map_count != 0) {
414                         error = EBUSY;
415                         goto out;
416                 }
417
418                 while (dmat != NULL) {
419                         bus_dma_tag_t parent;
420
421                         parent = dmat->parent;
422                         atomic_subtract_int(&dmat->ref_count, 1);
423                         if (dmat->ref_count == 0) {
424                                 free(dmat, M_DEVBUF);
425                                 /*
426                                  * Last reference count, so
427                                  * release our reference
428                                  * count on our parent.
429                                  */
430                                 dmat = parent;
431                         } else
432                                 dmat = NULL;
433                 }
434         }
435 out:
436         CTR3(KTR_BUSDMA, "%s tag %p error %d", __func__, dmat_copy, error);
437         return (error);
438 }
439
440 /*
441  * Allocate a handle for mapping from kva/uva/physical
442  * address space into bus device space.
443  */
444 int
445 bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
446 {
447         int error;
448
449         error = 0;
450
451         *mapp = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF,
452                                      M_NOWAIT | M_ZERO);
453         if (*mapp == NULL) {
454                 CTR3(KTR_BUSDMA, "%s: tag %p error %d",
455                     __func__, dmat, ENOMEM);
456                 return (ENOMEM);
457         }
458
459
460         /*
461          * Bouncing might be required if the driver asks for an active
462          * exclusion region, a data alignment that is stricter than 1, and/or
463          * an active address boundary.
464          */
465         if (dmat->flags & BUS_DMA_COULD_BOUNCE) {
466
467                 /* Must bounce */
468                 struct bounce_zone *bz;
469                 int maxpages;
470
471                 if (dmat->bounce_zone == NULL) {
472                         if ((error = alloc_bounce_zone(dmat)) != 0)
473                                 return (error);
474                 }
475                 bz = dmat->bounce_zone;
476
477                 /* Initialize the new map */
478                 STAILQ_INIT(&((*mapp)->bpages));
479
480                 /*
481                  * Attempt to add pages to our pool on a per-instance
482                  * basis up to a sane limit.
483                  */
484                 if (dmat->alignment > 1)
485                         maxpages = MAX_BPAGES;
486                 else
487                         maxpages = MIN(MAX_BPAGES, Maxmem -atop(dmat->lowaddr));
488                 if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0
489                  || (bz->map_count > 0 && bz->total_bpages < maxpages)) {
490                         int pages;
491
492                         pages = MAX(atop(dmat->maxsize), 1);
493                         pages = MIN(maxpages - bz->total_bpages, pages);
494                         pages = MAX(pages, 1);
495                         if (alloc_bounce_pages(dmat, pages) < pages)
496                                 error = ENOMEM;
497
498                         if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0) {
499                                 if (error == 0)
500                                         dmat->flags |= BUS_DMA_MIN_ALLOC_COMP;
501                         } else {
502                                 error = 0;
503                         }
504                 }
505                 bz->map_count++;
506         }
507
508         (*mapp)->nsegs = 0;
509         (*mapp)->segments = (bus_dma_segment_t *)malloc(
510             sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
511             M_NOWAIT);
512         if ((*mapp)->segments == NULL) {
513                 CTR3(KTR_BUSDMA, "%s: tag %p error %d",
514                     __func__, dmat, ENOMEM);
515                 return (ENOMEM);
516         }
517
518         if (error == 0)
519                 dmat->map_count++;
520         CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
521             __func__, dmat, dmat->flags, error);
522         return (error);
523 }
524
525 /*
526  * Destroy a handle for mapping from kva/uva/physical
527  * address space into bus device space.
528  */
529 int
530 bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
531 {
532         if (dmat->flags & BUS_DMA_COULD_BOUNCE) {
533                 if (STAILQ_FIRST(&map->bpages) != NULL) {
534                         CTR3(KTR_BUSDMA, "%s: tag %p error %d",
535                             __func__, dmat, EBUSY);
536                         return (EBUSY);
537                 }
538                 if (dmat->bounce_zone)
539                         dmat->bounce_zone->map_count--;
540         }
541         free(map->segments, M_DEVBUF);
542         free(map, M_DEVBUF);
543         dmat->map_count--;
544         CTR2(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat);
545         return (0);
546 }
547
548
549 /*
550  * Allocate a piece of memory that can be efficiently mapped into
551  * bus device space based on the constraints lited in the dma tag.
552  * A dmamap to for use with dmamap_load is also allocated.
553  */
554 int
555 bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
556                  bus_dmamap_t *mapp)
557 {
558         vm_memattr_t attr;
559         int mflags;
560
561         if (flags & BUS_DMA_NOWAIT)
562                 mflags = M_NOWAIT;
563         else
564                 mflags = M_WAITOK;
565
566         bus_dmamap_create(dmat, flags, mapp);
567
568         if (flags & BUS_DMA_ZERO)
569                 mflags |= M_ZERO;
570         if (flags & BUS_DMA_NOCACHE)
571                 attr = VM_MEMATTR_UNCACHEABLE;
572         else
573                 attr = VM_MEMATTR_DEFAULT;
574
575         /* 
576          * XXX:
577          * (dmat->alignment <= dmat->maxsize) is just a quick hack; the exact
578          * alignment guarantees of malloc need to be nailed down, and the
579          * code below should be rewritten to take that into account.
580          *
581          * In the meantime, we'll warn the user if malloc gets it wrong.
582          */
583         if ((dmat->maxsize <= PAGE_SIZE) &&
584            (dmat->alignment <= dmat->maxsize) &&
585             dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem) &&
586             attr == VM_MEMATTR_DEFAULT) {
587                 *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);
588         } else {
589                 /*
590                  * XXX Use Contigmalloc until it is merged into this facility
591                  *     and handles multi-seg allocations.  Nobody is doing
592                  *     multi-seg allocations yet though.
593                  * XXX Certain AGP hardware does.
594                  */
595                 *vaddr = (void *)kmem_alloc_contig(dmat->maxsize, mflags, 0ul,
596                     dmat->lowaddr, dmat->alignment ? dmat->alignment : 1ul,
597                     dmat->boundary, attr);
598                 (*mapp)->contigalloc = 1;
599         }
600         if (*vaddr == NULL) {
601                 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
602                     __func__, dmat, dmat->flags, ENOMEM);
603                 return (ENOMEM);
604         } else if (vtophys(*vaddr) & (dmat->alignment - 1)) {
605                 printf("bus_dmamem_alloc failed to align memory properly.\n");
606         }
607         CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
608             __func__, dmat, dmat->flags, 0);
609         return (0);
610 }
611
612 /*
613  * Free a piece of memory and it's allociated dmamap, that was allocated
614  * via bus_dmamem_alloc.  Make the same choice for free/contigfree.
615  */
616 void
617 bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
618 {
619
620         if (!map->contigalloc)
621                 free(vaddr, M_DEVBUF);
622         else
623                 kmem_free((vm_offset_t)vaddr, dmat->maxsize);
624         bus_dmamap_destroy(dmat, map);
625         CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
626 }
627
628 static void
629 _bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf,
630     bus_size_t buflen, int flags)
631 {
632         bus_addr_t curaddr;
633         bus_size_t sgsize;
634
635         if (map->pagesneeded == 0) {
636                 CTR4(KTR_BUSDMA, "lowaddr= %d Maxmem= %d, boundary= %d, "
637                     "alignment= %d", dmat->lowaddr, ptoa((vm_paddr_t)Maxmem),
638                     dmat->boundary, dmat->alignment);
639                 CTR2(KTR_BUSDMA, "map= %p, pagesneeded= %d", map, map->pagesneeded);
640                 /*
641                  * Count the number of bounce pages
642                  * needed in order to complete this transfer
643                  */
644                 curaddr = buf;
645                 while (buflen != 0) {
646                         sgsize = MIN(buflen, dmat->maxsegsz);
647                         if (run_filter(dmat, curaddr) != 0) {
648                                 sgsize = MIN(sgsize,
649                                     PAGE_SIZE - (curaddr & PAGE_MASK));
650                                 map->pagesneeded++;
651                         }
652                         curaddr += sgsize;
653                         buflen -= sgsize;
654                 }
655                 CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded);
656         }
657 }
658
659 static void
660 _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap,
661     void *buf, bus_size_t buflen, int flags)
662 {
663         vm_offset_t vaddr;
664         vm_offset_t vendaddr;
665         bus_addr_t paddr;
666
667         if (map->pagesneeded == 0) {
668                 CTR4(KTR_BUSDMA, "lowaddr= %d Maxmem= %d, boundary= %d, "
669                     "alignment= %d", dmat->lowaddr, ptoa((vm_paddr_t)Maxmem),
670                     dmat->boundary, dmat->alignment);
671                 CTR2(KTR_BUSDMA, "map= %p, pagesneeded= %d", map, map->pagesneeded);
672                 /*
673                  * Count the number of bounce pages
674                  * needed in order to complete this transfer
675                  */
676                 vaddr = (vm_offset_t)buf;
677                 vendaddr = (vm_offset_t)buf + buflen;
678
679                 while (vaddr < vendaddr) {
680                         bus_size_t sg_len;
681
682                         sg_len = PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK);
683                         if (pmap == kernel_pmap)
684                                 paddr = pmap_kextract(vaddr);
685                         else
686                                 paddr = pmap_extract(pmap, vaddr);
687                         if (run_filter(dmat, paddr) != 0) {
688                                 sg_len = roundup2(sg_len, dmat->alignment);
689                                 map->pagesneeded++;
690                         }
691                         vaddr += sg_len;
692                 }
693                 CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded);
694         }
695 }
696
697 static int
698 _bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags)
699 {
700
701         /* Reserve Necessary Bounce Pages */
702         mtx_lock(&bounce_lock);
703         if (flags & BUS_DMA_NOWAIT) {
704                 if (reserve_bounce_pages(dmat, map, 0) != 0) {
705                         mtx_unlock(&bounce_lock);
706                         return (ENOMEM);
707                 }
708         } else {
709                 if (reserve_bounce_pages(dmat, map, 1) != 0) {
710                         /* Queue us for resources */
711                         STAILQ_INSERT_TAIL(&bounce_map_waitinglist,
712                             map, links);
713                         mtx_unlock(&bounce_lock);
714                         return (EINPROGRESS);
715                 }
716         }
717         mtx_unlock(&bounce_lock);
718
719         return (0);
720 }
721
722 /*
723  * Add a single contiguous physical range to the segment list.
724  */
725 static int
726 _bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr,
727                    bus_size_t sgsize, bus_dma_segment_t *segs, int *segp)
728 {
729         bus_addr_t baddr, bmask;
730         int seg;
731
732         /*
733          * Make sure we don't cross any boundaries.
734          */
735         bmask = ~(dmat->boundary - 1);
736         if (dmat->boundary > 0) {
737                 baddr = (curaddr + dmat->boundary) & bmask;
738                 if (sgsize > (baddr - curaddr))
739                         sgsize = (baddr - curaddr);
740         }
741
742         /*
743          * Insert chunk into a segment, coalescing with
744          * previous segment if possible.
745          */
746         seg = *segp;
747         if (seg == -1) {
748                 seg = 0;
749                 segs[seg].ds_addr = curaddr;
750                 segs[seg].ds_len = sgsize;
751         } else {
752                 if (curaddr == segs[seg].ds_addr + segs[seg].ds_len &&
753                     (segs[seg].ds_len + sgsize) <= dmat->maxsegsz &&
754                     (dmat->boundary == 0 ||
755                      (segs[seg].ds_addr & bmask) == (curaddr & bmask)))
756                         segs[seg].ds_len += sgsize;
757                 else {
758                         if (++seg >= dmat->nsegments)
759                                 return (0);
760                         segs[seg].ds_addr = curaddr;
761                         segs[seg].ds_len = sgsize;
762                 }
763         }
764         *segp = seg;
765         return (sgsize);
766 }
767
768 /*
769  * Utility function to load a physical buffer.  segp contains
770  * the starting segment on entrace, and the ending segment on exit.
771  */
772 int
773 _bus_dmamap_load_phys(bus_dma_tag_t dmat,
774                       bus_dmamap_t map,
775                       vm_paddr_t buf, bus_size_t buflen,
776                       int flags,
777                       bus_dma_segment_t *segs,
778                       int *segp)
779 {
780         bus_addr_t curaddr;
781         bus_size_t sgsize;
782         int error;
783
784         if (segs == NULL)
785                 segs = map->segments;
786
787         if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
788                 _bus_dmamap_count_phys(dmat, map, buf, buflen, flags);
789                 if (map->pagesneeded != 0) {
790                         error = _bus_dmamap_reserve_pages(dmat, map, flags);
791                         if (error)
792                                 return (error);
793                 }
794         }
795
796         while (buflen > 0) {
797                 curaddr = buf;
798                 sgsize = MIN(buflen, dmat->maxsegsz);
799                 if (map->pagesneeded != 0 && run_filter(dmat, curaddr)) {
800                         sgsize = MIN(sgsize, PAGE_SIZE - (curaddr & PAGE_MASK));
801                         curaddr = add_bounce_page(dmat, map, 0, curaddr,
802                             sgsize);
803                 }
804                 sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
805                     segp);
806                 if (sgsize == 0)
807                         break;
808                 buf += sgsize;
809                 buflen -= sgsize;
810         }
811
812         /*
813          * Did we fit?
814          */
815         return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */
816 }
817
818 int
819 _bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map,
820     struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
821     bus_dma_segment_t *segs, int *segp)
822 {
823
824         return (bus_dmamap_load_ma_triv(dmat, map, ma, tlen, ma_offs, flags,
825             segs, segp));
826 }
827
828 /*
829  * Utility function to load a linear buffer.  segp contains
830  * the starting segment on entrance, and the ending segment on exit.
831  */
832 int
833 _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
834                         bus_dmamap_t map,
835                         void *buf, bus_size_t buflen,
836                         pmap_t pmap,
837                         int flags,
838                         bus_dma_segment_t *segs,
839                         int *segp)
840 {
841         bus_size_t sgsize;
842         bus_addr_t curaddr;
843         vm_offset_t kvaddr, vaddr;
844         int error;
845
846         if (segs == NULL)
847                 segs = map->segments;
848
849         if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
850                 _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags);
851                 if (map->pagesneeded != 0) {
852                         error = _bus_dmamap_reserve_pages(dmat, map, flags);
853                         if (error)
854                                 return (error);
855                 }
856         }
857
858         vaddr = (vm_offset_t)buf;
859
860         while (buflen > 0) {
861                 bus_size_t max_sgsize;
862
863                 /*
864                  * Get the physical address for this segment.
865                  */
866                 if (pmap == kernel_pmap) {
867                         curaddr = pmap_kextract(vaddr);
868                         kvaddr = vaddr;
869                 } else {
870                         curaddr = pmap_extract(pmap, vaddr);
871                         kvaddr = 0;
872                 }
873
874                 /*
875                  * Compute the segment size, and adjust counts.
876                  */
877                 max_sgsize = MIN(buflen, dmat->maxsegsz);
878                 sgsize = PAGE_SIZE - (curaddr & PAGE_MASK);
879                 if (map->pagesneeded != 0 && run_filter(dmat, curaddr)) {
880                         sgsize = roundup2(sgsize, dmat->alignment);
881                         sgsize = MIN(sgsize, max_sgsize);
882                         curaddr = add_bounce_page(dmat, map, kvaddr, curaddr,
883                             sgsize);
884                 } else {
885                         sgsize = MIN(sgsize, max_sgsize);
886                 }
887
888                 sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
889                     segp);
890                 if (sgsize == 0)
891                         break;
892                 vaddr += sgsize;
893                 buflen -= sgsize;
894         }
895
896         /*
897          * Did we fit?
898          */
899         return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */
900 }
901
902 void
903 _bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
904                     struct memdesc *mem, bus_dmamap_callback_t *callback,
905                     void *callback_arg)
906 {
907
908         if (dmat->flags & BUS_DMA_COULD_BOUNCE) {
909                 map->dmat = dmat;
910                 map->mem = *mem;
911                 map->callback = callback;
912                 map->callback_arg = callback_arg;
913         }
914 }
915
916 bus_dma_segment_t *
917 _bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map,
918                      bus_dma_segment_t *segs, int nsegs, int error)
919 {
920
921         map->nsegs = nsegs;
922         if (segs != NULL)
923                 memcpy(map->segments, segs, map->nsegs*sizeof(segs[0]));
924         if (dmat->iommu != NULL)
925                 IOMMU_MAP(dmat->iommu, map->segments, &map->nsegs,
926                     dmat->lowaddr, dmat->highaddr, dmat->alignment,
927                     dmat->boundary, dmat->iommu_cookie);
928
929         if (segs != NULL)
930                 memcpy(segs, map->segments, map->nsegs*sizeof(segs[0]));
931         else
932                 segs = map->segments;
933
934         return (segs);
935 }
936
937 /*
938  * Release the mapping held by map.
939  */
940 void
941 bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
942 {
943         struct bounce_page *bpage;
944
945         if (dmat->iommu) {
946                 IOMMU_UNMAP(dmat->iommu, map->segments, map->nsegs, dmat->iommu_cookie);
947                 map->nsegs = 0;
948         }
949
950         while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
951                 STAILQ_REMOVE_HEAD(&map->bpages, links);
952                 free_bounce_page(dmat, bpage);
953         }
954 }
955
956 void
957 bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
958 {
959         struct bounce_page *bpage;
960         vm_offset_t datavaddr, tempvaddr;
961
962         if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
963
964                 /*
965                  * Handle data bouncing.  We might also
966                  * want to add support for invalidating
967                  * the caches on broken hardware
968                  */
969                 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
970                     "performing bounce", __func__, dmat, dmat->flags, op);
971
972                 if (op & BUS_DMASYNC_PREWRITE) {
973                         while (bpage != NULL) {
974                                 tempvaddr = 0;
975                                 datavaddr = bpage->datavaddr;
976                                 if (datavaddr == 0) {
977                                         tempvaddr = pmap_quick_enter_page(
978                                             bpage->datapage);
979                                         datavaddr = tempvaddr |
980                                             bpage->dataoffs;
981                                 }
982
983                                 bcopy((void *)datavaddr,
984                                     (void *)bpage->vaddr, bpage->datacount);
985
986                                 if (tempvaddr != 0)
987                                         pmap_quick_remove_page(tempvaddr);
988                                 bpage = STAILQ_NEXT(bpage, links);
989                         }
990                         dmat->bounce_zone->total_bounced++;
991                 }
992
993                 if (op & BUS_DMASYNC_POSTREAD) {
994                         while (bpage != NULL) {
995                                 tempvaddr = 0;
996                                 datavaddr = bpage->datavaddr;
997                                 if (datavaddr == 0) {
998                                         tempvaddr = pmap_quick_enter_page(
999                                             bpage->datapage);
1000                                         datavaddr = tempvaddr |
1001                                             bpage->dataoffs;
1002                                 }
1003
1004                                 bcopy((void *)bpage->vaddr,
1005                                     (void *)datavaddr, bpage->datacount);
1006
1007                                 if (tempvaddr != 0)
1008                                         pmap_quick_remove_page(tempvaddr);
1009                                 bpage = STAILQ_NEXT(bpage, links);
1010                         }
1011                         dmat->bounce_zone->total_bounced++;
1012                 }
1013         }
1014
1015         powerpc_sync();
1016 }
1017
1018 static void
1019 init_bounce_pages(void *dummy __unused)
1020 {
1021
1022         total_bpages = 0;
1023         STAILQ_INIT(&bounce_zone_list);
1024         STAILQ_INIT(&bounce_map_waitinglist);
1025         STAILQ_INIT(&bounce_map_callbacklist);
1026         mtx_init(&bounce_lock, "bounce pages lock", NULL, MTX_DEF);
1027 }
1028 SYSINIT(bpages, SI_SUB_LOCK, SI_ORDER_ANY, init_bounce_pages, NULL);
1029
1030 static struct sysctl_ctx_list *
1031 busdma_sysctl_tree(struct bounce_zone *bz)
1032 {
1033         return (&bz->sysctl_tree);
1034 }
1035
1036 static struct sysctl_oid *
1037 busdma_sysctl_tree_top(struct bounce_zone *bz)
1038 {
1039         return (bz->sysctl_tree_top);
1040 }
1041
1042 static int
1043 alloc_bounce_zone(bus_dma_tag_t dmat)
1044 {
1045         struct bounce_zone *bz;
1046
1047         /* Check to see if we already have a suitable zone */
1048         STAILQ_FOREACH(bz, &bounce_zone_list, links) {
1049                 if ((dmat->alignment <= bz->alignment)
1050                  && (dmat->lowaddr >= bz->lowaddr)) {
1051                         dmat->bounce_zone = bz;
1052                         return (0);
1053                 }
1054         }
1055
1056         if ((bz = (struct bounce_zone *)malloc(sizeof(*bz), M_DEVBUF,
1057             M_NOWAIT | M_ZERO)) == NULL)
1058                 return (ENOMEM);
1059
1060         STAILQ_INIT(&bz->bounce_page_list);
1061         bz->free_bpages = 0;
1062         bz->reserved_bpages = 0;
1063         bz->active_bpages = 0;
1064         bz->lowaddr = dmat->lowaddr;
1065         bz->alignment = MAX(dmat->alignment, PAGE_SIZE);
1066         bz->map_count = 0;
1067         snprintf(bz->zoneid, 8, "zone%d", busdma_zonecount);
1068         busdma_zonecount++;
1069         snprintf(bz->lowaddrid, 18, "%#jx", (uintmax_t)bz->lowaddr);
1070         STAILQ_INSERT_TAIL(&bounce_zone_list, bz, links);
1071         dmat->bounce_zone = bz;
1072
1073         sysctl_ctx_init(&bz->sysctl_tree);
1074         bz->sysctl_tree_top = SYSCTL_ADD_NODE(&bz->sysctl_tree,
1075             SYSCTL_STATIC_CHILDREN(_hw_busdma), OID_AUTO, bz->zoneid,
1076             CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
1077         if (bz->sysctl_tree_top == NULL) {
1078                 sysctl_ctx_free(&bz->sysctl_tree);
1079                 return (0);     /* XXX error code? */
1080         }
1081
1082         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1083             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1084             "total_bpages", CTLFLAG_RD, &bz->total_bpages, 0,
1085             "Total bounce pages");
1086         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1087             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1088             "free_bpages", CTLFLAG_RD, &bz->free_bpages, 0,
1089             "Free bounce pages");
1090         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1091             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1092             "reserved_bpages", CTLFLAG_RD, &bz->reserved_bpages, 0,
1093             "Reserved bounce pages");
1094         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1095             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1096             "active_bpages", CTLFLAG_RD, &bz->active_bpages, 0,
1097             "Active bounce pages");
1098         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1099             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1100             "total_bounced", CTLFLAG_RD, &bz->total_bounced, 0,
1101             "Total bounce requests");
1102         SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1103             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1104             "total_deferred", CTLFLAG_RD, &bz->total_deferred, 0,
1105             "Total bounce requests that were deferred");
1106         SYSCTL_ADD_STRING(busdma_sysctl_tree(bz),
1107             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1108             "lowaddr", CTLFLAG_RD, bz->lowaddrid, 0, "");
1109         SYSCTL_ADD_UAUTO(busdma_sysctl_tree(bz),
1110             SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1111             "alignment", CTLFLAG_RD, &bz->alignment, "");
1112
1113         return (0);
1114 }
1115
1116 static int
1117 alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages)
1118 {
1119         struct bounce_zone *bz;
1120         int count;
1121
1122         bz = dmat->bounce_zone;
1123         count = 0;
1124         while (numpages > 0) {
1125                 struct bounce_page *bpage;
1126
1127                 bpage = (struct bounce_page *)malloc(sizeof(*bpage), M_DEVBUF,
1128                                                      M_NOWAIT | M_ZERO);
1129
1130                 if (bpage == NULL)
1131                         break;
1132                 bpage->vaddr = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF,
1133                                                          M_NOWAIT, 0ul,
1134                                                          bz->lowaddr,
1135                                                          PAGE_SIZE,
1136                                                          0);
1137                 if (bpage->vaddr == 0) {
1138                         free(bpage, M_DEVBUF);
1139                         break;
1140                 }
1141                 bpage->busaddr = pmap_kextract(bpage->vaddr);
1142                 mtx_lock(&bounce_lock);
1143                 STAILQ_INSERT_TAIL(&bz->bounce_page_list, bpage, links);
1144                 total_bpages++;
1145                 bz->total_bpages++;
1146                 bz->free_bpages++;
1147                 mtx_unlock(&bounce_lock);
1148                 count++;
1149                 numpages--;
1150         }
1151         return (count);
1152 }
1153
1154 static int
1155 reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit)
1156 {
1157         struct bounce_zone *bz;
1158         int pages;
1159
1160         mtx_assert(&bounce_lock, MA_OWNED);
1161         bz = dmat->bounce_zone;
1162         pages = MIN(bz->free_bpages, map->pagesneeded - map->pagesreserved);
1163         if (commit == 0 && map->pagesneeded > (map->pagesreserved + pages))
1164                 return (map->pagesneeded - (map->pagesreserved + pages));
1165         bz->free_bpages -= pages;
1166         bz->reserved_bpages += pages;
1167         map->pagesreserved += pages;
1168         pages = map->pagesneeded - map->pagesreserved;
1169
1170         return (pages);
1171 }
1172
1173 static bus_addr_t
1174 add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr,
1175                 bus_addr_t addr, bus_size_t size)
1176 {
1177         struct bounce_zone *bz;
1178         struct bounce_page *bpage;
1179
1180         KASSERT(dmat->bounce_zone != NULL, ("no bounce zone in dma tag"));
1181
1182         bz = dmat->bounce_zone;
1183         if (map->pagesneeded == 0)
1184                 panic("add_bounce_page: map doesn't need any pages");
1185         map->pagesneeded--;
1186
1187         if (map->pagesreserved == 0)
1188                 panic("add_bounce_page: map doesn't need any pages");
1189         map->pagesreserved--;
1190
1191         mtx_lock(&bounce_lock);
1192         bpage = STAILQ_FIRST(&bz->bounce_page_list);
1193         if (bpage == NULL)
1194                 panic("add_bounce_page: free page list is empty");
1195
1196         STAILQ_REMOVE_HEAD(&bz->bounce_page_list, links);
1197         bz->reserved_bpages--;
1198         bz->active_bpages++;
1199         mtx_unlock(&bounce_lock);
1200
1201         if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
1202                 /* Page offset needs to be preserved. */
1203                 bpage->vaddr |= addr & PAGE_MASK;
1204                 bpage->busaddr |= addr & PAGE_MASK;
1205         }
1206         bpage->datavaddr = vaddr;
1207         bpage->datapage = PHYS_TO_VM_PAGE(addr);
1208         bpage->dataoffs = addr & PAGE_MASK;
1209         bpage->datacount = size;
1210         STAILQ_INSERT_TAIL(&(map->bpages), bpage, links);
1211         return (bpage->busaddr);
1212 }
1213
1214 static void
1215 free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
1216 {
1217         struct bus_dmamap *map;
1218         struct bounce_zone *bz;
1219
1220         bz = dmat->bounce_zone;
1221         bpage->datavaddr = 0;
1222         bpage->datacount = 0;
1223         if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
1224                 /*
1225                  * Reset the bounce page to start at offset 0.  Other uses
1226                  * of this bounce page may need to store a full page of
1227                  * data and/or assume it starts on a page boundary.
1228                  */
1229                 bpage->vaddr &= ~PAGE_MASK;
1230                 bpage->busaddr &= ~PAGE_MASK;
1231         }
1232
1233         mtx_lock(&bounce_lock);
1234         STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
1235         bz->free_bpages++;
1236         bz->active_bpages--;
1237         if ((map = STAILQ_FIRST(&bounce_map_waitinglist)) != NULL) {
1238                 if (reserve_bounce_pages(map->dmat, map, 1) == 0) {
1239                         STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links);
1240                         STAILQ_INSERT_TAIL(&bounce_map_callbacklist,
1241                                            map, links);
1242                         busdma_swi_pending = 1;
1243                         bz->total_deferred++;
1244                         swi_sched(vm_ih, 0);
1245                 }
1246         }
1247         mtx_unlock(&bounce_lock);
1248 }
1249
1250 void
1251 busdma_swi(void)
1252 {
1253         bus_dma_tag_t dmat;
1254         struct bus_dmamap *map;
1255
1256         mtx_lock(&bounce_lock);
1257         while ((map = STAILQ_FIRST(&bounce_map_callbacklist)) != NULL) {
1258                 STAILQ_REMOVE_HEAD(&bounce_map_callbacklist, links);
1259                 mtx_unlock(&bounce_lock);
1260                 dmat = map->dmat;
1261                 (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK);
1262                 bus_dmamap_load_mem(map->dmat, map, &map->mem,
1263                                     map->callback, map->callback_arg,
1264                                     BUS_DMA_WAITOK);
1265                 (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK);
1266                 mtx_lock(&bounce_lock);
1267         }
1268         mtx_unlock(&bounce_lock);
1269 }
1270
1271 int
1272 bus_dma_tag_set_iommu(bus_dma_tag_t tag, device_t iommu, void *cookie)
1273 {
1274         tag->iommu = iommu;
1275         tag->iommu_cookie = cookie;
1276
1277         return (0);
1278 }
1279