busdma_bounce.c (134934) | busdma_bounce.c (136805) |
---|---|
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 --- 11 unchanged lines hidden (view full) --- 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 27#include <sys/cdefs.h> | 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 --- 11 unchanged lines hidden (view full) --- 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 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/i386/i386/busdma_machdep.c 134934 2004-09-08 04:54:19Z scottl $"); | 28__FBSDID("$FreeBSD: head/sys/i386/i386/busdma_machdep.c 136805 2004-10-23 10:34:27Z rwatson $"); |
29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/malloc.h> 33#include <sys/bus.h> 34#include <sys/interrupt.h> 35#include <sys/kernel.h> | 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/malloc.h> 33#include <sys/bus.h> 34#include <sys/interrupt.h> 35#include <sys/kernel.h> |
36#include <sys/ktr.h> |
|
36#include <sys/lock.h> 37#include <sys/proc.h> 38#include <sys/mutex.h> 39#include <sys/mbuf.h> 40#include <sys/uio.h> 41#include <sys/sysctl.h> 42 43#include <vm/vm.h> --- 169 unchanged lines hidden (view full) --- 213 /* Basic sanity checking */ 214 if (boundary != 0 && boundary < maxsegsz) 215 maxsegsz = boundary; 216 217 /* Return a NULL tag on failure */ 218 *dmat = NULL; 219 220 newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, M_NOWAIT); | 37#include <sys/lock.h> 38#include <sys/proc.h> 39#include <sys/mutex.h> 40#include <sys/mbuf.h> 41#include <sys/uio.h> 42#include <sys/sysctl.h> 43 44#include <vm/vm.h> --- 169 unchanged lines hidden (view full) --- 214 /* Basic sanity checking */ 215 if (boundary != 0 && boundary < maxsegsz) 216 maxsegsz = boundary; 217 218 /* Return a NULL tag on failure */ 219 *dmat = NULL; 220 221 newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, M_NOWAIT); |
221 if (newtag == NULL) | 222 if (newtag == NULL) { 223 CTR3(KTR_BUSDMA, "bus_dma_tag_create returned tag %p tag " 224 "flags 0x%x error %d", newtag, 0, error); |
222 return (ENOMEM); | 225 return (ENOMEM); |
226 } |
|
223 224 newtag->parent = parent; 225 newtag->alignment = alignment; 226 newtag->boundary = boundary; 227 newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1); 228 newtag->highaddr = trunc_page((vm_paddr_t)highaddr) + 229 (PAGE_SIZE - 1); 230 newtag->filter = filter; --- 60 unchanged lines hidden (view full) --- 291 newtag->flags |= BUS_DMA_MIN_ALLOC_COMP; 292 } 293 294 if (error != 0) { 295 free(newtag, M_DEVBUF); 296 } else { 297 *dmat = newtag; 298 } | 227 228 newtag->parent = parent; 229 newtag->alignment = alignment; 230 newtag->boundary = boundary; 231 newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1); 232 newtag->highaddr = trunc_page((vm_paddr_t)highaddr) + 233 (PAGE_SIZE - 1); 234 newtag->filter = filter; --- 60 unchanged lines hidden (view full) --- 295 newtag->flags |= BUS_DMA_MIN_ALLOC_COMP; 296 } 297 298 if (error != 0) { 299 free(newtag, M_DEVBUF); 300 } else { 301 *dmat = newtag; 302 } |
303 CTR3(KTR_BUSDMA, "bus_dma_tag_create returned tag %p tag flags 0x%x " 304 "error %d", newtag, (newtag != NULL ? newtag->flags : 0), error); |
|
299 return (error); 300} 301 302int 303bus_dma_tag_destroy(bus_dma_tag_t dmat) 304{ | 305 return (error); 306} 307 308int 309bus_dma_tag_destroy(bus_dma_tag_t dmat) 310{ |
311 bus_dma_tag_t dmat_copy; 312 int error; 313 314 error = 0; 315 dmat_copy = dmat; 316 |
|
305 if (dmat != NULL) { 306 | 317 if (dmat != NULL) { 318 |
307 if (dmat->map_count != 0) 308 return (EBUSY); | 319 if (dmat->map_count != 0) { 320 error = EBUSY; 321 goto out; 322 } |
309 310 while (dmat != NULL) { 311 bus_dma_tag_t parent; 312 313 parent = dmat->parent; 314 atomic_subtract_int(&dmat->ref_count, 1); 315 if (dmat->ref_count == 0) { 316 if (dmat->segments != NULL) --- 4 unchanged lines hidden (view full) --- 321 * release our reference 322 * count on our parent. 323 */ 324 dmat = parent; 325 } else 326 dmat = NULL; 327 } 328 } | 323 324 while (dmat != NULL) { 325 bus_dma_tag_t parent; 326 327 parent = dmat->parent; 328 atomic_subtract_int(&dmat->ref_count, 1); 329 if (dmat->ref_count == 0) { 330 if (dmat->segments != NULL) --- 4 unchanged lines hidden (view full) --- 335 * release our reference 336 * count on our parent. 337 */ 338 dmat = parent; 339 } else 340 dmat = NULL; 341 } 342 } |
329 return (0); | 343out: 344 CTR2(KTR_BUSDMA, "bus_dma_tag_destroy tag %p error %d", dmat_copy, 345 error); 346 return (error); |
330} 331 332/* 333 * Allocate a handle for mapping from kva/uva/physical 334 * address space into bus device space. 335 */ 336int 337bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) 338{ 339 int error; 340 341 error = 0; 342 343 if (dmat->segments == NULL) { 344 dmat->segments = (bus_dma_segment_t *)malloc( 345 sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, 346 M_NOWAIT); | 347} 348 349/* 350 * Allocate a handle for mapping from kva/uva/physical 351 * address space into bus device space. 352 */ 353int 354bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) 355{ 356 int error; 357 358 error = 0; 359 360 if (dmat->segments == NULL) { 361 dmat->segments = (bus_dma_segment_t *)malloc( 362 sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, 363 M_NOWAIT); |
347 if (dmat->segments == NULL) | 364 if (dmat->segments == NULL) { 365 CTR2(KTR_BUSDMA, "bus_dmamap_create: tag %p error %d", 366 dmat, ENOMEM); |
348 return (ENOMEM); | 367 return (ENOMEM); |
368 } |
|
349 } 350 351 /* 352 * Bouncing might be required if the driver asks for an active 353 * exclusion region, a data alignment that is stricter than 1, and/or 354 * an active address boundary. 355 */ 356 if (dmat->lowaddr < ptoa((vm_paddr_t)Maxmem) 357 || dmat->alignment > 1 || dmat->boundary > 0) { 358 /* Must bounce */ 359 int maxpages; 360 361 *mapp = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF, 362 M_NOWAIT | M_ZERO); | 369 } 370 371 /* 372 * Bouncing might be required if the driver asks for an active 373 * exclusion region, a data alignment that is stricter than 1, and/or 374 * an active address boundary. 375 */ 376 if (dmat->lowaddr < ptoa((vm_paddr_t)Maxmem) 377 || dmat->alignment > 1 || dmat->boundary > 0) { 378 /* Must bounce */ 379 int maxpages; 380 381 *mapp = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF, 382 M_NOWAIT | M_ZERO); |
363 if (*mapp == NULL) | 383 if (*mapp == NULL) { 384 CTR2(KTR_BUSDMA, "bus_dmamap_create: tag %p error %d", 385 dmat, ENOMEM); |
364 return (ENOMEM); | 386 return (ENOMEM); |
387 } |
|
365 366 /* Initialize the new map */ 367 STAILQ_INIT(&((*mapp)->bpages)); 368 369 /* 370 * Attempt to add pages to our pool on a per-instance 371 * basis up to a sane limit. 372 */ --- 22 unchanged lines hidden (view full) --- 395 error = 0; 396 } 397 } 398 } else { 399 *mapp = NULL; 400 } 401 if (error == 0) 402 dmat->map_count++; | 388 389 /* Initialize the new map */ 390 STAILQ_INIT(&((*mapp)->bpages)); 391 392 /* 393 * Attempt to add pages to our pool on a per-instance 394 * basis up to a sane limit. 395 */ --- 22 unchanged lines hidden (view full) --- 418 error = 0; 419 } 420 } 421 } else { 422 *mapp = NULL; 423 } 424 if (error == 0) 425 dmat->map_count++; |
426 CTR3(KTR_BUSDMA, "bus_dmamap_create: tag %p tag flags 0x%x error %d", 427 dmat, dmat->flags, error); |
|
403 return (error); 404} 405 406/* 407 * Destroy a handle for mapping from kva/uva/physical 408 * address space into bus device space. 409 */ 410int 411bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) 412{ 413 if (map != NULL && map != &nobounce_dmamap) { | 428 return (error); 429} 430 431/* 432 * Destroy a handle for mapping from kva/uva/physical 433 * address space into bus device space. 434 */ 435int 436bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) 437{ 438 if (map != NULL && map != &nobounce_dmamap) { |
414 if (STAILQ_FIRST(&map->bpages) != NULL) | 439 if (STAILQ_FIRST(&map->bpages) != NULL) { 440 CTR2(KTR_BUSDMA, "bus_dmamap_destroy: tag %p error %d", 441 dmat, EBUSY); |
415 return (EBUSY); | 442 return (EBUSY); |
443 } |
|
416 free(map, M_DEVBUF); 417 } 418 dmat->map_count--; | 444 free(map, M_DEVBUF); 445 } 446 dmat->map_count--; |
447 CTR1(KTR_BUSDMA, "bus_dmamap_destroy: tag %p error 0", dmat); |
|
419 return (0); 420} 421 422 423/* 424 * Allocate a piece of memory that can be efficiently mapped into 425 * bus device space based on the constraints lited in the dma tag. 426 * A dmamap to for use with dmamap_load is also allocated. --- 13 unchanged lines hidden (view full) --- 440 441 /* If we succeed, no mapping/bouncing will be required */ 442 *mapp = NULL; 443 444 if (dmat->segments == NULL) { 445 dmat->segments = (bus_dma_segment_t *)malloc( 446 sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, 447 M_NOWAIT); | 448 return (0); 449} 450 451 452/* 453 * Allocate a piece of memory that can be efficiently mapped into 454 * bus device space based on the constraints lited in the dma tag. 455 * A dmamap to for use with dmamap_load is also allocated. --- 13 unchanged lines hidden (view full) --- 469 470 /* If we succeed, no mapping/bouncing will be required */ 471 *mapp = NULL; 472 473 if (dmat->segments == NULL) { 474 dmat->segments = (bus_dma_segment_t *)malloc( 475 sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, 476 M_NOWAIT); |
448 if (dmat->segments == NULL) | 477 if (dmat->segments == NULL) { 478 CTR3(KTR_BUSDMA, "bus_dmamem_alloc: tag %p tag " 479 "flags 0x%x error %d", dmat, dmat->flags, ENOMEM); |
449 return (ENOMEM); | 480 return (ENOMEM); |
481 } |
|
450 } 451 452 if ((dmat->maxsize <= PAGE_SIZE) && 453 dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) { 454 *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags); 455 } else { 456 /* 457 * XXX Use Contigmalloc until it is merged into this facility 458 * and handles multi-seg allocations. Nobody is doing 459 * multi-seg allocations yet though. 460 * XXX Certain AGP hardware does. 461 */ 462 *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags, 463 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul, 464 dmat->boundary); 465 } | 482 } 483 484 if ((dmat->maxsize <= PAGE_SIZE) && 485 dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) { 486 *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags); 487 } else { 488 /* 489 * XXX Use Contigmalloc until it is merged into this facility 490 * and handles multi-seg allocations. Nobody is doing 491 * multi-seg allocations yet though. 492 * XXX Certain AGP hardware does. 493 */ 494 *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags, 495 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul, 496 dmat->boundary); 497 } |
466 if (*vaddr == NULL) | 498 if (*vaddr == NULL) { 499 CTR3(KTR_BUSDMA, "bus_dmamem_alloc: tag %p tag flags 0x%x " 500 "error %d", dmat, dmat->flags, ENOMEM); |
467 return (ENOMEM); | 501 return (ENOMEM); |
502 } 503 CTR3(KTR_BUSDMA, "bus_dmamem_alloc: tag %p tag flags 0x%x error %d", 504 dmat, dmat->flags, ENOMEM); |
|
468 return (0); 469} 470 471/* 472 * Free a piece of memory and it's allociated dmamap, that was allocated 473 * via bus_dmamem_alloc. Make the same choice for free/contigfree. 474 */ 475void --- 6 unchanged lines hidden (view full) --- 482 if (map != NULL) 483 panic("bus_dmamem_free: Invalid map freed\n"); 484 if ((dmat->maxsize <= PAGE_SIZE) 485 && dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) 486 free(vaddr, M_DEVBUF); 487 else { 488 contigfree(vaddr, dmat->maxsize, M_DEVBUF); 489 } | 505 return (0); 506} 507 508/* 509 * Free a piece of memory and it's allociated dmamap, that was allocated 510 * via bus_dmamem_alloc. Make the same choice for free/contigfree. 511 */ 512void --- 6 unchanged lines hidden (view full) --- 519 if (map != NULL) 520 panic("bus_dmamem_free: Invalid map freed\n"); 521 if ((dmat->maxsize <= PAGE_SIZE) 522 && dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) 523 free(vaddr, M_DEVBUF); 524 else { 525 contigfree(vaddr, dmat->maxsize, M_DEVBUF); 526 } |
527 CTR2(KTR_BUSDMA, "bus_dmamem_free: tag %p flags 0x%x", dmat, 528 dmat->flags); |
|
490} 491 492/* 493 * Utility function to load a linear buffer. lastaddrp holds state 494 * between invocations (for multiple-buffer loads). segp contains 495 * the starting segment on entrace, and the ending segment on exit. 496 * first indicates if this is the first invocation of this function. 497 */ --- 155 unchanged lines hidden (view full) --- 653 flags |= BUS_DMA_WAITOK; 654 map->callback = callback; 655 map->callback_arg = callback_arg; 656 } 657 658 error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, NULL, flags, 659 &lastaddr, &nsegs, 1); 660 | 529} 530 531/* 532 * Utility function to load a linear buffer. lastaddrp holds state 533 * between invocations (for multiple-buffer loads). segp contains 534 * the starting segment on entrace, and the ending segment on exit. 535 * first indicates if this is the first invocation of this function. 536 */ --- 155 unchanged lines hidden (view full) --- 692 flags |= BUS_DMA_WAITOK; 693 map->callback = callback; 694 map->callback_arg = callback_arg; 695 } 696 697 error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, NULL, flags, 698 &lastaddr, &nsegs, 1); 699 |
661 if (error == EINPROGRESS) | 700 if (error == EINPROGRESS) { 701 CTR3(KTR_BUSDMA, "bus_dmamap_load: tag %p tag flags 0x%x " 702 "error %d", dmat, dmat->flags, error); |
662 return (error); | 703 return (error); |
704 } |
|
663 664 if (error) 665 (*callback)(callback_arg, dmat->segments, 0, error); 666 else 667 (*callback)(callback_arg, dmat->segments, nsegs + 1, 0); 668 | 705 706 if (error) 707 (*callback)(callback_arg, dmat->segments, 0, error); 708 else 709 (*callback)(callback_arg, dmat->segments, nsegs + 1, 0); 710 |
711 CTR2(KTR_BUSDMA, "bus_dmamap_load: tag %p tag flags 0x%x error 0", 712 dmat, dmat->flags); |
|
669 return (0); 670} 671 672 673/* 674 * Like _bus_dmamap_load(), but for mbufs. 675 */ 676int --- 29 unchanged lines hidden (view full) --- 706 707 if (error) { 708 /* force "no valid mappings" in callback */ 709 (*callback)(callback_arg, dmat->segments, 0, 0, error); 710 } else { 711 (*callback)(callback_arg, dmat->segments, 712 nsegs+1, m0->m_pkthdr.len, error); 713 } | 713 return (0); 714} 715 716 717/* 718 * Like _bus_dmamap_load(), but for mbufs. 719 */ 720int --- 29 unchanged lines hidden (view full) --- 750 751 if (error) { 752 /* force "no valid mappings" in callback */ 753 (*callback)(callback_arg, dmat->segments, 0, 0, error); 754 } else { 755 (*callback)(callback_arg, dmat->segments, 756 nsegs+1, m0->m_pkthdr.len, error); 757 } |
758 CTR3(KTR_BUSDMA, "bus_dmamap_load_mbuf: tag %p tag flags 0x%x " 759 "error %d", dmat, dmat->flags, error); |
|
714 return (error); 715} 716 717/* 718 * Like _bus_dmamap_load(), but for uios. 719 */ 720int 721bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, --- 41 unchanged lines hidden (view full) --- 763 764 if (error) { 765 /* force "no valid mappings" in callback */ 766 (*callback)(callback_arg, dmat->segments, 0, 0, error); 767 } else { 768 (*callback)(callback_arg, dmat->segments, 769 nsegs+1, uio->uio_resid, error); 770 } | 760 return (error); 761} 762 763/* 764 * Like _bus_dmamap_load(), but for uios. 765 */ 766int 767bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, --- 41 unchanged lines hidden (view full) --- 809 810 if (error) { 811 /* force "no valid mappings" in callback */ 812 (*callback)(callback_arg, dmat->segments, 0, 0, error); 813 } else { 814 (*callback)(callback_arg, dmat->segments, 815 nsegs+1, uio->uio_resid, error); 816 } |
817 CTR3(KTR_BUSDMA, "bus_dmamap_load_uio: tag %p tag flags 0x%x " 818 "error %d", dmat, dmat->flags, error); |
|
771 return (error); 772} 773 774/* 775 * Release the mapping held by map. 776 */ 777void 778_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) --- 13 unchanged lines hidden (view full) --- 792 793 if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) { 794 /* 795 * Handle data bouncing. We might also 796 * want to add support for invalidating 797 * the caches on broken hardware 798 */ 799 total_bounced++; | 819 return (error); 820} 821 822/* 823 * Release the mapping held by map. 824 */ 825void 826_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) --- 13 unchanged lines hidden (view full) --- 840 841 if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) { 842 /* 843 * Handle data bouncing. We might also 844 * want to add support for invalidating 845 * the caches on broken hardware 846 */ 847 total_bounced++; |
848 CTR3(KTR_BUSDMA, "_bus_dmamap_sync: tag %p tag flags 0x%x " 849 "op 0x%x performing bounce", op, dmat, dmat->flags); |
|
800 801 if (op & BUS_DMASYNC_PREWRITE) { 802 while (bpage != NULL) { 803 bcopy((void *)bpage->datavaddr, 804 (void *)bpage->vaddr, 805 bpage->datacount); 806 bpage = STAILQ_NEXT(bpage, links); 807 } --- 157 unchanged lines hidden --- | 850 851 if (op & BUS_DMASYNC_PREWRITE) { 852 while (bpage != NULL) { 853 bcopy((void *)bpage->datavaddr, 854 (void *)bpage->vaddr, 855 bpage->datacount); 856 bpage = STAILQ_NEXT(bpage, links); 857 } --- 157 unchanged lines hidden --- |