Deleted Added
full compact
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 ---