1 /* 2 * Copyright (c) 1997, 1998 Justin T. Gibbs. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions, and the following disclaimer, 10 * without modification, immediately at the beginning of the file. 11 * 2. The name of the author may not be used to endorse or promote products 12 * derived from this software without specific prior written permission. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: src/sys/i386/i386/busdma_machdep.c,v 1.94 2008/08/15 20:51:31 kmacy Exp $ 27 * $DragonFly: src/sys/platform/pc32/i386/busdma_machdep.c,v 1.23 2008/06/05 18:06:32 swildner Exp $ 28 */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/malloc.h> 33 #include <sys/mbuf.h> 34 #include <sys/uio.h> 35 #include <sys/bus_dma.h> 36 #include <sys/kernel.h> 37 #include <sys/sysctl.h> 38 #include <sys/lock.h> 39 40 #include <sys/thread2.h> 41 #include <sys/spinlock2.h> 42 #include <sys/mplock2.h> 43 44 #include <vm/vm.h> 45 #include <vm/vm_page.h> 46 47 /* XXX needed for to access pmap to convert per-proc virtual to physical */ 48 #include <sys/proc.h> 49 #include <sys/lock.h> 50 #include <vm/vm_map.h> 51 52 #include <machine/md_var.h> 53 54 #define MAX_BPAGES 1024 55 56 /* 57 * 16 x N declared on stack. 58 */ 59 #define BUS_DMA_CACHE_SEGMENTS 8 60 61 struct bounce_zone; 62 struct bus_dmamap; 63 64 struct bus_dma_tag { 65 bus_dma_tag_t parent; 66 bus_size_t alignment; 67 bus_size_t boundary; 68 bus_addr_t lowaddr; 69 bus_addr_t highaddr; 70 bus_dma_filter_t *filter; 71 void *filterarg; 72 bus_size_t maxsize; 73 u_int nsegments; 74 bus_size_t maxsegsz; 75 int flags; 76 int ref_count; 77 int map_count; 78 bus_dma_segment_t *segments; 79 struct bounce_zone *bounce_zone; 80 #ifdef SMP 81 struct spinlock spin; 82 #else 83 int unused0; 84 #endif 85 }; 86 87 /* 88 * bus_dma_tag private flags 89 */ 90 #define BUS_DMA_BOUNCE_ALIGN BUS_DMA_BUS2 91 #define BUS_DMA_BOUNCE_LOWADDR BUS_DMA_BUS3 92 #define BUS_DMA_MIN_ALLOC_COMP BUS_DMA_BUS4 93 94 #define BUS_DMA_COULD_BOUNCE (BUS_DMA_BOUNCE_LOWADDR | BUS_DMA_BOUNCE_ALIGN) 95 96 #define BUS_DMAMEM_KMALLOC(dmat) \ 97 ((dmat)->maxsize <= PAGE_SIZE && \ 98 (dmat)->alignment <= PAGE_SIZE && \ 99 (dmat)->lowaddr >= ptoa(Maxmem)) 100 101 struct bounce_page { 102 vm_offset_t vaddr; /* kva of bounce buffer */ 103 bus_addr_t busaddr; /* Physical address */ 104 vm_offset_t datavaddr; /* kva of client data */ 105 bus_size_t datacount; /* client data count */ 106 STAILQ_ENTRY(bounce_page) links; 107 }; 108 109 struct bounce_zone { 110 STAILQ_ENTRY(bounce_zone) links; 111 STAILQ_HEAD(bp_list, bounce_page) bounce_page_list; 112 STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist; 113 #ifdef SMP 114 struct spinlock spin; 115 #else 116 int unused0; 117 #endif 118 int total_bpages; 119 int free_bpages; 120 int reserved_bpages; 121 int active_bpages; 122 int total_bounced; 123 int total_deferred; 124 int reserve_failed; 125 bus_size_t alignment; 126 bus_addr_t lowaddr; 127 char zoneid[8]; 128 char lowaddrid[20]; 129 struct sysctl_ctx_list sysctl_ctx; 130 struct sysctl_oid *sysctl_tree; 131 }; 132 133 #ifdef SMP 134 #define BZ_LOCK(bz) spin_lock(&(bz)->spin) 135 #define BZ_UNLOCK(bz) spin_unlock(&(bz)->spin) 136 #else 137 #define BZ_LOCK(bz) crit_enter() 138 #define BZ_UNLOCK(bz) crit_exit() 139 #endif 140 141 static struct lwkt_token bounce_zone_tok = 142 LWKT_TOKEN_MP_INITIALIZER(bounce_zone_token); 143 static int busdma_zonecount; 144 static STAILQ_HEAD(, bounce_zone) bounce_zone_list = 145 STAILQ_HEAD_INITIALIZER(bounce_zone_list); 146 147 int busdma_swi_pending; 148 static int total_bounce_pages; 149 static int max_bounce_pages = MAX_BPAGES; 150 static int bounce_alignment = 1; /* XXX temporary */ 151 152 TUNABLE_INT("hw.busdma.max_bpages", &max_bounce_pages); 153 TUNABLE_INT("hw.busdma.bounce_alignment", &bounce_alignment); 154 155 struct bus_dmamap { 156 struct bp_list bpages; 157 int pagesneeded; 158 int pagesreserved; 159 bus_dma_tag_t dmat; 160 void *buf; /* unmapped buffer pointer */ 161 bus_size_t buflen; /* unmapped buffer length */ 162 bus_dmamap_callback_t *callback; 163 void *callback_arg; 164 STAILQ_ENTRY(bus_dmamap) links; 165 }; 166 167 static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist = 168 STAILQ_HEAD_INITIALIZER(bounce_map_callbacklist); 169 static struct spinlock bounce_map_list_spin = 170 SPINLOCK_INITIALIZER(&bounce_map_list_spin); 171 172 static struct bus_dmamap nobounce_dmamap; 173 174 static int alloc_bounce_zone(bus_dma_tag_t); 175 static int alloc_bounce_pages(bus_dma_tag_t, u_int, int); 176 static int reserve_bounce_pages(bus_dma_tag_t, bus_dmamap_t, int); 177 static void return_bounce_pages(bus_dma_tag_t, bus_dmamap_t); 178 static bus_addr_t add_bounce_page(bus_dma_tag_t, bus_dmamap_t, 179 vm_offset_t, bus_size_t); 180 static void free_bounce_page(bus_dma_tag_t, struct bounce_page *); 181 182 static bus_dmamap_t get_map_waiting(bus_dma_tag_t); 183 static void add_map_callback(bus_dmamap_t); 184 185 SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD, 0, "Busdma parameters"); 186 SYSCTL_INT(_hw_busdma, OID_AUTO, total_bpages, CTLFLAG_RD, &total_bounce_pages, 187 0, "Total bounce pages"); 188 SYSCTL_INT(_hw_busdma, OID_AUTO, max_bpages, CTLFLAG_RD, &max_bounce_pages, 189 0, "Max bounce pages per bounce zone"); 190 SYSCTL_INT(_hw_busdma, OID_AUTO, bounce_alignment, CTLFLAG_RD, 191 &bounce_alignment, 0, "Obey alignment constraint"); 192 193 static __inline int 194 run_filter(bus_dma_tag_t dmat, bus_addr_t paddr) 195 { 196 int retval; 197 198 retval = 0; 199 do { 200 if (((paddr > dmat->lowaddr && paddr <= dmat->highaddr) || 201 (bounce_alignment && (paddr & (dmat->alignment - 1)) != 0)) 202 && (dmat->filter == NULL || 203 dmat->filter(dmat->filterarg, paddr) != 0)) 204 retval = 1; 205 206 dmat = dmat->parent; 207 } while (retval == 0 && dmat != NULL); 208 return (retval); 209 } 210 211 static __inline 212 bus_dma_segment_t * 213 bus_dma_tag_lock(bus_dma_tag_t tag, bus_dma_segment_t *cache) 214 { 215 if (tag->nsegments <= BUS_DMA_CACHE_SEGMENTS) 216 return(cache); 217 #ifdef SMP 218 spin_lock(&tag->spin); 219 #endif 220 return(tag->segments); 221 } 222 223 static __inline 224 void 225 bus_dma_tag_unlock(bus_dma_tag_t tag) 226 { 227 #ifdef SMP 228 if (tag->nsegments > BUS_DMA_CACHE_SEGMENTS) 229 spin_unlock(&tag->spin); 230 #endif 231 } 232 233 /* 234 * Allocate a device specific dma_tag. 235 */ 236 int 237 bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, 238 bus_size_t boundary, bus_addr_t lowaddr, 239 bus_addr_t highaddr, bus_dma_filter_t *filter, 240 void *filterarg, bus_size_t maxsize, int nsegments, 241 bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat) 242 { 243 bus_dma_tag_t newtag; 244 int error = 0; 245 246 /* 247 * Sanity checks 248 */ 249 250 if (alignment == 0) 251 alignment = 1; 252 if (alignment & (alignment - 1)) 253 panic("alignment must be power of 2\n"); 254 255 if (boundary != 0) { 256 if (boundary & (boundary - 1)) 257 panic("boundary must be power of 2\n"); 258 if (boundary < maxsegsz) { 259 kprintf("boundary < maxsegsz:\n"); 260 print_backtrace(-1); 261 maxsegsz = boundary; 262 } 263 } 264 265 /* Return a NULL tag on failure */ 266 *dmat = NULL; 267 268 newtag = kmalloc(sizeof(*newtag), M_DEVBUF, M_INTWAIT | M_ZERO); 269 270 #ifdef SMP 271 spin_init(&newtag->spin); 272 #endif 273 newtag->parent = parent; 274 newtag->alignment = alignment; 275 newtag->boundary = boundary; 276 newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1); 277 newtag->highaddr = trunc_page((vm_paddr_t)highaddr) + (PAGE_SIZE - 1); 278 newtag->filter = filter; 279 newtag->filterarg = filterarg; 280 newtag->maxsize = maxsize; 281 newtag->nsegments = nsegments; 282 newtag->maxsegsz = maxsegsz; 283 newtag->flags = flags; 284 newtag->ref_count = 1; /* Count ourself */ 285 newtag->map_count = 0; 286 newtag->segments = NULL; 287 newtag->bounce_zone = NULL; 288 289 /* Take into account any restrictions imposed by our parent tag */ 290 if (parent != NULL) { 291 newtag->lowaddr = MIN(parent->lowaddr, newtag->lowaddr); 292 newtag->highaddr = MAX(parent->highaddr, newtag->highaddr); 293 294 if (newtag->boundary == 0) { 295 newtag->boundary = parent->boundary; 296 } else if (parent->boundary != 0) { 297 newtag->boundary = MIN(parent->boundary, 298 newtag->boundary); 299 } 300 301 #ifdef notyet 302 newtag->alignment = MAX(parent->alignment, newtag->alignment); 303 #endif 304 305 if (newtag->filter == NULL) { 306 /* 307 * Short circuit looking at our parent directly 308 * since we have encapsulated all of its information 309 */ 310 newtag->filter = parent->filter; 311 newtag->filterarg = parent->filterarg; 312 newtag->parent = parent->parent; 313 } 314 if (newtag->parent != NULL) 315 parent->ref_count++; 316 } 317 318 if (newtag->lowaddr < ptoa(Maxmem)) 319 newtag->flags |= BUS_DMA_BOUNCE_LOWADDR; 320 if (bounce_alignment && newtag->alignment > 1 && 321 !(newtag->flags & BUS_DMA_ALIGNED)) 322 newtag->flags |= BUS_DMA_BOUNCE_ALIGN; 323 324 if ((newtag->flags & BUS_DMA_COULD_BOUNCE) && 325 (flags & BUS_DMA_ALLOCNOW) != 0) { 326 struct bounce_zone *bz; 327 328 /* Must bounce */ 329 330 error = alloc_bounce_zone(newtag); 331 if (error) 332 goto back; 333 bz = newtag->bounce_zone; 334 335 if (ptoa(bz->total_bpages) < maxsize) { 336 int pages; 337 338 if (flags & BUS_DMA_ONEBPAGE) { 339 pages = 1; 340 } else { 341 pages = atop(round_page(maxsize)) - 342 bz->total_bpages; 343 pages = MAX(pages, 1); 344 } 345 346 /* Add pages to our bounce pool */ 347 if (alloc_bounce_pages(newtag, pages, flags) < pages) 348 error = ENOMEM; 349 350 /* Performed initial allocation */ 351 newtag->flags |= BUS_DMA_MIN_ALLOC_COMP; 352 } 353 } 354 back: 355 if (error) 356 kfree(newtag, M_DEVBUF); 357 else 358 *dmat = newtag; 359 return error; 360 } 361 362 int 363 bus_dma_tag_destroy(bus_dma_tag_t dmat) 364 { 365 if (dmat != NULL) { 366 if (dmat->map_count != 0) 367 return (EBUSY); 368 369 while (dmat != NULL) { 370 bus_dma_tag_t parent; 371 372 parent = dmat->parent; 373 dmat->ref_count--; 374 if (dmat->ref_count == 0) { 375 if (dmat->segments != NULL) 376 kfree(dmat->segments, M_DEVBUF); 377 kfree(dmat, M_DEVBUF); 378 /* 379 * Last reference count, so 380 * release our reference 381 * count on our parent. 382 */ 383 dmat = parent; 384 } else 385 dmat = NULL; 386 } 387 } 388 return (0); 389 } 390 391 bus_size_t 392 bus_dma_tag_getmaxsize(bus_dma_tag_t tag) 393 { 394 return(tag->maxsize); 395 } 396 397 /* 398 * Allocate a handle for mapping from kva/uva/physical 399 * address space into bus device space. 400 */ 401 int 402 bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) 403 { 404 int error; 405 406 error = 0; 407 408 if (dmat->segments == NULL) { 409 KKASSERT(dmat->nsegments && dmat->nsegments < 16384); 410 dmat->segments = kmalloc(sizeof(bus_dma_segment_t) * 411 dmat->nsegments, M_DEVBUF, M_INTWAIT); 412 } 413 414 if (dmat->flags & BUS_DMA_COULD_BOUNCE) { 415 struct bounce_zone *bz; 416 int maxpages; 417 418 /* Must bounce */ 419 420 if (dmat->bounce_zone == NULL) { 421 error = alloc_bounce_zone(dmat); 422 if (error) 423 return error; 424 } 425 bz = dmat->bounce_zone; 426 427 *mapp = kmalloc(sizeof(**mapp), M_DEVBUF, M_INTWAIT | M_ZERO); 428 429 /* Initialize the new map */ 430 STAILQ_INIT(&((*mapp)->bpages)); 431 432 /* 433 * Attempt to add pages to our pool on a per-instance 434 * basis up to a sane limit. 435 */ 436 if (dmat->flags & BUS_DMA_BOUNCE_ALIGN) { 437 maxpages = max_bounce_pages; 438 } else { 439 maxpages = MIN(max_bounce_pages, 440 Maxmem - atop(dmat->lowaddr)); 441 } 442 if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0 443 || (dmat->map_count > 0 444 && bz->total_bpages < maxpages)) { 445 int pages; 446 447 if (flags & BUS_DMA_ONEBPAGE) { 448 pages = 1; 449 } else { 450 pages = atop(round_page(dmat->maxsize)); 451 pages = MIN(maxpages - bz->total_bpages, pages); 452 pages = MAX(pages, 1); 453 } 454 if (alloc_bounce_pages(dmat, pages, flags) < pages) 455 error = ENOMEM; 456 457 if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0) { 458 if (!error) 459 dmat->flags |= BUS_DMA_MIN_ALLOC_COMP; 460 } else { 461 error = 0; 462 } 463 } 464 } else { 465 *mapp = NULL; 466 } 467 if (!error) 468 dmat->map_count++; 469 return error; 470 } 471 472 /* 473 * Destroy a handle for mapping from kva/uva/physical 474 * address space into bus device space. 475 */ 476 int 477 bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) 478 { 479 if (map != NULL) { 480 if (STAILQ_FIRST(&map->bpages) != NULL) 481 return (EBUSY); 482 kfree(map, M_DEVBUF); 483 } 484 dmat->map_count--; 485 return (0); 486 } 487 488 static __inline bus_size_t 489 check_kmalloc(bus_dma_tag_t dmat, const void *vaddr0, int verify) 490 { 491 bus_size_t maxsize = 0; 492 uintptr_t vaddr = (uintptr_t)vaddr0; 493 494 if ((vaddr ^ (vaddr + dmat->maxsize - 1)) & ~PAGE_MASK) { 495 if (verify || bootverbose) 496 kprintf("boundary check failed\n"); 497 if (verify) 498 print_backtrace(-1); /* XXX panic */ 499 maxsize = dmat->maxsize; 500 } 501 if (vaddr & (dmat->alignment - 1)) { 502 if (verify || bootverbose) 503 kprintf("alignment check failed\n"); 504 if (verify) 505 print_backtrace(-1); /* XXX panic */ 506 if (dmat->maxsize < dmat->alignment) 507 maxsize = dmat->alignment; 508 else 509 maxsize = dmat->maxsize; 510 } 511 return maxsize; 512 } 513 514 /* 515 * Allocate a piece of memory that can be efficiently mapped into 516 * bus device space based on the constraints lited in the dma tag. 517 * 518 * mapp is degenerate. By definition this allocation should not require 519 * bounce buffers so do not allocate a dma map. 520 */ 521 int 522 bus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddr, int flags, 523 bus_dmamap_t *mapp) 524 { 525 int mflags; 526 527 /* If we succeed, no mapping/bouncing will be required */ 528 *mapp = NULL; 529 530 if (dmat->segments == NULL) { 531 KKASSERT(dmat->nsegments < 16384); 532 dmat->segments = kmalloc(sizeof(bus_dma_segment_t) * 533 dmat->nsegments, M_DEVBUF, M_INTWAIT); 534 } 535 536 if (flags & BUS_DMA_NOWAIT) 537 mflags = M_NOWAIT; 538 else 539 mflags = M_WAITOK; 540 if (flags & BUS_DMA_ZERO) 541 mflags |= M_ZERO; 542 543 if (BUS_DMAMEM_KMALLOC(dmat)) { 544 bus_size_t maxsize; 545 546 *vaddr = kmalloc(dmat->maxsize, M_DEVBUF, mflags); 547 548 /* 549 * XXX 550 * Check whether the allocation 551 * - crossed a page boundary 552 * - was not aligned 553 * Retry with power-of-2 alignment in the above cases. 554 */ 555 maxsize = check_kmalloc(dmat, *vaddr, 0); 556 if (maxsize) { 557 size_t size; 558 559 kfree(*vaddr, M_DEVBUF); 560 /* XXX check for overflow? */ 561 for (size = 1; size <= maxsize; size <<= 1) 562 ; 563 *vaddr = kmalloc(size, M_DEVBUF, mflags); 564 check_kmalloc(dmat, *vaddr, 1); 565 } 566 } else { 567 /* 568 * XXX Use Contigmalloc until it is merged into this facility 569 * and handles multi-seg allocations. Nobody is doing 570 * multi-seg allocations yet though. 571 */ 572 *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags, 573 0ul, dmat->lowaddr, dmat->alignment, dmat->boundary); 574 } 575 if (*vaddr == NULL) 576 return (ENOMEM); 577 return (0); 578 } 579 580 /* 581 * Free a piece of memory and it's allociated dmamap, that was allocated 582 * via bus_dmamem_alloc. Make the same choice for free/contigfree. 583 */ 584 void 585 bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) 586 { 587 /* 588 * dmamem does not need to be bounced, so the map should be 589 * NULL 590 */ 591 if (map != NULL) 592 panic("bus_dmamem_free: Invalid map freed\n"); 593 if (BUS_DMAMEM_KMALLOC(dmat)) 594 kfree(vaddr, M_DEVBUF); 595 else 596 contigfree(vaddr, dmat->maxsize, M_DEVBUF); 597 } 598 599 static __inline vm_paddr_t 600 _bus_dma_extract(pmap_t pmap, vm_offset_t vaddr) 601 { 602 if (pmap) 603 return pmap_extract(pmap, vaddr); 604 else 605 return pmap_kextract(vaddr); 606 } 607 608 /* 609 * Utility function to load a linear buffer. lastaddrp holds state 610 * between invocations (for multiple-buffer loads). segp contains 611 * the segment following the starting one on entrace, and the ending 612 * segment on exit. first indicates if this is the first invocation 613 * of this function. 614 */ 615 static int 616 _bus_dmamap_load_buffer(bus_dma_tag_t dmat, 617 bus_dmamap_t map, 618 void *buf, bus_size_t buflen, 619 bus_dma_segment_t *segments, 620 int nsegments, 621 pmap_t pmap, 622 int flags, 623 vm_paddr_t *lastpaddrp, 624 int *segp, 625 int first) 626 { 627 vm_offset_t vaddr; 628 vm_paddr_t paddr, nextpaddr; 629 bus_dma_segment_t *sg; 630 bus_addr_t bmask; 631 int seg, error = 0; 632 633 if (map == NULL) 634 map = &nobounce_dmamap; 635 636 #ifdef INVARIANTS 637 if (dmat->flags & BUS_DMA_ALIGNED) 638 KKASSERT(((uintptr_t)buf & (dmat->alignment - 1)) == 0); 639 #endif 640 641 /* 642 * If we are being called during a callback, pagesneeded will 643 * be non-zero, so we can avoid doing the work twice. 644 */ 645 if ((dmat->flags & BUS_DMA_COULD_BOUNCE) && 646 map != &nobounce_dmamap && map->pagesneeded == 0) { 647 vm_offset_t vendaddr; 648 649 /* 650 * Count the number of bounce pages 651 * needed in order to complete this transfer 652 */ 653 vaddr = (vm_offset_t)buf; 654 vendaddr = (vm_offset_t)buf + buflen; 655 656 while (vaddr < vendaddr) { 657 paddr = _bus_dma_extract(pmap, vaddr); 658 if (run_filter(dmat, paddr) != 0) 659 map->pagesneeded++; 660 vaddr += (PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK)); 661 } 662 } 663 664 /* Reserve Necessary Bounce Pages */ 665 if (map->pagesneeded != 0) { 666 struct bounce_zone *bz; 667 668 bz = dmat->bounce_zone; 669 BZ_LOCK(bz); 670 if (flags & BUS_DMA_NOWAIT) { 671 if (reserve_bounce_pages(dmat, map, 0) != 0) { 672 BZ_UNLOCK(bz); 673 error = ENOMEM; 674 goto free_bounce; 675 } 676 } else { 677 if (reserve_bounce_pages(dmat, map, 1) != 0) { 678 /* Queue us for resources */ 679 map->dmat = dmat; 680 map->buf = buf; 681 map->buflen = buflen; 682 683 STAILQ_INSERT_TAIL( 684 &dmat->bounce_zone->bounce_map_waitinglist, 685 map, links); 686 BZ_UNLOCK(bz); 687 688 return (EINPROGRESS); 689 } 690 } 691 BZ_UNLOCK(bz); 692 } 693 694 KKASSERT(*segp >= 1 && *segp <= nsegments); 695 seg = *segp; 696 sg = &segments[seg - 1]; 697 698 vaddr = (vm_offset_t)buf; 699 nextpaddr = *lastpaddrp; 700 bmask = ~(dmat->boundary - 1); /* note: will be 0 if boundary is 0 */ 701 702 /* force at least one segment */ 703 do { 704 bus_size_t size; 705 706 /* 707 * Per-page main loop 708 */ 709 paddr = _bus_dma_extract(pmap, vaddr); 710 size = PAGE_SIZE - (paddr & PAGE_MASK); 711 if (size > buflen) 712 size = buflen; 713 if (map->pagesneeded != 0 && run_filter(dmat, paddr)) { 714 /* 715 * note: this paddr has the same in-page offset 716 * as vaddr and thus the paddr above, so the 717 * size does not have to be recalculated 718 */ 719 paddr = add_bounce_page(dmat, map, vaddr, size); 720 } 721 722 /* 723 * Fill in the bus_dma_segment 724 */ 725 if (first) { 726 sg->ds_addr = paddr; 727 sg->ds_len = size; 728 first = 0; 729 } else if (paddr == nextpaddr) { 730 sg->ds_len += size; 731 } else { 732 sg++; 733 seg++; 734 if (seg > nsegments) 735 break; 736 sg->ds_addr = paddr; 737 sg->ds_len = size; 738 } 739 nextpaddr = paddr + size; 740 741 /* 742 * Handle maxsegsz and boundary issues with a nested loop 743 */ 744 for (;;) { 745 bus_size_t tmpsize; 746 747 /* 748 * Limit to the boundary and maximum segment size 749 */ 750 if (((nextpaddr - 1) ^ sg->ds_addr) & bmask) { 751 tmpsize = dmat->boundary - 752 (sg->ds_addr & ~bmask); 753 if (tmpsize > dmat->maxsegsz) 754 tmpsize = dmat->maxsegsz; 755 KKASSERT(tmpsize < sg->ds_len); 756 } else if (sg->ds_len > dmat->maxsegsz) { 757 tmpsize = dmat->maxsegsz; 758 } else { 759 break; 760 } 761 762 /* 763 * Futz, split the data into a new segment. 764 */ 765 if (seg >= nsegments) 766 goto fail; 767 sg[1].ds_len = sg[0].ds_len - tmpsize; 768 sg[1].ds_addr = sg[0].ds_addr + tmpsize; 769 sg[0].ds_len = tmpsize; 770 sg++; 771 seg++; 772 } 773 774 /* 775 * Adjust for loop 776 */ 777 buflen -= size; 778 vaddr += size; 779 } while (buflen > 0); 780 fail: 781 if (buflen != 0) 782 error = EFBIG; 783 784 *segp = seg; 785 *lastpaddrp = nextpaddr; 786 787 free_bounce: 788 if (error && (dmat->flags & BUS_DMA_COULD_BOUNCE) && 789 map != &nobounce_dmamap) { 790 _bus_dmamap_unload(dmat, map); 791 return_bounce_pages(dmat, map); 792 } 793 return error; 794 } 795 796 /* 797 * Map the buffer buf into bus space using the dmamap map. 798 */ 799 int 800 bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, 801 bus_size_t buflen, bus_dmamap_callback_t *callback, 802 void *callback_arg, int flags) 803 { 804 bus_dma_segment_t cache_segments[BUS_DMA_CACHE_SEGMENTS]; 805 bus_dma_segment_t *segments; 806 vm_paddr_t lastaddr = 0; 807 int error, nsegs = 1; 808 809 if (map != NULL) { 810 /* 811 * XXX 812 * Follow old semantics. Once all of the callers are fixed, 813 * we should get rid of these internal flag "adjustment". 814 */ 815 flags &= ~BUS_DMA_NOWAIT; 816 flags |= BUS_DMA_WAITOK; 817 818 map->callback = callback; 819 map->callback_arg = callback_arg; 820 } 821 822 segments = bus_dma_tag_lock(dmat, cache_segments); 823 error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, 824 segments, dmat->nsegments, 825 NULL, flags, &lastaddr, &nsegs, 1); 826 if (error == EINPROGRESS) { 827 bus_dma_tag_unlock(dmat); 828 return error; 829 } 830 callback(callback_arg, segments, nsegs, error); 831 bus_dma_tag_unlock(dmat); 832 return 0; 833 } 834 835 /* 836 * Like _bus_dmamap_load(), but for mbufs. 837 */ 838 int 839 bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, 840 struct mbuf *m0, 841 bus_dmamap_callback2_t *callback, void *callback_arg, 842 int flags) 843 { 844 bus_dma_segment_t cache_segments[BUS_DMA_CACHE_SEGMENTS]; 845 bus_dma_segment_t *segments; 846 int nsegs, error; 847 848 /* 849 * XXX 850 * Follow old semantics. Once all of the callers are fixed, 851 * we should get rid of these internal flag "adjustment". 852 */ 853 flags &= ~BUS_DMA_WAITOK; 854 flags |= BUS_DMA_NOWAIT; 855 856 segments = bus_dma_tag_lock(dmat, cache_segments); 857 error = bus_dmamap_load_mbuf_segment(dmat, map, m0, 858 segments, dmat->nsegments, &nsegs, flags); 859 if (error) { 860 /* force "no valid mappings" in callback */ 861 callback(callback_arg, segments, 0, 862 0, error); 863 } else { 864 callback(callback_arg, segments, nsegs, 865 m0->m_pkthdr.len, error); 866 } 867 bus_dma_tag_unlock(dmat); 868 return error; 869 } 870 871 int 872 bus_dmamap_load_mbuf_segment(bus_dma_tag_t dmat, bus_dmamap_t map, 873 struct mbuf *m0, 874 bus_dma_segment_t *segs, int maxsegs, 875 int *nsegs, int flags) 876 { 877 int error; 878 879 M_ASSERTPKTHDR(m0); 880 881 KASSERT(maxsegs >= 1, ("invalid maxsegs %d\n", maxsegs)); 882 KASSERT(maxsegs <= dmat->nsegments, 883 ("%d too many segments, dmat only support %d segments\n", 884 maxsegs, dmat->nsegments)); 885 KASSERT(flags & BUS_DMA_NOWAIT, 886 ("only BUS_DMA_NOWAIT is supported\n")); 887 888 if (m0->m_pkthdr.len <= dmat->maxsize) { 889 int first = 1; 890 vm_paddr_t lastaddr = 0; 891 struct mbuf *m; 892 893 *nsegs = 1; 894 error = 0; 895 for (m = m0; m != NULL && error == 0; m = m->m_next) { 896 if (m->m_len == 0) 897 continue; 898 899 error = _bus_dmamap_load_buffer(dmat, map, 900 m->m_data, m->m_len, 901 segs, maxsegs, 902 NULL, flags, &lastaddr, 903 nsegs, first); 904 if (error == ENOMEM && !first) { 905 /* 906 * Out of bounce pages due to too many 907 * fragments in the mbuf chain; return 908 * EFBIG instead. 909 */ 910 error = EFBIG; 911 } 912 first = 0; 913 } 914 #ifdef INVARIANTS 915 if (!error) 916 KKASSERT(*nsegs <= maxsegs && *nsegs >= 1); 917 #endif 918 } else { 919 *nsegs = 0; 920 error = EINVAL; 921 } 922 KKASSERT(error != EINPROGRESS); 923 return error; 924 } 925 926 /* 927 * Like _bus_dmamap_load(), but for uios. 928 */ 929 int 930 bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, 931 struct uio *uio, 932 bus_dmamap_callback2_t *callback, void *callback_arg, 933 int flags) 934 { 935 vm_paddr_t lastaddr; 936 int nsegs, error, first, i; 937 bus_size_t resid; 938 struct iovec *iov; 939 pmap_t pmap; 940 bus_dma_segment_t cache_segments[BUS_DMA_CACHE_SEGMENTS]; 941 bus_dma_segment_t *segments; 942 bus_dma_segment_t *segs; 943 int nsegs_left; 944 945 if (dmat->nsegments <= BUS_DMA_CACHE_SEGMENTS) 946 segments = cache_segments; 947 else 948 segments = kmalloc(sizeof(bus_dma_segment_t) * dmat->nsegments, 949 M_DEVBUF, M_WAITOK | M_ZERO); 950 951 /* 952 * XXX 953 * Follow old semantics. Once all of the callers are fixed, 954 * we should get rid of these internal flag "adjustment". 955 */ 956 flags &= ~BUS_DMA_WAITOK; 957 flags |= BUS_DMA_NOWAIT; 958 959 resid = (bus_size_t)uio->uio_resid; 960 iov = uio->uio_iov; 961 962 segs = segments; 963 nsegs_left = dmat->nsegments; 964 965 if (uio->uio_segflg == UIO_USERSPACE) { 966 struct thread *td; 967 968 td = uio->uio_td; 969 KASSERT(td != NULL && td->td_proc != NULL, 970 ("bus_dmamap_load_uio: USERSPACE but no proc")); 971 pmap = vmspace_pmap(td->td_proc->p_vmspace); 972 } else { 973 pmap = NULL; 974 } 975 976 error = 0; 977 nsegs = 1; 978 first = 1; 979 lastaddr = 0; 980 for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { 981 /* 982 * Now at the first iovec to load. Load each iovec 983 * until we have exhausted the residual count. 984 */ 985 bus_size_t minlen = 986 resid < iov[i].iov_len ? resid : iov[i].iov_len; 987 caddr_t addr = (caddr_t) iov[i].iov_base; 988 989 error = _bus_dmamap_load_buffer(dmat, map, addr, minlen, 990 segs, nsegs_left, 991 pmap, flags, &lastaddr, &nsegs, first); 992 first = 0; 993 994 resid -= minlen; 995 if (error == 0) { 996 nsegs_left -= nsegs; 997 segs += nsegs; 998 } 999 } 1000 1001 /* 1002 * Minimum one DMA segment, even if 0-length buffer. 1003 */ 1004 if (nsegs_left == dmat->nsegments) 1005 --nsegs_left; 1006 1007 if (error) { 1008 /* force "no valid mappings" in callback */ 1009 callback(callback_arg, segments, 0, 1010 0, error); 1011 } else { 1012 callback(callback_arg, segments, dmat->nsegments - nsegs_left, 1013 (bus_size_t)uio->uio_resid, error); 1014 } 1015 if (dmat->nsegments > BUS_DMA_CACHE_SEGMENTS) 1016 kfree(segments, M_DEVBUF); 1017 return error; 1018 } 1019 1020 /* 1021 * Release the mapping held by map. 1022 */ 1023 void 1024 _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) 1025 { 1026 struct bounce_page *bpage; 1027 1028 while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) { 1029 STAILQ_REMOVE_HEAD(&map->bpages, links); 1030 free_bounce_page(dmat, bpage); 1031 } 1032 } 1033 1034 void 1035 _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) 1036 { 1037 struct bounce_page *bpage; 1038 1039 if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) { 1040 /* 1041 * Handle data bouncing. We might also 1042 * want to add support for invalidating 1043 * the caches on broken hardware 1044 */ 1045 switch (op) { 1046 case BUS_DMASYNC_PREWRITE: 1047 while (bpage != NULL) { 1048 bcopy((void *)bpage->datavaddr, 1049 (void *)bpage->vaddr, 1050 bpage->datacount); 1051 bpage = STAILQ_NEXT(bpage, links); 1052 } 1053 dmat->bounce_zone->total_bounced++; 1054 break; 1055 1056 case BUS_DMASYNC_POSTREAD: 1057 while (bpage != NULL) { 1058 bcopy((void *)bpage->vaddr, 1059 (void *)bpage->datavaddr, 1060 bpage->datacount); 1061 bpage = STAILQ_NEXT(bpage, links); 1062 } 1063 dmat->bounce_zone->total_bounced++; 1064 break; 1065 1066 case BUS_DMASYNC_PREREAD: 1067 case BUS_DMASYNC_POSTWRITE: 1068 /* No-ops */ 1069 break; 1070 } 1071 } 1072 } 1073 1074 static int 1075 alloc_bounce_zone(bus_dma_tag_t dmat) 1076 { 1077 struct bounce_zone *bz, *new_bz; 1078 1079 KASSERT(dmat->bounce_zone == NULL, 1080 ("bounce zone was already assigned\n")); 1081 1082 new_bz = kmalloc(sizeof(*new_bz), M_DEVBUF, M_INTWAIT | M_ZERO); 1083 1084 lwkt_gettoken(&bounce_zone_tok); 1085 1086 /* Check to see if we already have a suitable zone */ 1087 STAILQ_FOREACH(bz, &bounce_zone_list, links) { 1088 if (dmat->alignment <= bz->alignment && 1089 dmat->lowaddr >= bz->lowaddr) { 1090 lwkt_reltoken(&bounce_zone_tok); 1091 1092 dmat->bounce_zone = bz; 1093 kfree(new_bz, M_DEVBUF); 1094 return 0; 1095 } 1096 } 1097 bz = new_bz; 1098 1099 #ifdef SMP 1100 spin_init(&bz->spin); 1101 #endif 1102 STAILQ_INIT(&bz->bounce_page_list); 1103 STAILQ_INIT(&bz->bounce_map_waitinglist); 1104 bz->free_bpages = 0; 1105 bz->reserved_bpages = 0; 1106 bz->active_bpages = 0; 1107 bz->lowaddr = dmat->lowaddr; 1108 bz->alignment = round_page(dmat->alignment); 1109 ksnprintf(bz->zoneid, 8, "zone%d", busdma_zonecount); 1110 busdma_zonecount++; 1111 ksnprintf(bz->lowaddrid, 18, "%#jx", (uintmax_t)bz->lowaddr); 1112 STAILQ_INSERT_TAIL(&bounce_zone_list, bz, links); 1113 1114 lwkt_reltoken(&bounce_zone_tok); 1115 1116 dmat->bounce_zone = bz; 1117 1118 sysctl_ctx_init(&bz->sysctl_ctx); 1119 bz->sysctl_tree = SYSCTL_ADD_NODE(&bz->sysctl_ctx, 1120 SYSCTL_STATIC_CHILDREN(_hw_busdma), OID_AUTO, bz->zoneid, 1121 CTLFLAG_RD, 0, ""); 1122 if (bz->sysctl_tree == NULL) { 1123 sysctl_ctx_free(&bz->sysctl_ctx); 1124 return 0; /* XXX error code? */ 1125 } 1126 1127 SYSCTL_ADD_INT(&bz->sysctl_ctx, 1128 SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO, 1129 "total_bpages", CTLFLAG_RD, &bz->total_bpages, 0, 1130 "Total bounce pages"); 1131 SYSCTL_ADD_INT(&bz->sysctl_ctx, 1132 SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO, 1133 "free_bpages", CTLFLAG_RD, &bz->free_bpages, 0, 1134 "Free bounce pages"); 1135 SYSCTL_ADD_INT(&bz->sysctl_ctx, 1136 SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO, 1137 "reserved_bpages", CTLFLAG_RD, &bz->reserved_bpages, 0, 1138 "Reserved bounce pages"); 1139 SYSCTL_ADD_INT(&bz->sysctl_ctx, 1140 SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO, 1141 "active_bpages", CTLFLAG_RD, &bz->active_bpages, 0, 1142 "Active bounce pages"); 1143 SYSCTL_ADD_INT(&bz->sysctl_ctx, 1144 SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO, 1145 "total_bounced", CTLFLAG_RD, &bz->total_bounced, 0, 1146 "Total bounce requests"); 1147 SYSCTL_ADD_INT(&bz->sysctl_ctx, 1148 SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO, 1149 "total_deferred", CTLFLAG_RD, &bz->total_deferred, 0, 1150 "Total bounce requests that were deferred"); 1151 SYSCTL_ADD_INT(&bz->sysctl_ctx, 1152 SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO, 1153 "reserve_failed", CTLFLAG_RD, &bz->reserve_failed, 0, 1154 "Total bounce page reservations that were failed"); 1155 SYSCTL_ADD_STRING(&bz->sysctl_ctx, 1156 SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO, 1157 "lowaddr", CTLFLAG_RD, bz->lowaddrid, 0, ""); 1158 SYSCTL_ADD_INT(&bz->sysctl_ctx, 1159 SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO, 1160 "alignment", CTLFLAG_RD, &bz->alignment, 0, ""); 1161 1162 return 0; 1163 } 1164 1165 static int 1166 alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages, int flags) 1167 { 1168 struct bounce_zone *bz = dmat->bounce_zone; 1169 int count = 0, mflags; 1170 1171 if (flags & BUS_DMA_NOWAIT) 1172 mflags = M_NOWAIT; 1173 else 1174 mflags = M_WAITOK; 1175 1176 while (numpages > 0) { 1177 struct bounce_page *bpage; 1178 1179 bpage = kmalloc(sizeof(*bpage), M_DEVBUF, M_INTWAIT | M_ZERO); 1180 1181 bpage->vaddr = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF, 1182 mflags, 0ul, 1183 bz->lowaddr, 1184 bz->alignment, 0); 1185 if (bpage->vaddr == 0) { 1186 kfree(bpage, M_DEVBUF); 1187 break; 1188 } 1189 bpage->busaddr = pmap_kextract(bpage->vaddr); 1190 1191 BZ_LOCK(bz); 1192 STAILQ_INSERT_TAIL(&bz->bounce_page_list, bpage, links); 1193 total_bounce_pages++; 1194 bz->total_bpages++; 1195 bz->free_bpages++; 1196 BZ_UNLOCK(bz); 1197 1198 count++; 1199 numpages--; 1200 } 1201 return count; 1202 } 1203 1204 /* Assume caller holds bounce zone spinlock */ 1205 static int 1206 reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit) 1207 { 1208 struct bounce_zone *bz = dmat->bounce_zone; 1209 int pages; 1210 1211 pages = MIN(bz->free_bpages, map->pagesneeded - map->pagesreserved); 1212 if (!commit && map->pagesneeded > (map->pagesreserved + pages)) { 1213 bz->reserve_failed++; 1214 return (map->pagesneeded - (map->pagesreserved + pages)); 1215 } 1216 1217 bz->free_bpages -= pages; 1218 1219 bz->reserved_bpages += pages; 1220 KKASSERT(bz->reserved_bpages <= bz->total_bpages); 1221 1222 map->pagesreserved += pages; 1223 pages = map->pagesneeded - map->pagesreserved; 1224 1225 return pages; 1226 } 1227 1228 static void 1229 return_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map) 1230 { 1231 struct bounce_zone *bz = dmat->bounce_zone; 1232 int reserved = map->pagesreserved; 1233 bus_dmamap_t wait_map; 1234 1235 map->pagesreserved = 0; 1236 map->pagesneeded = 0; 1237 1238 if (reserved == 0) 1239 return; 1240 1241 BZ_LOCK(bz); 1242 1243 bz->free_bpages += reserved; 1244 KKASSERT(bz->free_bpages <= bz->total_bpages); 1245 1246 KKASSERT(bz->reserved_bpages >= reserved); 1247 bz->reserved_bpages -= reserved; 1248 1249 wait_map = get_map_waiting(dmat); 1250 1251 BZ_UNLOCK(bz); 1252 1253 if (wait_map != NULL) 1254 add_map_callback(map); 1255 } 1256 1257 static bus_addr_t 1258 add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, 1259 bus_size_t size) 1260 { 1261 struct bounce_zone *bz = dmat->bounce_zone; 1262 struct bounce_page *bpage; 1263 1264 KASSERT(map->pagesneeded > 0, ("map doesn't need any pages")); 1265 map->pagesneeded--; 1266 1267 KASSERT(map->pagesreserved > 0, ("map doesn't reserve any pages")); 1268 map->pagesreserved--; 1269 1270 BZ_LOCK(bz); 1271 1272 bpage = STAILQ_FIRST(&bz->bounce_page_list); 1273 KASSERT(bpage != NULL, ("free page list is empty")); 1274 STAILQ_REMOVE_HEAD(&bz->bounce_page_list, links); 1275 1276 KKASSERT(bz->reserved_bpages > 0); 1277 bz->reserved_bpages--; 1278 1279 bz->active_bpages++; 1280 KKASSERT(bz->active_bpages <= bz->total_bpages); 1281 1282 BZ_UNLOCK(bz); 1283 1284 bpage->datavaddr = vaddr; 1285 bpage->datacount = size; 1286 STAILQ_INSERT_TAIL(&map->bpages, bpage, links); 1287 return bpage->busaddr; 1288 } 1289 1290 static void 1291 free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage) 1292 { 1293 struct bounce_zone *bz = dmat->bounce_zone; 1294 bus_dmamap_t map; 1295 1296 bpage->datavaddr = 0; 1297 bpage->datacount = 0; 1298 1299 BZ_LOCK(bz); 1300 1301 STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links); 1302 1303 bz->free_bpages++; 1304 KKASSERT(bz->free_bpages <= bz->total_bpages); 1305 1306 KKASSERT(bz->active_bpages > 0); 1307 bz->active_bpages--; 1308 1309 map = get_map_waiting(dmat); 1310 1311 BZ_UNLOCK(bz); 1312 1313 if (map != NULL) 1314 add_map_callback(map); 1315 } 1316 1317 /* Assume caller holds bounce zone spinlock */ 1318 static bus_dmamap_t 1319 get_map_waiting(bus_dma_tag_t dmat) 1320 { 1321 struct bounce_zone *bz = dmat->bounce_zone; 1322 bus_dmamap_t map; 1323 1324 map = STAILQ_FIRST(&bz->bounce_map_waitinglist); 1325 if (map != NULL) { 1326 if (reserve_bounce_pages(map->dmat, map, 1) == 0) { 1327 STAILQ_REMOVE_HEAD(&bz->bounce_map_waitinglist, links); 1328 bz->total_deferred++; 1329 } else { 1330 map = NULL; 1331 } 1332 } 1333 return map; 1334 } 1335 1336 static void 1337 add_map_callback(bus_dmamap_t map) 1338 { 1339 spin_lock(&bounce_map_list_spin); 1340 STAILQ_INSERT_TAIL(&bounce_map_callbacklist, map, links); 1341 busdma_swi_pending = 1; 1342 setsoftvm(); 1343 spin_unlock(&bounce_map_list_spin); 1344 } 1345 1346 void 1347 busdma_swi(void) 1348 { 1349 bus_dmamap_t map; 1350 1351 spin_lock(&bounce_map_list_spin); 1352 while ((map = STAILQ_FIRST(&bounce_map_callbacklist)) != NULL) { 1353 STAILQ_REMOVE_HEAD(&bounce_map_callbacklist, links); 1354 spin_unlock(&bounce_map_list_spin); 1355 bus_dmamap_load(map->dmat, map, map->buf, map->buflen, 1356 map->callback, map->callback_arg, /*flags*/0); 1357 spin_lock(&bounce_map_list_spin); 1358 } 1359 spin_unlock(&bounce_map_list_spin); 1360 } 1361