busdma_bounce.c (143284) | busdma_bounce.c (143293) |
---|---|
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 143284 2005-03-08 11:18:14Z mux $"); | 28__FBSDID("$FreeBSD: head/sys/i386/i386/busdma_machdep.c 143293 2005-03-08 14:44:33Z mux $"); |
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> --- 183 unchanged lines hidden (view full) --- 220 maxsegsz = boundary; 221 222 /* Return a NULL tag on failure */ 223 *dmat = NULL; 224 225 newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, 226 M_ZERO | M_NOWAIT); 227 if (newtag == NULL) { | 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> --- 183 unchanged lines hidden (view full) --- 220 maxsegsz = boundary; 221 222 /* Return a NULL tag on failure */ 223 *dmat = NULL; 224 225 newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, 226 M_ZERO | M_NOWAIT); 227 if (newtag == NULL) { |
228 CTR3(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d", | 228 CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d", |
229 __func__, newtag, 0, error); 230 return (ENOMEM); 231 } 232 233 newtag->parent = parent; 234 newtag->alignment = alignment; 235 newtag->boundary = boundary; 236 newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1); --- 65 unchanged lines hidden (view full) --- 302 newtag->flags |= BUS_DMA_MIN_ALLOC_COMP; 303 } 304 305 if (error != 0) { 306 free(newtag, M_DEVBUF); 307 } else { 308 *dmat = newtag; 309 } | 229 __func__, newtag, 0, error); 230 return (ENOMEM); 231 } 232 233 newtag->parent = parent; 234 newtag->alignment = alignment; 235 newtag->boundary = boundary; 236 newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1); --- 65 unchanged lines hidden (view full) --- 302 newtag->flags |= BUS_DMA_MIN_ALLOC_COMP; 303 } 304 305 if (error != 0) { 306 free(newtag, M_DEVBUF); 307 } else { 308 *dmat = newtag; 309 } |
310 CTR3(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d", | 310 CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d", |
311 __func__, newtag, (newtag != NULL ? newtag->flags : 0), error); 312 return (error); 313} 314 315int 316bus_dma_tag_destroy(bus_dma_tag_t dmat) 317{ 318 bus_dma_tag_t dmat_copy; --- 24 unchanged lines hidden (view full) --- 343 * count on our parent. 344 */ 345 dmat = parent; 346 } else 347 dmat = NULL; 348 } 349 } 350out: | 311 __func__, newtag, (newtag != NULL ? newtag->flags : 0), error); 312 return (error); 313} 314 315int 316bus_dma_tag_destroy(bus_dma_tag_t dmat) 317{ 318 bus_dma_tag_t dmat_copy; --- 24 unchanged lines hidden (view full) --- 343 * count on our parent. 344 */ 345 dmat = parent; 346 } else 347 dmat = NULL; 348 } 349 } 350out: |
351 CTR2(KTR_BUSDMA, "%s tag %p error %d", __func__, dmat_copy, error); | 351 CTR3(KTR_BUSDMA, "%s tag %p error %d", __func__, dmat_copy, error); |
352 return (error); 353} 354 355/* 356 * Allocate a handle for mapping from kva/uva/physical 357 * address space into bus device space. 358 */ 359int 360bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) 361{ 362 int error; 363 364 error = 0; 365 366 if (dmat->segments == NULL) { 367 dmat->segments = (bus_dma_segment_t *)malloc( 368 sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, 369 M_NOWAIT); 370 if (dmat->segments == NULL) { | 352 return (error); 353} 354 355/* 356 * Allocate a handle for mapping from kva/uva/physical 357 * address space into bus device space. 358 */ 359int 360bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) 361{ 362 int error; 363 364 error = 0; 365 366 if (dmat->segments == NULL) { 367 dmat->segments = (bus_dma_segment_t *)malloc( 368 sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, 369 M_NOWAIT); 370 if (dmat->segments == NULL) { |
371 CTR2(KTR_BUSDMA, "%s: tag %p error %d", | 371 CTR3(KTR_BUSDMA, "%s: tag %p error %d", |
372 __func__, dmat, ENOMEM); 373 return (ENOMEM); 374 } 375 } 376 377 /* 378 * Bouncing might be required if the driver asks for an active 379 * exclusion region, a data alignment that is stricter than 1, and/or --- 7 unchanged lines hidden (view full) --- 387 if (dmat->bounce_zone == NULL) { 388 if ((error = alloc_bounce_zone(dmat)) != 0) 389 return (error); 390 } 391 392 *mapp = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF, 393 M_NOWAIT | M_ZERO); 394 if (*mapp == NULL) { | 372 __func__, dmat, ENOMEM); 373 return (ENOMEM); 374 } 375 } 376 377 /* 378 * Bouncing might be required if the driver asks for an active 379 * exclusion region, a data alignment that is stricter than 1, and/or --- 7 unchanged lines hidden (view full) --- 387 if (dmat->bounce_zone == NULL) { 388 if ((error = alloc_bounce_zone(dmat)) != 0) 389 return (error); 390 } 391 392 *mapp = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF, 393 M_NOWAIT | M_ZERO); 394 if (*mapp == NULL) { |
395 CTR2(KTR_BUSDMA, "%s: tag %p error %d", | 395 CTR3(KTR_BUSDMA, "%s: tag %p error %d", |
396 __func__, dmat, ENOMEM); 397 return (ENOMEM); 398 } 399 400 /* Initialize the new map */ 401 STAILQ_INIT(&((*mapp)->bpages)); 402 403 /* --- 17 unchanged lines hidden (view full) --- 421 error = 0; 422 } 423 } 424 } else { 425 *mapp = NULL; 426 } 427 if (error == 0) 428 dmat->map_count++; | 396 __func__, dmat, ENOMEM); 397 return (ENOMEM); 398 } 399 400 /* Initialize the new map */ 401 STAILQ_INIT(&((*mapp)->bpages)); 402 403 /* --- 17 unchanged lines hidden (view full) --- 421 error = 0; 422 } 423 } 424 } else { 425 *mapp = NULL; 426 } 427 if (error == 0) 428 dmat->map_count++; |
429 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", | 429 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", |
430 __func__, dmat, dmat->flags, error); 431 return (error); 432} 433 434/* 435 * Destroy a handle for mapping from kva/uva/physical 436 * address space into bus device space. 437 */ 438int 439bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) 440{ 441 if (map != NULL && map != &nobounce_dmamap) { 442 if (STAILQ_FIRST(&map->bpages) != NULL) { | 430 __func__, dmat, dmat->flags, error); 431 return (error); 432} 433 434/* 435 * Destroy a handle for mapping from kva/uva/physical 436 * address space into bus device space. 437 */ 438int 439bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) 440{ 441 if (map != NULL && map != &nobounce_dmamap) { 442 if (STAILQ_FIRST(&map->bpages) != NULL) { |
443 CTR2(KTR_BUSDMA, "%s: tag %p error %d", | 443 CTR3(KTR_BUSDMA, "%s: tag %p error %d", |
444 __func__, dmat, EBUSY); 445 return (EBUSY); 446 } 447 free(map, M_DEVBUF); 448 } 449 dmat->map_count--; | 444 __func__, dmat, EBUSY); 445 return (EBUSY); 446 } 447 free(map, M_DEVBUF); 448 } 449 dmat->map_count--; |
450 CTR1(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat); | 450 CTR2(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat); |
451 return (0); 452} 453 454 455/* 456 * Allocate a piece of memory that can be efficiently mapped into 457 * bus device space based on the constraints lited in the dma tag. 458 * A dmamap to for use with dmamap_load is also allocated. --- 14 unchanged lines hidden (view full) --- 473 /* If we succeed, no mapping/bouncing will be required */ 474 *mapp = NULL; 475 476 if (dmat->segments == NULL) { 477 dmat->segments = (bus_dma_segment_t *)malloc( 478 sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, 479 M_NOWAIT); 480 if (dmat->segments == NULL) { | 451 return (0); 452} 453 454 455/* 456 * Allocate a piece of memory that can be efficiently mapped into 457 * bus device space based on the constraints lited in the dma tag. 458 * A dmamap to for use with dmamap_load is also allocated. --- 14 unchanged lines hidden (view full) --- 473 /* If we succeed, no mapping/bouncing will be required */ 474 *mapp = NULL; 475 476 if (dmat->segments == NULL) { 477 dmat->segments = (bus_dma_segment_t *)malloc( 478 sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, 479 M_NOWAIT); 480 if (dmat->segments == NULL) { |
481 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", | 481 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", |
482 __func__, dmat, dmat->flags, ENOMEM); 483 return (ENOMEM); 484 } 485 } 486 487 if ((dmat->maxsize <= PAGE_SIZE) && 488 dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) { 489 *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags); --- 4 unchanged lines hidden (view full) --- 494 * multi-seg allocations yet though. 495 * XXX Certain AGP hardware does. 496 */ 497 *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags, 498 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul, 499 dmat->boundary); 500 } 501 if (*vaddr == NULL) { | 482 __func__, dmat, dmat->flags, ENOMEM); 483 return (ENOMEM); 484 } 485 } 486 487 if ((dmat->maxsize <= PAGE_SIZE) && 488 dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) { 489 *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags); --- 4 unchanged lines hidden (view full) --- 494 * multi-seg allocations yet though. 495 * XXX Certain AGP hardware does. 496 */ 497 *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags, 498 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul, 499 dmat->boundary); 500 } 501 if (*vaddr == NULL) { |
502 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", | 502 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", |
503 __func__, dmat, dmat->flags, ENOMEM); 504 return (ENOMEM); 505 } | 503 __func__, dmat, dmat->flags, ENOMEM); 504 return (ENOMEM); 505 } |
506 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", | 506 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", |
507 __func__, dmat, dmat->flags, ENOMEM); 508 return (0); 509} 510 511/* 512 * Free a piece of memory and it's allociated dmamap, that was allocated 513 * via bus_dmamem_alloc. Make the same choice for free/contigfree. 514 */ --- 7 unchanged lines hidden (view full) --- 522 if (map != NULL) 523 panic("bus_dmamem_free: Invalid map freed\n"); 524 if ((dmat->maxsize <= PAGE_SIZE) 525 && dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) 526 free(vaddr, M_DEVBUF); 527 else { 528 contigfree(vaddr, dmat->maxsize, M_DEVBUF); 529 } | 507 __func__, dmat, dmat->flags, ENOMEM); 508 return (0); 509} 510 511/* 512 * Free a piece of memory and it's allociated dmamap, that was allocated 513 * via bus_dmamem_alloc. Make the same choice for free/contigfree. 514 */ --- 7 unchanged lines hidden (view full) --- 522 if (map != NULL) 523 panic("bus_dmamem_free: Invalid map freed\n"); 524 if ((dmat->maxsize <= PAGE_SIZE) 525 && dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) 526 free(vaddr, M_DEVBUF); 527 else { 528 contigfree(vaddr, dmat->maxsize, M_DEVBUF); 529 } |
530 CTR2(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags); | 530 CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags); |
531} 532 533/* 534 * Utility function to load a linear buffer. lastaddrp holds state 535 * between invocations (for multiple-buffer loads). segp contains 536 * the starting segment on entrace, and the ending segment on exit. 537 * first indicates if this is the first invocation of this function. 538 */ --- 152 unchanged lines hidden (view full) --- 691 map->callback = callback; 692 map->callback_arg = callback_arg; 693 } 694 695 error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, NULL, flags, 696 &lastaddr, dmat->segments, &nsegs, 1); 697 698 if (error == EINPROGRESS) { | 531} 532 533/* 534 * Utility function to load a linear buffer. lastaddrp holds state 535 * between invocations (for multiple-buffer loads). segp contains 536 * the starting segment on entrace, and the ending segment on exit. 537 * first indicates if this is the first invocation of this function. 538 */ --- 152 unchanged lines hidden (view full) --- 691 map->callback = callback; 692 map->callback_arg = callback_arg; 693 } 694 695 error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, NULL, flags, 696 &lastaddr, dmat->segments, &nsegs, 1); 697 698 if (error == EINPROGRESS) { |
699 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", | 699 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", |
700 __func__, dmat, dmat->flags, error); 701 return (error); 702 } 703 704 if (error) 705 (*callback)(callback_arg, dmat->segments, 0, error); 706 else 707 (*callback)(callback_arg, dmat->segments, nsegs + 1, 0); 708 | 700 __func__, dmat, dmat->flags, error); 701 return (error); 702 } 703 704 if (error) 705 (*callback)(callback_arg, dmat->segments, 0, error); 706 else 707 (*callback)(callback_arg, dmat->segments, nsegs + 1, 0); 708 |
709 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error 0 nsegs %d", | 709 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error 0 nsegs %d", |
710 __func__, dmat, dmat->flags, nsegs + 1); 711 return (0); 712} 713 714 715/* 716 * Like _bus_dmamap_load(), but for mbufs. 717 */ --- 30 unchanged lines hidden (view full) --- 748 749 if (error) { 750 /* force "no valid mappings" in callback */ 751 (*callback)(callback_arg, dmat->segments, 0, 0, error); 752 } else { 753 (*callback)(callback_arg, dmat->segments, 754 nsegs+1, m0->m_pkthdr.len, error); 755 } | 710 __func__, dmat, dmat->flags, nsegs + 1); 711 return (0); 712} 713 714 715/* 716 * Like _bus_dmamap_load(), but for mbufs. 717 */ --- 30 unchanged lines hidden (view full) --- 748 749 if (error) { 750 /* force "no valid mappings" in callback */ 751 (*callback)(callback_arg, dmat->segments, 0, 0, error); 752 } else { 753 (*callback)(callback_arg, dmat->segments, 754 nsegs+1, m0->m_pkthdr.len, error); 755 } |
756 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", | 756 CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", |
757 __func__, dmat, dmat->flags, error, nsegs + 1); 758 return (error); 759} 760 761int 762bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, 763 struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, 764 int flags) --- 20 unchanged lines hidden (view full) --- 785 } 786 } 787 } else { 788 error = EINVAL; 789 } 790 791 /* XXX FIXME: Having to increment nsegs is really annoying */ 792 ++*nsegs; | 757 __func__, dmat, dmat->flags, error, nsegs + 1); 758 return (error); 759} 760 761int 762bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, 763 struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, 764 int flags) --- 20 unchanged lines hidden (view full) --- 785 } 786 } 787 } else { 788 error = EINVAL; 789 } 790 791 /* XXX FIXME: Having to increment nsegs is really annoying */ 792 ++*nsegs; |
793 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", | 793 CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", |
794 __func__, dmat, dmat->flags, error, *nsegs); 795 return (error); 796} 797 798/* 799 * Like _bus_dmamap_load(), but for uios. 800 */ 801int --- 43 unchanged lines hidden (view full) --- 845 846 if (error) { 847 /* force "no valid mappings" in callback */ 848 (*callback)(callback_arg, dmat->segments, 0, 0, error); 849 } else { 850 (*callback)(callback_arg, dmat->segments, 851 nsegs+1, uio->uio_resid, error); 852 } | 794 __func__, dmat, dmat->flags, error, *nsegs); 795 return (error); 796} 797 798/* 799 * Like _bus_dmamap_load(), but for uios. 800 */ 801int --- 43 unchanged lines hidden (view full) --- 845 846 if (error) { 847 /* force "no valid mappings" in callback */ 848 (*callback)(callback_arg, dmat->segments, 0, 0, error); 849 } else { 850 (*callback)(callback_arg, dmat->segments, 851 nsegs+1, uio->uio_resid, error); 852 } |
853 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", | 853 CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", |
854 __func__, dmat, dmat->flags, error, nsegs + 1); 855 return (error); 856} 857 858/* 859 * Release the mapping held by map. 860 */ 861void --- 14 unchanged lines hidden (view full) --- 876 877 if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) { 878 /* 879 * Handle data bouncing. We might also 880 * want to add support for invalidating 881 * the caches on broken hardware 882 */ 883 dmat->bounce_zone->total_bounced++; | 854 __func__, dmat, dmat->flags, error, nsegs + 1); 855 return (error); 856} 857 858/* 859 * Release the mapping held by map. 860 */ 861void --- 14 unchanged lines hidden (view full) --- 876 877 if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) { 878 /* 879 * Handle data bouncing. We might also 880 * want to add support for invalidating 881 * the caches on broken hardware 882 */ 883 dmat->bounce_zone->total_bounced++; |
884 CTR3(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x " | 884 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x " |
885 "performing bounce", __func__, op, dmat, dmat->flags); 886 887 if (op & BUS_DMASYNC_PREWRITE) { 888 while (bpage != NULL) { 889 bcopy((void *)bpage->datavaddr, 890 (void *)bpage->vaddr, 891 bpage->datacount); 892 bpage = STAILQ_NEXT(bpage, links); --- 255 unchanged lines hidden --- | 885 "performing bounce", __func__, op, dmat, dmat->flags); 886 887 if (op & BUS_DMASYNC_PREWRITE) { 888 while (bpage != NULL) { 889 bcopy((void *)bpage->datavaddr, 890 (void *)bpage->vaddr, 891 bpage->datacount); 892 bpage = STAILQ_NEXT(bpage, links); --- 255 unchanged lines hidden --- |