xref: /freebsd/sys/arm64/arm64/busdma_bounce.c (revision 681ce946)
1 /*-
2  * Copyright (c) 1997, 1998 Justin T. Gibbs.
3  * Copyright (c) 2015-2016 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * Portions of this software were developed by Andrew Turner
7  * under sponsorship of the FreeBSD Foundation.
8  *
9  * Portions of this software were developed by Semihalf
10  * under sponsorship of the FreeBSD Foundation.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification, immediately at the beginning of the file.
18  * 2. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
25  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
40 #include <sys/bus.h>
41 #include <sys/interrupt.h>
42 #include <sys/kernel.h>
43 #include <sys/ktr.h>
44 #include <sys/lock.h>
45 #include <sys/proc.h>
46 #include <sys/memdesc.h>
47 #include <sys/mutex.h>
48 #include <sys/sysctl.h>
49 #include <sys/uio.h>
50 
51 #include <vm/vm.h>
52 #include <vm/vm_extern.h>
53 #include <vm/vm_kern.h>
54 #include <vm/vm_page.h>
55 #include <vm/vm_map.h>
56 
57 #include <machine/atomic.h>
58 #include <machine/bus.h>
59 #include <machine/md_var.h>
60 #include <arm64/include/bus_dma_impl.h>
61 
62 #define MAX_BPAGES 4096
63 
64 enum {
65 	BF_COULD_BOUNCE		= 0x01,
66 	BF_MIN_ALLOC_COMP	= 0x02,
67 	BF_KMEM_ALLOC		= 0x04,
68 	BF_COHERENT		= 0x10,
69 };
70 
71 struct bounce_zone;
72 
73 struct bus_dma_tag {
74 	struct bus_dma_tag_common common;
75 	size_t			alloc_size;
76 	size_t			alloc_alignment;
77 	int			map_count;
78 	int			bounce_flags;
79 	bus_dma_segment_t	*segments;
80 	struct bounce_zone	*bounce_zone;
81 };
82 
83 struct bounce_page {
84 	vm_offset_t	vaddr;		/* kva of bounce buffer */
85 	bus_addr_t	busaddr;	/* Physical address */
86 	vm_offset_t	datavaddr;	/* kva of client data */
87 	vm_page_t	datapage;	/* physical page of client data */
88 	vm_offset_t	dataoffs;	/* page offset of client data */
89 	bus_size_t	datacount;	/* client data count */
90 	STAILQ_ENTRY(bounce_page) links;
91 };
92 
93 int busdma_swi_pending;
94 
95 struct bounce_zone {
96 	STAILQ_ENTRY(bounce_zone) links;
97 	STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
98 	int		total_bpages;
99 	int		free_bpages;
100 	int		reserved_bpages;
101 	int		active_bpages;
102 	int		total_bounced;
103 	int		total_deferred;
104 	int		map_count;
105 	bus_size_t	alignment;
106 	bus_addr_t	lowaddr;
107 	char		zoneid[8];
108 	char		lowaddrid[20];
109 	struct sysctl_ctx_list sysctl_tree;
110 	struct sysctl_oid *sysctl_tree_top;
111 };
112 
113 static struct mtx bounce_lock;
114 static int total_bpages;
115 static int busdma_zonecount;
116 static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
117 
118 static SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
119     "Busdma parameters");
120 SYSCTL_INT(_hw_busdma, OID_AUTO, total_bpages, CTLFLAG_RD, &total_bpages, 0,
121 	   "Total bounce pages");
122 
123 struct sync_list {
124 	vm_offset_t	vaddr;		/* kva of client data */
125 	bus_addr_t	paddr;		/* physical address */
126 	vm_page_t	pages;		/* starting page of client data */
127 	bus_size_t	datacount;	/* client data count */
128 };
129 
130 struct bus_dmamap {
131 	struct bp_list	       bpages;
132 	int		       pagesneeded;
133 	int		       pagesreserved;
134 	bus_dma_tag_t	       dmat;
135 	struct memdesc	       mem;
136 	bus_dmamap_callback_t *callback;
137 	void		      *callback_arg;
138 	STAILQ_ENTRY(bus_dmamap) links;
139 	u_int			flags;
140 #define	DMAMAP_COHERENT		(1 << 0)
141 #define	DMAMAP_FROM_DMAMEM	(1 << 1)
142 #define	DMAMAP_MBUF		(1 << 2)
143 	int			sync_count;
144 	struct sync_list	slist[];
145 };
146 
147 static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
148 static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist;
149 
150 static void init_bounce_pages(void *dummy);
151 static int alloc_bounce_zone(bus_dma_tag_t dmat);
152 static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages);
153 static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
154     int commit);
155 static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map,
156     vm_offset_t vaddr, bus_addr_t addr, bus_size_t size);
157 static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage);
158 int run_filter(bus_dma_tag_t dmat, bus_addr_t paddr);
159 static bool _bus_dmamap_pagesneeded(bus_dma_tag_t dmat, bus_dmamap_t map,
160     vm_paddr_t buf, bus_size_t buflen, int *pagesneeded);
161 static void _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
162     pmap_t pmap, void *buf, bus_size_t buflen, int flags);
163 static void _bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map,
164     vm_paddr_t buf, bus_size_t buflen, int flags);
165 static int _bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
166     int flags);
167 
168 /*
169  * Return true if the DMA should bounce because the start or end does not fall
170  * on a cacheline boundary (which would require a partial cacheline flush).
171  * COHERENT memory doesn't trigger cacheline flushes.  Memory allocated by
172  * bus_dmamem_alloc() is always aligned to cacheline boundaries, and there's a
173  * strict rule that such memory cannot be accessed by the CPU while DMA is in
174  * progress (or by multiple DMA engines at once), so that it's always safe to do
175  * full cacheline flushes even if that affects memory outside the range of a
176  * given DMA operation that doesn't involve the full allocated buffer.  If we're
177  * mapping an mbuf, that follows the same rules as a buffer we allocated.
178  */
179 static bool
180 cacheline_bounce(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t paddr,
181     bus_size_t size)
182 {
183 
184 #define	DMAMAP_CACHELINE_FLAGS						\
185     (DMAMAP_FROM_DMAMEM | DMAMAP_COHERENT | DMAMAP_MBUF)
186 	if ((dmat->bounce_flags & BF_COHERENT) != 0)
187 		return (false);
188 	if (map != NULL && (map->flags & DMAMAP_CACHELINE_FLAGS) != 0)
189 		return (false);
190 	return (((paddr | size) & (dcache_line_size - 1)) != 0);
191 #undef DMAMAP_CACHELINE_FLAGS
192 }
193 
194 /*
195  * Return true if the given address does not fall on the alignment boundary.
196  */
197 static bool
198 alignment_bounce(bus_dma_tag_t dmat, bus_addr_t addr)
199 {
200 
201 	return ((addr & (dmat->common.alignment - 1)) != 0);
202 }
203 
204 static bool
205 might_bounce(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t paddr,
206     bus_size_t size)
207 {
208 
209 	/* Memory allocated by bounce_bus_dmamem_alloc won't bounce */
210 	if (map && (map->flags & DMAMAP_FROM_DMAMEM) != 0)
211 		return (false);
212 
213 	if ((dmat->bounce_flags & BF_COULD_BOUNCE) != 0)
214 		return (true);
215 
216 	if (cacheline_bounce(dmat, map, paddr, size))
217 		return (true);
218 
219 	if (alignment_bounce(dmat, paddr))
220 		return (true);
221 
222 	return (false);
223 }
224 
225 static bool
226 must_bounce(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t paddr,
227     bus_size_t size)
228 {
229 
230 	if (cacheline_bounce(dmat, map, paddr, size))
231 		return (true);
232 
233 	if (alignment_bounce(dmat, paddr))
234 		return (true);
235 
236 	if ((dmat->bounce_flags & BF_COULD_BOUNCE) != 0 &&
237 	    bus_dma_run_filter(&dmat->common, paddr))
238 		return (true);
239 
240 	return (false);
241 }
242 
243 /*
244  * Allocate a device specific dma_tag.
245  */
246 static int
247 bounce_bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
248     bus_addr_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr,
249     bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize,
250     int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
251     void *lockfuncarg, bus_dma_tag_t *dmat)
252 {
253 	bus_dma_tag_t newtag;
254 	int error;
255 
256 	*dmat = NULL;
257 	error = common_bus_dma_tag_create(parent != NULL ? &parent->common :
258 	    NULL, alignment, boundary, lowaddr, highaddr, filter, filterarg,
259 	    maxsize, nsegments, maxsegsz, flags, lockfunc, lockfuncarg,
260 	    sizeof (struct bus_dma_tag), (void **)&newtag);
261 	if (error != 0)
262 		return (error);
263 
264 	newtag->common.impl = &bus_dma_bounce_impl;
265 	newtag->map_count = 0;
266 	newtag->segments = NULL;
267 
268 	if ((flags & BUS_DMA_COHERENT) != 0) {
269 		newtag->bounce_flags |= BF_COHERENT;
270 		newtag->alloc_alignment = newtag->common.alignment;
271 		newtag->alloc_size = newtag->common.maxsize;
272 	} else {
273 		/*
274 		 * Ensure the buffer is aligned to a cacheline when allocating
275 		 * a non-coherent buffer. This is so we don't have any data
276 		 * that another CPU may be accessing around DMA buffer
277 		 * causing the cache to become dirty.
278 		 */
279 		newtag->alloc_alignment = MAX(newtag->common.alignment,
280 		    dcache_line_size);
281 		newtag->alloc_size = roundup2(newtag->common.maxsize,
282 		    dcache_line_size);
283 	}
284 
285 	if (parent != NULL) {
286 		if ((newtag->common.filter != NULL ||
287 		    (parent->bounce_flags & BF_COULD_BOUNCE) != 0))
288 			newtag->bounce_flags |= BF_COULD_BOUNCE;
289 
290 		/* Copy some flags from the parent */
291 		newtag->bounce_flags |= parent->bounce_flags & BF_COHERENT;
292 	}
293 
294 	if (newtag->common.lowaddr < ptoa((vm_paddr_t)Maxmem) ||
295 	    newtag->common.alignment > 1)
296 		newtag->bounce_flags |= BF_COULD_BOUNCE;
297 
298 	if ((flags & BUS_DMA_ALLOCNOW) != 0) {
299 		struct bounce_zone *bz;
300 		/*
301 		 * Round size up to a full page, and add one more page because
302 		 * there can always be one more boundary crossing than the
303 		 * number of pages in a transfer.
304 		 */
305 		maxsize = roundup2(maxsize, PAGE_SIZE) + PAGE_SIZE;
306 
307 		/* Must bounce */
308 		if ((error = alloc_bounce_zone(newtag)) != 0) {
309 			free(newtag, M_DEVBUF);
310 			return (error);
311 		}
312 		bz = newtag->bounce_zone;
313 
314 		if (ptoa(bz->total_bpages) < maxsize) {
315 			int pages;
316 
317 			pages = atop(maxsize) + 1 - bz->total_bpages;
318 
319 			/* Add pages to our bounce pool */
320 			if (alloc_bounce_pages(newtag, pages) < pages)
321 				error = ENOMEM;
322 		}
323 		/* Performed initial allocation */
324 		newtag->bounce_flags |= BF_MIN_ALLOC_COMP;
325 	} else
326 		error = 0;
327 
328 	if (error != 0)
329 		free(newtag, M_DEVBUF);
330 	else
331 		*dmat = newtag;
332 	CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
333 	    __func__, newtag, (newtag != NULL ? newtag->common.flags : 0),
334 	    error);
335 	return (error);
336 }
337 
338 static int
339 bounce_bus_dma_tag_destroy(bus_dma_tag_t dmat)
340 {
341 #ifdef KTR
342 	bus_dma_tag_t dmat_copy;
343 #endif
344 	bus_dma_tag_t parent;
345 	int error;
346 
347 	error = 0;
348 #ifdef KTR
349 	dmat_copy = dmat;
350 #endif
351 
352 
353 	if (dmat != NULL) {
354 		if (dmat->map_count != 0) {
355 			error = EBUSY;
356 			goto out;
357 		}
358 		while (dmat != NULL) {
359 			parent = (bus_dma_tag_t)dmat->common.parent;
360 			atomic_subtract_int(&dmat->common.ref_count, 1);
361 			if (dmat->common.ref_count == 0) {
362 				if (dmat->segments != NULL)
363 					free(dmat->segments, M_DEVBUF);
364 				free(dmat, M_DEVBUF);
365 				/*
366 				 * Last reference count, so
367 				 * release our reference
368 				 * count on our parent.
369 				 */
370 				dmat = parent;
371 			} else
372 				dmat = NULL;
373 		}
374 	}
375 out:
376 	CTR3(KTR_BUSDMA, "%s tag %p error %d", __func__, dmat_copy, error);
377 	return (error);
378 }
379 
380 static bool
381 bounce_bus_dma_id_mapped(bus_dma_tag_t dmat, vm_paddr_t buf, bus_size_t buflen)
382 {
383 
384 	if (!might_bounce(dmat, NULL, buf, buflen))
385 		return (true);
386 	return (!_bus_dmamap_pagesneeded(dmat, NULL, buf, buflen, NULL));
387 }
388 
389 static bus_dmamap_t
390 alloc_dmamap(bus_dma_tag_t dmat, int flags)
391 {
392 	u_long mapsize;
393 	bus_dmamap_t map;
394 
395 	mapsize = sizeof(*map);
396 	mapsize += sizeof(struct sync_list) * dmat->common.nsegments;
397 	map = malloc(mapsize, M_DEVBUF, flags | M_ZERO);
398 	if (map == NULL)
399 		return (NULL);
400 
401 	/* Initialize the new map */
402 	STAILQ_INIT(&map->bpages);
403 
404 	return (map);
405 }
406 
407 /*
408  * Allocate a handle for mapping from kva/uva/physical
409  * address space into bus device space.
410  */
411 static int
412 bounce_bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
413 {
414 	struct bounce_zone *bz;
415 	int error, maxpages, pages;
416 
417 	error = 0;
418 
419 	if (dmat->segments == NULL) {
420 		dmat->segments = (bus_dma_segment_t *)malloc(
421 		    sizeof(bus_dma_segment_t) * dmat->common.nsegments,
422 		    M_DEVBUF, M_NOWAIT);
423 		if (dmat->segments == NULL) {
424 			CTR3(KTR_BUSDMA, "%s: tag %p error %d",
425 			    __func__, dmat, ENOMEM);
426 			return (ENOMEM);
427 		}
428 	}
429 
430 	*mapp = alloc_dmamap(dmat, M_NOWAIT);
431 	if (*mapp == NULL) {
432 		CTR3(KTR_BUSDMA, "%s: tag %p error %d",
433 		    __func__, dmat, ENOMEM);
434 		return (ENOMEM);
435 	}
436 
437 	/*
438 	 * Bouncing might be required if the driver asks for an active
439 	 * exclusion region, a data alignment that is stricter than 1, and/or
440 	 * an active address boundary.
441 	 */
442 	if (dmat->bounce_zone == NULL) {
443 		if ((error = alloc_bounce_zone(dmat)) != 0) {
444 			free(*mapp, M_DEVBUF);
445 			return (error);
446 		}
447 	}
448 	bz = dmat->bounce_zone;
449 
450 	/*
451 	 * Attempt to add pages to our pool on a per-instance basis up to a sane
452 	 * limit. Even if the tag isn't subject of bouncing due to alignment
453 	 * and boundary constraints, it could still auto-bounce due to
454 	 * cacheline alignment, which requires at most two bounce pages.
455 	 */
456 	if (dmat->common.alignment > 1)
457 		maxpages = MAX_BPAGES;
458 	else
459 		maxpages = MIN(MAX_BPAGES, Maxmem -
460 		    atop(dmat->common.lowaddr));
461 	if ((dmat->bounce_flags & BF_MIN_ALLOC_COMP) == 0 ||
462 	    (bz->map_count > 0 && bz->total_bpages < maxpages)) {
463 		pages = atop(roundup2(dmat->common.maxsize, PAGE_SIZE)) + 1;
464 		pages = MIN(maxpages - bz->total_bpages, pages);
465 		pages = MAX(pages, 2);
466 		if (alloc_bounce_pages(dmat, pages) < pages)
467 			error = ENOMEM;
468 		if ((dmat->bounce_flags & BF_MIN_ALLOC_COMP) == 0) {
469 			if (error == 0) {
470 				dmat->bounce_flags |= BF_MIN_ALLOC_COMP;
471 			}
472 		} else
473 			error = 0;
474 	}
475 	bz->map_count++;
476 
477 	if (error == 0) {
478 		dmat->map_count++;
479 		if ((dmat->bounce_flags & BF_COHERENT) != 0)
480 			(*mapp)->flags |= DMAMAP_COHERENT;
481 	} else {
482 		free(*mapp, M_DEVBUF);
483 	}
484 	CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
485 	    __func__, dmat, dmat->common.flags, error);
486 	return (error);
487 }
488 
489 /*
490  * Destroy a handle for mapping from kva/uva/physical
491  * address space into bus device space.
492  */
493 static int
494 bounce_bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
495 {
496 
497 	/* Check we are destroying the correct map type */
498 	if ((map->flags & DMAMAP_FROM_DMAMEM) != 0)
499 		panic("bounce_bus_dmamap_destroy: Invalid map freed\n");
500 
501 	if (STAILQ_FIRST(&map->bpages) != NULL || map->sync_count != 0) {
502 		CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, EBUSY);
503 		return (EBUSY);
504 	}
505 	if (dmat->bounce_zone)
506 		dmat->bounce_zone->map_count--;
507 	free(map, M_DEVBUF);
508 	dmat->map_count--;
509 	CTR2(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat);
510 	return (0);
511 }
512 
513 /*
514  * Allocate a piece of memory that can be efficiently mapped into
515  * bus device space based on the constraints lited in the dma tag.
516  * A dmamap to for use with dmamap_load is also allocated.
517  */
518 static int
519 bounce_bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
520     bus_dmamap_t *mapp)
521 {
522 	vm_memattr_t attr;
523 	int mflags;
524 
525 	if (flags & BUS_DMA_NOWAIT)
526 		mflags = M_NOWAIT;
527 	else
528 		mflags = M_WAITOK;
529 
530 	if (dmat->segments == NULL) {
531 		dmat->segments = (bus_dma_segment_t *)malloc(
532 		    sizeof(bus_dma_segment_t) * dmat->common.nsegments,
533 		    M_DEVBUF, mflags);
534 		if (dmat->segments == NULL) {
535 			CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
536 			    __func__, dmat, dmat->common.flags, ENOMEM);
537 			return (ENOMEM);
538 		}
539 	}
540 	if (flags & BUS_DMA_ZERO)
541 		mflags |= M_ZERO;
542 	if (flags & BUS_DMA_NOCACHE)
543 		attr = VM_MEMATTR_UNCACHEABLE;
544 	else if ((flags & BUS_DMA_COHERENT) != 0 &&
545 	    (dmat->bounce_flags & BF_COHERENT) == 0)
546 		/*
547 		 * If we have a non-coherent tag, and are trying to allocate
548 		 * a coherent block of memory it needs to be uncached.
549 		 */
550 		attr = VM_MEMATTR_UNCACHEABLE;
551 	else
552 		attr = VM_MEMATTR_DEFAULT;
553 
554 	/*
555 	 * Create the map, but don't set the could bounce flag as
556 	 * this allocation should never bounce;
557 	 */
558 	*mapp = alloc_dmamap(dmat, mflags);
559 	if (*mapp == NULL) {
560 		CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
561 		    __func__, dmat, dmat->common.flags, ENOMEM);
562 		return (ENOMEM);
563 	}
564 
565 	/*
566 	 * Mark the map as coherent if we used uncacheable memory or the
567 	 * tag was already marked as coherent.
568 	 */
569 	if (attr == VM_MEMATTR_UNCACHEABLE ||
570 	    (dmat->bounce_flags & BF_COHERENT) != 0)
571 		(*mapp)->flags |= DMAMAP_COHERENT;
572 
573 	(*mapp)->flags |= DMAMAP_FROM_DMAMEM;
574 
575 	/*
576 	 * Allocate the buffer from the malloc(9) allocator if...
577 	 *  - It's small enough to fit into a single power of two sized bucket.
578 	 *  - The alignment is less than or equal to the maximum size
579 	 *  - The low address requirement is fulfilled.
580 	 * else allocate non-contiguous pages if...
581 	 *  - The page count that could get allocated doesn't exceed
582 	 *    nsegments also when the maximum segment size is less
583 	 *    than PAGE_SIZE.
584 	 *  - The alignment constraint isn't larger than a page boundary.
585 	 *  - There are no boundary-crossing constraints.
586 	 * else allocate a block of contiguous pages because one or more of the
587 	 * constraints is something that only the contig allocator can fulfill.
588 	 *
589 	 * NOTE: The (dmat->common.alignment <= dmat->maxsize) check
590 	 * below is just a quick hack. The exact alignment guarantees
591 	 * of malloc(9) need to be nailed down, and the code below
592 	 * should be rewritten to take that into account.
593 	 *
594 	 * In the meantime warn the user if malloc gets it wrong.
595 	 */
596 	if ((dmat->alloc_size <= PAGE_SIZE) &&
597 	   (dmat->alloc_alignment <= dmat->alloc_size) &&
598 	    dmat->common.lowaddr >= ptoa((vm_paddr_t)Maxmem) &&
599 	    attr == VM_MEMATTR_DEFAULT) {
600 		*vaddr = malloc(dmat->alloc_size, M_DEVBUF, mflags);
601 	} else if (dmat->common.nsegments >=
602 	    howmany(dmat->alloc_size, MIN(dmat->common.maxsegsz, PAGE_SIZE)) &&
603 	    dmat->alloc_alignment <= PAGE_SIZE &&
604 	    (dmat->common.boundary % PAGE_SIZE) == 0) {
605 		/* Page-based multi-segment allocations allowed */
606 		*vaddr = (void *)kmem_alloc_attr(dmat->alloc_size, mflags,
607 		    0ul, dmat->common.lowaddr, attr);
608 		dmat->bounce_flags |= BF_KMEM_ALLOC;
609 	} else {
610 		*vaddr = (void *)kmem_alloc_contig(dmat->alloc_size, mflags,
611 		    0ul, dmat->common.lowaddr, dmat->alloc_alignment != 0 ?
612 		    dmat->alloc_alignment : 1ul, dmat->common.boundary, attr);
613 		dmat->bounce_flags |= BF_KMEM_ALLOC;
614 	}
615 	if (*vaddr == NULL) {
616 		CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
617 		    __func__, dmat, dmat->common.flags, ENOMEM);
618 		free(*mapp, M_DEVBUF);
619 		return (ENOMEM);
620 	} else if (vtophys(*vaddr) & (dmat->alloc_alignment - 1)) {
621 		printf("bus_dmamem_alloc failed to align memory properly.\n");
622 	}
623 	dmat->map_count++;
624 	CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
625 	    __func__, dmat, dmat->common.flags, 0);
626 	return (0);
627 }
628 
629 /*
630  * Free a piece of memory and it's allociated dmamap, that was allocated
631  * via bus_dmamem_alloc.  Make the same choice for free/contigfree.
632  */
633 static void
634 bounce_bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
635 {
636 
637 	/*
638 	 * Check the map came from bounce_bus_dmamem_alloc, so the map
639 	 * should be NULL and the BF_KMEM_ALLOC flag cleared if malloc()
640 	 * was used and set if kmem_alloc_contig() was used.
641 	 */
642 	if ((map->flags & DMAMAP_FROM_DMAMEM) == 0)
643 		panic("bus_dmamem_free: Invalid map freed\n");
644 	if ((dmat->bounce_flags & BF_KMEM_ALLOC) == 0)
645 		free(vaddr, M_DEVBUF);
646 	else
647 		kmem_free((vm_offset_t)vaddr, dmat->alloc_size);
648 	free(map, M_DEVBUF);
649 	dmat->map_count--;
650 	CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat,
651 	    dmat->bounce_flags);
652 }
653 
654 static bool
655 _bus_dmamap_pagesneeded(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf,
656     bus_size_t buflen, int *pagesneeded)
657 {
658 	bus_addr_t curaddr;
659 	bus_size_t sgsize;
660 	int count;
661 
662 	/*
663 	 * Count the number of bounce pages needed in order to
664 	 * complete this transfer
665 	 */
666 	count = 0;
667 	curaddr = buf;
668 	while (buflen != 0) {
669 		sgsize = MIN(buflen, dmat->common.maxsegsz);
670 		if (must_bounce(dmat, map, curaddr, sgsize)) {
671 			sgsize = MIN(sgsize,
672 			    PAGE_SIZE - (curaddr & PAGE_MASK));
673 			if (pagesneeded == NULL)
674 				return (true);
675 			count++;
676 		}
677 		curaddr += sgsize;
678 		buflen -= sgsize;
679 	}
680 
681 	if (pagesneeded != NULL)
682 		*pagesneeded = count;
683 	return (count != 0);
684 }
685 
686 static void
687 _bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf,
688     bus_size_t buflen, int flags)
689 {
690 
691 	if (map->pagesneeded == 0) {
692 		_bus_dmamap_pagesneeded(dmat, map, buf, buflen,
693 		    &map->pagesneeded);
694 		CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded);
695 	}
696 }
697 
698 static void
699 _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap,
700     void *buf, bus_size_t buflen, int flags)
701 {
702 	vm_offset_t vaddr;
703 	vm_offset_t vendaddr;
704 	bus_addr_t paddr;
705 	bus_size_t sg_len;
706 
707 	if (map->pagesneeded == 0) {
708 		CTR4(KTR_BUSDMA, "lowaddr= %d Maxmem= %d, boundary= %d, "
709 		    "alignment= %d", dmat->common.lowaddr,
710 		    ptoa((vm_paddr_t)Maxmem),
711 		    dmat->common.boundary, dmat->common.alignment);
712 		CTR2(KTR_BUSDMA, "map= %p, pagesneeded= %d", map,
713 		    map->pagesneeded);
714 		/*
715 		 * Count the number of bounce pages
716 		 * needed in order to complete this transfer
717 		 */
718 		vaddr = (vm_offset_t)buf;
719 		vendaddr = (vm_offset_t)buf + buflen;
720 
721 		while (vaddr < vendaddr) {
722 			sg_len = PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK);
723 			if (pmap == kernel_pmap)
724 				paddr = pmap_kextract(vaddr);
725 			else
726 				paddr = pmap_extract(pmap, vaddr);
727 			if (must_bounce(dmat, map, paddr,
728 			    min(vendaddr - vaddr, (PAGE_SIZE - ((vm_offset_t)vaddr &
729 			    PAGE_MASK)))) != 0) {
730 				sg_len = roundup2(sg_len,
731 				    dmat->common.alignment);
732 				map->pagesneeded++;
733 			}
734 			vaddr += sg_len;
735 		}
736 		CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded);
737 	}
738 }
739 
740 static int
741 _bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags)
742 {
743 
744 	/* Reserve Necessary Bounce Pages */
745 	mtx_lock(&bounce_lock);
746 	if (flags & BUS_DMA_NOWAIT) {
747 		if (reserve_bounce_pages(dmat, map, 0) != 0) {
748 			mtx_unlock(&bounce_lock);
749 			return (ENOMEM);
750 		}
751 	} else {
752 		if (reserve_bounce_pages(dmat, map, 1) != 0) {
753 			/* Queue us for resources */
754 			STAILQ_INSERT_TAIL(&bounce_map_waitinglist, map, links);
755 			mtx_unlock(&bounce_lock);
756 			return (EINPROGRESS);
757 		}
758 	}
759 	mtx_unlock(&bounce_lock);
760 
761 	return (0);
762 }
763 
764 /*
765  * Add a single contiguous physical range to the segment list.
766  */
767 static bus_size_t
768 _bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr,
769     bus_size_t sgsize, bus_dma_segment_t *segs, int *segp)
770 {
771 	bus_addr_t baddr, bmask;
772 	int seg;
773 
774 	/*
775 	 * Make sure we don't cross any boundaries.
776 	 */
777 	bmask = ~(dmat->common.boundary - 1);
778 	if (dmat->common.boundary > 0) {
779 		baddr = (curaddr + dmat->common.boundary) & bmask;
780 		if (sgsize > (baddr - curaddr))
781 			sgsize = (baddr - curaddr);
782 	}
783 
784 	/*
785 	 * Insert chunk into a segment, coalescing with
786 	 * previous segment if possible.
787 	 */
788 	seg = *segp;
789 	if (seg == -1) {
790 		seg = 0;
791 		segs[seg].ds_addr = curaddr;
792 		segs[seg].ds_len = sgsize;
793 	} else {
794 		if (curaddr == segs[seg].ds_addr + segs[seg].ds_len &&
795 		    (segs[seg].ds_len + sgsize) <= dmat->common.maxsegsz &&
796 		    (dmat->common.boundary == 0 ||
797 		     (segs[seg].ds_addr & bmask) == (curaddr & bmask)))
798 			segs[seg].ds_len += sgsize;
799 		else {
800 			if (++seg >= dmat->common.nsegments)
801 				return (0);
802 			segs[seg].ds_addr = curaddr;
803 			segs[seg].ds_len = sgsize;
804 		}
805 	}
806 	*segp = seg;
807 	return (sgsize);
808 }
809 
810 /*
811  * Utility function to load a physical buffer.  segp contains
812  * the starting segment on entrace, and the ending segment on exit.
813  */
814 static int
815 bounce_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map,
816     vm_paddr_t buf, bus_size_t buflen, int flags, bus_dma_segment_t *segs,
817     int *segp)
818 {
819 	struct sync_list *sl;
820 	bus_size_t sgsize;
821 	bus_addr_t curaddr, sl_end;
822 	int error;
823 
824 	if (segs == NULL)
825 		segs = dmat->segments;
826 
827 	if (might_bounce(dmat, map, (bus_addr_t)buf, buflen)) {
828 		_bus_dmamap_count_phys(dmat, map, buf, buflen, flags);
829 		if (map->pagesneeded != 0) {
830 			error = _bus_dmamap_reserve_pages(dmat, map, flags);
831 			if (error)
832 				return (error);
833 		}
834 	}
835 
836 	sl = map->slist + map->sync_count - 1;
837 	sl_end = 0;
838 
839 	while (buflen > 0) {
840 		curaddr = buf;
841 		sgsize = MIN(buflen, dmat->common.maxsegsz);
842 		if (map->pagesneeded != 0 &&
843 		    must_bounce(dmat, map, curaddr, sgsize)) {
844 			/*
845 			 * The attempt to split a physically continuous buffer
846 			 * seems very controversial, it's unclear whether we
847 			 * can do this in all cases. Also, memory for bounced
848 			 * buffers is allocated as pages, so we cannot
849 			 * guarantee multipage alignment.
850 			 */
851 			KASSERT(dmat->common.alignment <= PAGE_SIZE,
852 			    ("bounced buffer cannot have alignment bigger "
853 			    "than PAGE_SIZE: %lu", dmat->common.alignment));
854 			sgsize = MIN(sgsize, PAGE_SIZE - (curaddr & PAGE_MASK));
855 			curaddr = add_bounce_page(dmat, map, 0, curaddr,
856 			    sgsize);
857 		} else if ((map->flags & DMAMAP_COHERENT) == 0) {
858 			if (map->sync_count > 0)
859 				sl_end = sl->paddr + sl->datacount;
860 
861 			if (map->sync_count == 0 || curaddr != sl_end) {
862 				if (++map->sync_count > dmat->common.nsegments)
863 					break;
864 				sl++;
865 				sl->vaddr = 0;
866 				sl->paddr = curaddr;
867 				sl->pages = PHYS_TO_VM_PAGE(curaddr);
868 				KASSERT(sl->pages != NULL,
869 				    ("%s: page at PA:0x%08lx is not in "
870 				    "vm_page_array", __func__, curaddr));
871 				sl->datacount = sgsize;
872 			} else
873 				sl->datacount += sgsize;
874 		}
875 		sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
876 		    segp);
877 		if (sgsize == 0)
878 			break;
879 		buf += sgsize;
880 		buflen -= sgsize;
881 	}
882 
883 	/*
884 	 * Did we fit?
885 	 */
886 	if (buflen != 0) {
887 		bus_dmamap_unload(dmat, map);
888 		return (EFBIG); /* XXX better return value here? */
889 	}
890 	return (0);
891 }
892 
893 /*
894  * Utility function to load a linear buffer.  segp contains
895  * the starting segment on entrace, and the ending segment on exit.
896  */
897 static int
898 bounce_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
899     bus_size_t buflen, pmap_t pmap, int flags, bus_dma_segment_t *segs,
900     int *segp)
901 {
902 	struct sync_list *sl;
903 	bus_size_t sgsize;
904 	bus_addr_t curaddr, sl_pend;
905 	vm_offset_t kvaddr, vaddr, sl_vend;
906 	int error;
907 
908 	KASSERT((map->flags & DMAMAP_FROM_DMAMEM) != 0 ||
909 	    dmat->common.alignment <= PAGE_SIZE,
910 	    ("loading user buffer with alignment bigger than PAGE_SIZE is not "
911 	    "supported"));
912 
913 	if (segs == NULL)
914 		segs = dmat->segments;
915 
916 	if (flags & BUS_DMA_LOAD_MBUF)
917 		map->flags |= DMAMAP_MBUF;
918 
919 	if (might_bounce(dmat, map, (bus_addr_t)buf, buflen)) {
920 		_bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags);
921 		if (map->pagesneeded != 0) {
922 			error = _bus_dmamap_reserve_pages(dmat, map, flags);
923 			if (error)
924 				return (error);
925 		}
926 	}
927 
928 	/*
929 	 * XXX Optimally we should parse input buffer for physically
930 	 * continuous segments first and then pass these segment into
931 	 * load loop.
932 	 */
933 	sl = map->slist + map->sync_count - 1;
934 	vaddr = (vm_offset_t)buf;
935 	sl_pend = 0;
936 	sl_vend = 0;
937 
938 	while (buflen > 0) {
939 		/*
940 		 * Get the physical address for this segment.
941 		 */
942 		if (__predict_true(pmap == kernel_pmap)) {
943 			curaddr = pmap_kextract(vaddr);
944 			kvaddr = vaddr;
945 		} else {
946 			curaddr = pmap_extract(pmap, vaddr);
947 			kvaddr = 0;
948 		}
949 
950 		/*
951 		 * Compute the segment size, and adjust counts.
952 		 */
953 		sgsize = MIN(buflen, dmat->common.maxsegsz);
954 		if ((map->flags & DMAMAP_FROM_DMAMEM) == 0)
955 			sgsize = MIN(sgsize, PAGE_SIZE - (curaddr & PAGE_MASK));
956 
957 		if (map->pagesneeded != 0 &&
958 		    must_bounce(dmat, map, curaddr, sgsize)) {
959 			/* See comment in bounce_bus_dmamap_load_phys */
960 			KASSERT(dmat->common.alignment <= PAGE_SIZE,
961 			    ("bounced buffer cannot have alignment bigger "
962 			    "than PAGE_SIZE: %lu", dmat->common.alignment));
963 			curaddr = add_bounce_page(dmat, map, kvaddr, curaddr,
964 			    sgsize);
965 		} else if ((map->flags & DMAMAP_COHERENT) == 0) {
966 			if (map->sync_count > 0) {
967 				sl_pend = sl->paddr + sl->datacount;
968 				sl_vend = sl->vaddr + sl->datacount;
969 			}
970 
971 			if (map->sync_count == 0 ||
972 			    (kvaddr != 0 && kvaddr != sl_vend) ||
973 			    (curaddr != sl_pend)) {
974 				if (++map->sync_count > dmat->common.nsegments)
975 					break;
976 				sl++;
977 				sl->vaddr = kvaddr;
978 				sl->paddr = curaddr;
979 				if (kvaddr != 0) {
980 					sl->pages = NULL;
981 				} else {
982 					sl->pages = PHYS_TO_VM_PAGE(curaddr);
983 					KASSERT(sl->pages != NULL,
984 					    ("%s: page at PA:0x%08lx is not "
985 					    "in vm_page_array", __func__,
986 					    curaddr));
987 				}
988 				sl->datacount = sgsize;
989 			} else
990 				sl->datacount += sgsize;
991 		}
992 		sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
993 		    segp);
994 		if (sgsize == 0)
995 			break;
996 		vaddr += sgsize;
997 		buflen -= sgsize;
998 	}
999 
1000 	/*
1001 	 * Did we fit?
1002 	 */
1003 	if (buflen != 0) {
1004 		bus_dmamap_unload(dmat, map);
1005 		return (EFBIG); /* XXX better return value here? */
1006 	}
1007 	return (0);
1008 }
1009 
1010 static void
1011 bounce_bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
1012     struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg)
1013 {
1014 
1015 	map->mem = *mem;
1016 	map->dmat = dmat;
1017 	map->callback = callback;
1018 	map->callback_arg = callback_arg;
1019 }
1020 
1021 static bus_dma_segment_t *
1022 bounce_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map,
1023     bus_dma_segment_t *segs, int nsegs, int error)
1024 {
1025 
1026 	if (segs == NULL)
1027 		segs = dmat->segments;
1028 	return (segs);
1029 }
1030 
1031 /*
1032  * Release the mapping held by map.
1033  */
1034 static void
1035 bounce_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
1036 {
1037 	struct bounce_page *bpage;
1038 
1039 	while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
1040 		STAILQ_REMOVE_HEAD(&map->bpages, links);
1041 		free_bounce_page(dmat, bpage);
1042 	}
1043 
1044 	map->sync_count = 0;
1045 	map->flags &= ~DMAMAP_MBUF;
1046 }
1047 
1048 static void
1049 dma_preread_safe(vm_offset_t va, vm_size_t size)
1050 {
1051 	/*
1052 	 * Write back any partial cachelines immediately before and
1053 	 * after the DMA region.
1054 	 */
1055 	if (va & (dcache_line_size - 1))
1056 		cpu_dcache_wb_range(va, 1);
1057 	if ((va + size) & (dcache_line_size - 1))
1058 		cpu_dcache_wb_range(va + size, 1);
1059 
1060 	cpu_dcache_inv_range(va, size);
1061 }
1062 
1063 static void
1064 dma_dcache_sync(struct sync_list *sl, bus_dmasync_op_t op)
1065 {
1066 	uint32_t len, offset;
1067 	vm_page_t m;
1068 	vm_paddr_t pa;
1069 	vm_offset_t va, tempva;
1070 	bus_size_t size;
1071 
1072 	offset = sl->paddr & PAGE_MASK;
1073 	m = sl->pages;
1074 	size = sl->datacount;
1075 	pa = sl->paddr;
1076 
1077 	for ( ; size != 0; size -= len, pa += len, offset = 0, ++m) {
1078 		tempva = 0;
1079 		if (sl->vaddr == 0) {
1080 			len = min(PAGE_SIZE - offset, size);
1081 			tempva = pmap_quick_enter_page(m);
1082 			va = tempva | offset;
1083 			KASSERT(pa == (VM_PAGE_TO_PHYS(m) | offset),
1084 			    ("unexpected vm_page_t phys: 0x%16lx != 0x%16lx",
1085 			    VM_PAGE_TO_PHYS(m) | offset, pa));
1086 		} else {
1087 			len = sl->datacount;
1088 			va = sl->vaddr;
1089 		}
1090 
1091 		switch (op) {
1092 		case BUS_DMASYNC_PREWRITE:
1093 		case BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD:
1094 			cpu_dcache_wb_range(va, len);
1095 			break;
1096 		case BUS_DMASYNC_PREREAD:
1097 			/*
1098 			 * An mbuf may start in the middle of a cacheline. There
1099 			 * will be no cpu writes to the beginning of that line
1100 			 * (which contains the mbuf header) while dma is in
1101 			 * progress.  Handle that case by doing a writeback of
1102 			 * just the first cacheline before invalidating the
1103 			 * overall buffer.  Any mbuf in a chain may have this
1104 			 * misalignment.  Buffers which are not mbufs bounce if
1105 			 * they are not aligned to a cacheline.
1106 			 */
1107 			dma_preread_safe(va, len);
1108 			break;
1109 		case BUS_DMASYNC_POSTREAD:
1110 		case BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE:
1111 			cpu_dcache_inv_range(va, len);
1112 			break;
1113 		default:
1114 			panic("unsupported combination of sync operations: "
1115                               "0x%08x\n", op);
1116 		}
1117 
1118 		if (tempva != 0)
1119 			pmap_quick_remove_page(tempva);
1120 	}
1121 }
1122 
1123 static void
1124 bounce_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map,
1125     bus_dmasync_op_t op)
1126 {
1127 	struct bounce_page *bpage;
1128 	struct sync_list *sl, *end;
1129 	vm_offset_t datavaddr, tempvaddr;
1130 
1131 	if (op == BUS_DMASYNC_POSTWRITE)
1132 		return;
1133 
1134 	if ((op & BUS_DMASYNC_POSTREAD) != 0) {
1135 		/*
1136 		 * Wait for any DMA operations to complete before the bcopy.
1137 		 */
1138 		dsb(sy);
1139 	}
1140 
1141 	if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
1142 		CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
1143 		    "performing bounce", __func__, dmat, dmat->common.flags,
1144 		    op);
1145 
1146 		if ((op & BUS_DMASYNC_PREWRITE) != 0) {
1147 			while (bpage != NULL) {
1148 				tempvaddr = 0;
1149 				datavaddr = bpage->datavaddr;
1150 				if (datavaddr == 0) {
1151 					tempvaddr = pmap_quick_enter_page(
1152 					    bpage->datapage);
1153 					datavaddr = tempvaddr | bpage->dataoffs;
1154 				}
1155 
1156 				bcopy((void *)datavaddr,
1157 				    (void *)bpage->vaddr, bpage->datacount);
1158 				if (tempvaddr != 0)
1159 					pmap_quick_remove_page(tempvaddr);
1160 				if ((map->flags & DMAMAP_COHERENT) == 0)
1161 					cpu_dcache_wb_range(bpage->vaddr,
1162 					    bpage->datacount);
1163 				bpage = STAILQ_NEXT(bpage, links);
1164 			}
1165 			dmat->bounce_zone->total_bounced++;
1166 		} else if ((op & BUS_DMASYNC_PREREAD) != 0) {
1167 			while (bpage != NULL) {
1168 				if ((map->flags & DMAMAP_COHERENT) == 0)
1169 					cpu_dcache_wbinv_range(bpage->vaddr,
1170 					    bpage->datacount);
1171 				bpage = STAILQ_NEXT(bpage, links);
1172 			}
1173 		}
1174 
1175 		if ((op & BUS_DMASYNC_POSTREAD) != 0) {
1176 			while (bpage != NULL) {
1177 				if ((map->flags & DMAMAP_COHERENT) == 0)
1178 					cpu_dcache_inv_range(bpage->vaddr,
1179 					    bpage->datacount);
1180 				tempvaddr = 0;
1181 				datavaddr = bpage->datavaddr;
1182 				if (datavaddr == 0) {
1183 					tempvaddr = pmap_quick_enter_page(
1184 					    bpage->datapage);
1185 					datavaddr = tempvaddr | bpage->dataoffs;
1186 				}
1187 
1188 				bcopy((void *)bpage->vaddr,
1189 				    (void *)datavaddr, bpage->datacount);
1190 
1191 				if (tempvaddr != 0)
1192 					pmap_quick_remove_page(tempvaddr);
1193 				bpage = STAILQ_NEXT(bpage, links);
1194 			}
1195 			dmat->bounce_zone->total_bounced++;
1196 		}
1197 	}
1198 
1199 	/*
1200 	 * Cache maintenance for normal (non-COHERENT non-bounce) buffers.
1201 	 */
1202 	if (map->sync_count != 0) {
1203 		sl = &map->slist[0];
1204 		end = &map->slist[map->sync_count];
1205 		CTR3(KTR_BUSDMA, "%s: tag %p op 0x%x "
1206 		    "performing sync", __func__, dmat, op);
1207 
1208 		for ( ; sl != end; ++sl)
1209 			dma_dcache_sync(sl, op);
1210 	}
1211 
1212 	if ((op & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)) != 0) {
1213 		/*
1214 		 * Wait for the bcopy to complete before any DMA operations.
1215 		 */
1216 		dsb(sy);
1217 	}
1218 }
1219 
1220 static void
1221 init_bounce_pages(void *dummy __unused)
1222 {
1223 
1224 	total_bpages = 0;
1225 	STAILQ_INIT(&bounce_zone_list);
1226 	STAILQ_INIT(&bounce_map_waitinglist);
1227 	STAILQ_INIT(&bounce_map_callbacklist);
1228 	mtx_init(&bounce_lock, "bounce pages lock", NULL, MTX_DEF);
1229 }
1230 SYSINIT(bpages, SI_SUB_LOCK, SI_ORDER_ANY, init_bounce_pages, NULL);
1231 
1232 static struct sysctl_ctx_list *
1233 busdma_sysctl_tree(struct bounce_zone *bz)
1234 {
1235 
1236 	return (&bz->sysctl_tree);
1237 }
1238 
1239 static struct sysctl_oid *
1240 busdma_sysctl_tree_top(struct bounce_zone *bz)
1241 {
1242 
1243 	return (bz->sysctl_tree_top);
1244 }
1245 
1246 static int
1247 alloc_bounce_zone(bus_dma_tag_t dmat)
1248 {
1249 	struct bounce_zone *bz;
1250 
1251 	/* Check to see if we already have a suitable zone */
1252 	STAILQ_FOREACH(bz, &bounce_zone_list, links) {
1253 		if ((dmat->common.alignment <= bz->alignment) &&
1254 		    (dmat->common.lowaddr >= bz->lowaddr)) {
1255 			dmat->bounce_zone = bz;
1256 			return (0);
1257 		}
1258 	}
1259 
1260 	if ((bz = (struct bounce_zone *)malloc(sizeof(*bz), M_DEVBUF,
1261 	    M_NOWAIT | M_ZERO)) == NULL)
1262 		return (ENOMEM);
1263 
1264 	STAILQ_INIT(&bz->bounce_page_list);
1265 	bz->free_bpages = 0;
1266 	bz->reserved_bpages = 0;
1267 	bz->active_bpages = 0;
1268 	bz->lowaddr = dmat->common.lowaddr;
1269 	bz->alignment = MAX(dmat->common.alignment, PAGE_SIZE);
1270 	bz->map_count = 0;
1271 	snprintf(bz->zoneid, 8, "zone%d", busdma_zonecount);
1272 	busdma_zonecount++;
1273 	snprintf(bz->lowaddrid, 18, "%#jx", (uintmax_t)bz->lowaddr);
1274 	STAILQ_INSERT_TAIL(&bounce_zone_list, bz, links);
1275 	dmat->bounce_zone = bz;
1276 
1277 	sysctl_ctx_init(&bz->sysctl_tree);
1278 	bz->sysctl_tree_top = SYSCTL_ADD_NODE(&bz->sysctl_tree,
1279 	    SYSCTL_STATIC_CHILDREN(_hw_busdma), OID_AUTO, bz->zoneid,
1280 	    CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
1281 	if (bz->sysctl_tree_top == NULL) {
1282 		sysctl_ctx_free(&bz->sysctl_tree);
1283 		return (0);	/* XXX error code? */
1284 	}
1285 
1286 	SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1287 	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1288 	    "total_bpages", CTLFLAG_RD, &bz->total_bpages, 0,
1289 	    "Total bounce pages");
1290 	SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1291 	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1292 	    "free_bpages", CTLFLAG_RD, &bz->free_bpages, 0,
1293 	    "Free bounce pages");
1294 	SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1295 	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1296 	    "reserved_bpages", CTLFLAG_RD, &bz->reserved_bpages, 0,
1297 	    "Reserved bounce pages");
1298 	SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1299 	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1300 	    "active_bpages", CTLFLAG_RD, &bz->active_bpages, 0,
1301 	    "Active bounce pages");
1302 	SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1303 	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1304 	    "total_bounced", CTLFLAG_RD, &bz->total_bounced, 0,
1305 	    "Total bounce requests");
1306 	SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
1307 	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1308 	    "total_deferred", CTLFLAG_RD, &bz->total_deferred, 0,
1309 	    "Total bounce requests that were deferred");
1310 	SYSCTL_ADD_STRING(busdma_sysctl_tree(bz),
1311 	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1312 	    "lowaddr", CTLFLAG_RD, bz->lowaddrid, 0, "");
1313 	SYSCTL_ADD_UAUTO(busdma_sysctl_tree(bz),
1314 	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
1315 	    "alignment", CTLFLAG_RD, &bz->alignment, "");
1316 
1317 	return (0);
1318 }
1319 
1320 static int
1321 alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages)
1322 {
1323 	struct bounce_zone *bz;
1324 	int count;
1325 
1326 	bz = dmat->bounce_zone;
1327 	count = 0;
1328 	while (numpages > 0) {
1329 		struct bounce_page *bpage;
1330 
1331 		bpage = (struct bounce_page *)malloc(sizeof(*bpage), M_DEVBUF,
1332 						     M_NOWAIT | M_ZERO);
1333 
1334 		if (bpage == NULL)
1335 			break;
1336 		bpage->vaddr = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF,
1337 		    M_NOWAIT, 0ul, bz->lowaddr, PAGE_SIZE, 0);
1338 		if (bpage->vaddr == 0) {
1339 			free(bpage, M_DEVBUF);
1340 			break;
1341 		}
1342 		bpage->busaddr = pmap_kextract(bpage->vaddr);
1343 		mtx_lock(&bounce_lock);
1344 		STAILQ_INSERT_TAIL(&bz->bounce_page_list, bpage, links);
1345 		total_bpages++;
1346 		bz->total_bpages++;
1347 		bz->free_bpages++;
1348 		mtx_unlock(&bounce_lock);
1349 		count++;
1350 		numpages--;
1351 	}
1352 	return (count);
1353 }
1354 
1355 static int
1356 reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit)
1357 {
1358 	struct bounce_zone *bz;
1359 	int pages;
1360 
1361 	mtx_assert(&bounce_lock, MA_OWNED);
1362 	bz = dmat->bounce_zone;
1363 	pages = MIN(bz->free_bpages, map->pagesneeded - map->pagesreserved);
1364 	if (commit == 0 && map->pagesneeded > (map->pagesreserved + pages))
1365 		return (map->pagesneeded - (map->pagesreserved + pages));
1366 	bz->free_bpages -= pages;
1367 	bz->reserved_bpages += pages;
1368 	map->pagesreserved += pages;
1369 	pages = map->pagesneeded - map->pagesreserved;
1370 
1371 	return (pages);
1372 }
1373 
1374 static bus_addr_t
1375 add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr,
1376 		bus_addr_t addr, bus_size_t size)
1377 {
1378 	struct bounce_zone *bz;
1379 	struct bounce_page *bpage;
1380 
1381 	KASSERT(dmat->bounce_zone != NULL, ("no bounce zone in dma tag"));
1382 
1383 	bz = dmat->bounce_zone;
1384 	if (map->pagesneeded == 0)
1385 		panic("add_bounce_page: map doesn't need any pages");
1386 	map->pagesneeded--;
1387 
1388 	if (map->pagesreserved == 0)
1389 		panic("add_bounce_page: map doesn't need any pages");
1390 	map->pagesreserved--;
1391 
1392 	mtx_lock(&bounce_lock);
1393 	bpage = STAILQ_FIRST(&bz->bounce_page_list);
1394 	if (bpage == NULL)
1395 		panic("add_bounce_page: free page list is empty");
1396 
1397 	STAILQ_REMOVE_HEAD(&bz->bounce_page_list, links);
1398 	bz->reserved_bpages--;
1399 	bz->active_bpages++;
1400 	mtx_unlock(&bounce_lock);
1401 
1402 	if (dmat->common.flags & BUS_DMA_KEEP_PG_OFFSET) {
1403 		/* Page offset needs to be preserved. */
1404 		bpage->vaddr |= addr & PAGE_MASK;
1405 		bpage->busaddr |= addr & PAGE_MASK;
1406 	}
1407 	bpage->datavaddr = vaddr;
1408 	bpage->datapage = PHYS_TO_VM_PAGE(addr);
1409 	bpage->dataoffs = addr & PAGE_MASK;
1410 	bpage->datacount = size;
1411 	STAILQ_INSERT_TAIL(&(map->bpages), bpage, links);
1412 	return (bpage->busaddr);
1413 }
1414 
1415 static void
1416 free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
1417 {
1418 	struct bus_dmamap *map;
1419 	struct bounce_zone *bz;
1420 
1421 	bz = dmat->bounce_zone;
1422 	bpage->datavaddr = 0;
1423 	bpage->datacount = 0;
1424 	if (dmat->common.flags & BUS_DMA_KEEP_PG_OFFSET) {
1425 		/*
1426 		 * Reset the bounce page to start at offset 0.  Other uses
1427 		 * of this bounce page may need to store a full page of
1428 		 * data and/or assume it starts on a page boundary.
1429 		 */
1430 		bpage->vaddr &= ~PAGE_MASK;
1431 		bpage->busaddr &= ~PAGE_MASK;
1432 	}
1433 
1434 	mtx_lock(&bounce_lock);
1435 	STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
1436 	bz->free_bpages++;
1437 	bz->active_bpages--;
1438 	if ((map = STAILQ_FIRST(&bounce_map_waitinglist)) != NULL) {
1439 		if (reserve_bounce_pages(map->dmat, map, 1) == 0) {
1440 			STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links);
1441 			STAILQ_INSERT_TAIL(&bounce_map_callbacklist,
1442 			    map, links);
1443 			busdma_swi_pending = 1;
1444 			bz->total_deferred++;
1445 			swi_sched(vm_ih, 0);
1446 		}
1447 	}
1448 	mtx_unlock(&bounce_lock);
1449 }
1450 
1451 void
1452 busdma_swi(void)
1453 {
1454 	bus_dma_tag_t dmat;
1455 	struct bus_dmamap *map;
1456 
1457 	mtx_lock(&bounce_lock);
1458 	while ((map = STAILQ_FIRST(&bounce_map_callbacklist)) != NULL) {
1459 		STAILQ_REMOVE_HEAD(&bounce_map_callbacklist, links);
1460 		mtx_unlock(&bounce_lock);
1461 		dmat = map->dmat;
1462 		(dmat->common.lockfunc)(dmat->common.lockfuncarg, BUS_DMA_LOCK);
1463 		bus_dmamap_load_mem(map->dmat, map, &map->mem,
1464 		    map->callback, map->callback_arg, BUS_DMA_WAITOK);
1465 		(dmat->common.lockfunc)(dmat->common.lockfuncarg,
1466 		    BUS_DMA_UNLOCK);
1467 		mtx_lock(&bounce_lock);
1468 	}
1469 	mtx_unlock(&bounce_lock);
1470 }
1471 
1472 struct bus_dma_impl bus_dma_bounce_impl = {
1473 	.tag_create = bounce_bus_dma_tag_create,
1474 	.tag_destroy = bounce_bus_dma_tag_destroy,
1475 	.id_mapped = bounce_bus_dma_id_mapped,
1476 	.map_create = bounce_bus_dmamap_create,
1477 	.map_destroy = bounce_bus_dmamap_destroy,
1478 	.mem_alloc = bounce_bus_dmamem_alloc,
1479 	.mem_free = bounce_bus_dmamem_free,
1480 	.load_phys = bounce_bus_dmamap_load_phys,
1481 	.load_buffer = bounce_bus_dmamap_load_buffer,
1482 	.load_ma = bus_dmamap_load_ma_triv,
1483 	.map_waitok = bounce_bus_dmamap_waitok,
1484 	.map_complete = bounce_bus_dmamap_complete,
1485 	.map_unload = bounce_bus_dmamap_unload,
1486 	.map_sync = bounce_bus_dmamap_sync
1487 };
1488