busdma_bounce.c (233036) | busdma_bounce.c (239008) |
---|---|
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/x86/x86/busdma_machdep.c 233036 2012-03-16 16:12:10Z jhb $"); | 28__FBSDID("$FreeBSD: head/sys/x86/x86/busdma_machdep.c 239008 2012-08-03 13:50:29Z jhb $"); |
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> 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> | 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> 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> |
45#include <vm/vm_extern.h> 46#include <vm/vm_kern.h> |
|
45#include <vm/vm_page.h> 46#include <vm/vm_map.h> 47 48#include <machine/atomic.h> 49#include <machine/bus.h> 50#include <machine/md_var.h> 51#include <machine/specialreg.h> 52 --- 73 unchanged lines hidden (view full) --- 126 bus_size_t buflen; /* unmapped buffer length */ 127 bus_dmamap_callback_t *callback; 128 void *callback_arg; 129 STAILQ_ENTRY(bus_dmamap) links; 130}; 131 132static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist; 133static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist; | 47#include <vm/vm_page.h> 48#include <vm/vm_map.h> 49 50#include <machine/atomic.h> 51#include <machine/bus.h> 52#include <machine/md_var.h> 53#include <machine/specialreg.h> 54 --- 73 unchanged lines hidden (view full) --- 128 bus_size_t buflen; /* unmapped buffer length */ 129 bus_dmamap_callback_t *callback; 130 void *callback_arg; 131 STAILQ_ENTRY(bus_dmamap) links; 132}; 133 134static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist; 135static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist; |
134static struct bus_dmamap nobounce_dmamap; | 136static struct bus_dmamap nobounce_dmamap, contig_dmamap; |
135 136static void init_bounce_pages(void *dummy); 137static int alloc_bounce_zone(bus_dma_tag_t dmat); 138static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages); 139static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, 140 int commit); 141static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, 142 vm_offset_t vaddr, bus_size_t size); --- 317 unchanged lines hidden (view full) --- 460 461/* 462 * Destroy a handle for mapping from kva/uva/physical 463 * address space into bus device space. 464 */ 465int 466bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) 467{ | 137 138static void init_bounce_pages(void *dummy); 139static int alloc_bounce_zone(bus_dma_tag_t dmat); 140static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages); 141static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, 142 int commit); 143static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, 144 vm_offset_t vaddr, bus_size_t size); --- 317 unchanged lines hidden (view full) --- 462 463/* 464 * Destroy a handle for mapping from kva/uva/physical 465 * address space into bus device space. 466 */ 467int 468bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) 469{ |
468 if (map != NULL && map != &nobounce_dmamap) { | 470 if (map != NULL && map != &nobounce_dmamap && map != &contig_dmamap) { |
469 if (STAILQ_FIRST(&map->bpages) != NULL) { 470 CTR3(KTR_BUSDMA, "%s: tag %p error %d", 471 __func__, dmat, EBUSY); 472 return (EBUSY); 473 } 474 if (dmat->bounce_zone) 475 dmat->bounce_zone->map_count--; 476 free(map, M_DEVBUF); --- 8 unchanged lines hidden (view full) --- 485 * Allocate a piece of memory that can be efficiently mapped into 486 * bus device space based on the constraints lited in the dma tag. 487 * A dmamap to for use with dmamap_load is also allocated. 488 */ 489int 490bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, 491 bus_dmamap_t *mapp) 492{ | 471 if (STAILQ_FIRST(&map->bpages) != NULL) { 472 CTR3(KTR_BUSDMA, "%s: tag %p error %d", 473 __func__, dmat, EBUSY); 474 return (EBUSY); 475 } 476 if (dmat->bounce_zone) 477 dmat->bounce_zone->map_count--; 478 free(map, M_DEVBUF); --- 8 unchanged lines hidden (view full) --- 487 * Allocate a piece of memory that can be efficiently mapped into 488 * bus device space based on the constraints lited in the dma tag. 489 * A dmamap to for use with dmamap_load is also allocated. 490 */ 491int 492bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, 493 bus_dmamap_t *mapp) 494{ |
495 vm_memattr_t attr; |
|
493 int mflags; 494 495 if (flags & BUS_DMA_NOWAIT) 496 mflags = M_NOWAIT; 497 else 498 mflags = M_WAITOK; 499 500 /* If we succeed, no mapping/bouncing will be required */ --- 6 unchanged lines hidden (view full) --- 507 if (dmat->segments == NULL) { 508 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", 509 __func__, dmat, dmat->flags, ENOMEM); 510 return (ENOMEM); 511 } 512 } 513 if (flags & BUS_DMA_ZERO) 514 mflags |= M_ZERO; | 496 int mflags; 497 498 if (flags & BUS_DMA_NOWAIT) 499 mflags = M_NOWAIT; 500 else 501 mflags = M_WAITOK; 502 503 /* If we succeed, no mapping/bouncing will be required */ --- 6 unchanged lines hidden (view full) --- 510 if (dmat->segments == NULL) { 511 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", 512 __func__, dmat, dmat->flags, ENOMEM); 513 return (ENOMEM); 514 } 515 } 516 if (flags & BUS_DMA_ZERO) 517 mflags |= M_ZERO; |
518 if (flags & BUS_DMA_NOCACHE) 519 attr = VM_MEMATTR_UNCACHEABLE; 520 else 521 attr = VM_MEMATTR_DEFAULT; |
|
515 516 /* 517 * XXX: 518 * (dmat->alignment < dmat->maxsize) is just a quick hack; the exact 519 * alignment guarantees of malloc need to be nailed down, and the 520 * code below should be rewritten to take that into account. 521 * 522 * In the meantime, we'll warn the user if malloc gets it wrong. 523 */ 524 if ((dmat->maxsize <= PAGE_SIZE) && 525 (dmat->alignment < dmat->maxsize) && | 522 523 /* 524 * XXX: 525 * (dmat->alignment < dmat->maxsize) is just a quick hack; the exact 526 * alignment guarantees of malloc need to be nailed down, and the 527 * code below should be rewritten to take that into account. 528 * 529 * In the meantime, we'll warn the user if malloc gets it wrong. 530 */ 531 if ((dmat->maxsize <= PAGE_SIZE) && 532 (dmat->alignment < dmat->maxsize) && |
526 dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) { | 533 dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem) && 534 attr == VM_MEMATTR_DEFAULT) { |
527 *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags); 528 } else { 529 /* 530 * XXX Use Contigmalloc until it is merged into this facility 531 * and handles multi-seg allocations. Nobody is doing 532 * multi-seg allocations yet though. 533 * XXX Certain AGP hardware does. 534 */ | 535 *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags); 536 } else { 537 /* 538 * XXX Use Contigmalloc until it is merged into this facility 539 * and handles multi-seg allocations. Nobody is doing 540 * multi-seg allocations yet though. 541 * XXX Certain AGP hardware does. 542 */ |
535 *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags, 536 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul, 537 dmat->boundary); | 543 *vaddr = (void *)kmem_alloc_contig(kernel_map, dmat->maxsize, 544 mflags, 0ul, dmat->lowaddr, dmat->alignment ? 545 dmat->alignment : 1ul, dmat->boundary, attr); 546 *mapp = &contig_dmamap; |
538 } 539 if (*vaddr == NULL) { 540 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", 541 __func__, dmat, dmat->flags, ENOMEM); 542 return (ENOMEM); 543 } else if (vtophys(*vaddr) & (dmat->alignment - 1)) { 544 printf("bus_dmamem_alloc failed to align memory properly.\n"); 545 } | 547 } 548 if (*vaddr == NULL) { 549 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", 550 __func__, dmat, dmat->flags, ENOMEM); 551 return (ENOMEM); 552 } else if (vtophys(*vaddr) & (dmat->alignment - 1)) { 553 printf("bus_dmamem_alloc failed to align memory properly.\n"); 554 } |
546 if (flags & BUS_DMA_NOCACHE) 547 pmap_change_attr((vm_offset_t)*vaddr, dmat->maxsize, 548 PAT_UNCACHEABLE); | |
549 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", 550 __func__, dmat, dmat->flags, 0); 551 return (0); 552} 553 554/* 555 * Free a piece of memory and it's allociated dmamap, that was allocated 556 * via bus_dmamem_alloc. Make the same choice for free/contigfree. 557 */ 558void 559bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) 560{ 561 /* 562 * dmamem does not need to be bounced, so the map should be | 555 CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", 556 __func__, dmat, dmat->flags, 0); 557 return (0); 558} 559 560/* 561 * Free a piece of memory and it's allociated dmamap, that was allocated 562 * via bus_dmamem_alloc. Make the same choice for free/contigfree. 563 */ 564void 565bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) 566{ 567 /* 568 * dmamem does not need to be bounced, so the map should be |
563 * NULL | 569 * NULL if malloc() was used and contig_dmamap if 570 * contigmalloc() was used. |
564 */ | 571 */ |
565 if (map != NULL) | 572 if (!(map == NULL || map == &contig_dmamap)) |
566 panic("bus_dmamem_free: Invalid map freed\n"); | 573 panic("bus_dmamem_free: Invalid map freed\n"); |
567 pmap_change_attr((vm_offset_t)vaddr, dmat->maxsize, PAT_WRITE_BACK); 568 if ((dmat->maxsize <= PAGE_SIZE) && 569 (dmat->alignment < dmat->maxsize) && 570 dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) | 574 if (map == NULL) |
571 free(vaddr, M_DEVBUF); | 575 free(vaddr, M_DEVBUF); |
572 else { 573 contigfree(vaddr, dmat->maxsize, M_DEVBUF); 574 } | 576 else 577 kmem_free(kernel_map, (vm_offset_t)vaddr, dmat->maxsize); |
575 CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags); 576} 577 578int 579_bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, 580 void *buf, bus_size_t buflen, int flags) 581{ 582 vm_offset_t vaddr; --- 74 unchanged lines hidden (view full) --- 657 int *segp, 658 int first) 659{ 660 bus_size_t sgsize; 661 bus_addr_t curaddr, lastaddr, baddr, bmask; 662 vm_offset_t vaddr; 663 int seg, error; 664 | 578 CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags); 579} 580 581int 582_bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, 583 void *buf, bus_size_t buflen, int flags) 584{ 585 vm_offset_t vaddr; --- 74 unchanged lines hidden (view full) --- 660 int *segp, 661 int first) 662{ 663 bus_size_t sgsize; 664 bus_addr_t curaddr, lastaddr, baddr, bmask; 665 vm_offset_t vaddr; 666 int seg, error; 667 |
665 if (map == NULL) | 668 if (map == NULL || map == &contig_dmamap) |
666 map = &nobounce_dmamap; 667 668 if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { 669 error = _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags); 670 if (error) 671 return (error); 672 } 673 --- 460 unchanged lines hidden (view full) --- 1134static bus_addr_t 1135add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, 1136 bus_size_t size) 1137{ 1138 struct bounce_zone *bz; 1139 struct bounce_page *bpage; 1140 1141 KASSERT(dmat->bounce_zone != NULL, ("no bounce zone in dma tag")); | 669 map = &nobounce_dmamap; 670 671 if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { 672 error = _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags); 673 if (error) 674 return (error); 675 } 676 --- 460 unchanged lines hidden (view full) --- 1137static bus_addr_t 1138add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, 1139 bus_size_t size) 1140{ 1141 struct bounce_zone *bz; 1142 struct bounce_page *bpage; 1143 1144 KASSERT(dmat->bounce_zone != NULL, ("no bounce zone in dma tag")); |
1142 KASSERT(map != NULL && map != &nobounce_dmamap, | 1145 KASSERT(map != NULL && map != &nobounce_dmamap && map != &contig_dmamap, |
1143 ("add_bounce_page: bad map %p", map)); 1144 1145 bz = dmat->bounce_zone; 1146 if (map->pagesneeded == 0) 1147 panic("add_bounce_page: map doesn't need any pages"); 1148 map->pagesneeded--; 1149 1150 if (map->pagesreserved == 0) --- 79 unchanged lines hidden --- | 1146 ("add_bounce_page: bad map %p", map)); 1147 1148 bz = dmat->bounce_zone; 1149 if (map->pagesneeded == 0) 1150 panic("add_bounce_page: map doesn't need any pages"); 1151 map->pagesneeded--; 1152 1153 if (map->pagesreserved == 0) --- 79 unchanged lines hidden --- |