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