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