diff --git a/sys/dev/usb/usb_busdma.c b/sys/dev/usb/usb_busdma.c index d31aeec..4c613cf 100644 --- a/sys/dev/usb/usb_busdma.c +++ b/sys/dev/usb/usb_busdma.c @@ -369,7 +369,7 @@ usb_dma_tag_create(struct usb_dma_tag *udt, (2 + (size / USB_PAGE_SIZE)) : 1, /* maxsegsz */ (align == 1 && size > USB_PAGE_SIZE) ? USB_PAGE_SIZE : size, - /* flags */ BUS_DMA_KEEP_PG_OFFSET, + /* flags */ BUS_DMA_KEEP_PG_OFFSET | BUS_DMA_NO_PAGEZERO, /* lockfn */ &usb_dma_lock_cb, /* lockarg */ NULL, &tag)) { diff --git a/sys/sys/bus_dma.h b/sys/sys/bus_dma.h index 0dad326..7771d32 100644 --- a/sys/sys/bus_dma.h +++ b/sys/sys/bus_dma.h @@ -109,6 +109,9 @@ */ #define BUS_DMA_KEEP_PG_OFFSET 0x400 +/* Do not use the physical page zero. */ +#define BUS_DMA_NO_PAGEZERO 0x800 + /* Forwards needed by prototypes below. */ struct mbuf; struct uio; diff --git a/sys/x86/x86/busdma_machdep.c b/sys/x86/x86/busdma_machdep.c index 70dd72b..02a0602 100644 --- a/sys/x86/x86/busdma_machdep.c +++ b/sys/x86/x86/busdma_machdep.c @@ -171,8 +171,10 @@ run_filter(bus_dma_tag_t dmat, bus_addr_t paddr) && (dmat->filter == NULL || (*dmat->filter)(dmat->filterarg, paddr) != 0)) retval = 1; + else if ((dmat->flags & BUS_DMA_NO_PAGEZERO) != 0 && paddr == 0) + retval = 1; - dmat = dmat->parent; + dmat = dmat->parent; } while (retval == 0 && dmat != NULL); return (retval); } @@ -293,8 +295,11 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, atomic_add_int(&parent->ref_count, 1); } - if (newtag->lowaddr < ptoa((vm_paddr_t)Maxmem) - || newtag->alignment > 1) + if (newtag->lowaddr < ptoa((vm_paddr_t)Maxmem) || + newtag->alignment > 1) + newtag->flags |= BUS_DMA_COULD_BOUNCE; + + if ((newtag->flags & BUS_DMA_NO_PAGEZERO) != 0) newtag->flags |= BUS_DMA_COULD_BOUNCE; if (((newtag->flags & BUS_DMA_COULD_BOUNCE) != 0) && @@ -523,7 +528,8 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, */ if ((dmat->maxsize <= PAGE_SIZE) && (dmat->alignment < dmat->maxsize) && - dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) { + dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem) && + (dmat->flags & BUS_DMA_NO_PAGEZERO) == 0) { *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags); } else { /* @@ -533,7 +539,8 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, * XXX Certain AGP hardware does. */ *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags, - 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul, + (dmat->flags & BUS_DMA_NO_PAGEZERO) != 0 ? PAGE_SIZE : 0, + dmat->lowaddr, dmat->alignment ? dmat->alignment : 1ul, dmat->boundary); } if (*vaddr == NULL) { @@ -567,7 +574,8 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) pmap_change_attr((vm_offset_t)vaddr, dmat->maxsize, PAT_WRITE_BACK); if ((dmat->maxsize <= PAGE_SIZE) && (dmat->alignment < dmat->maxsize) && - dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) + dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem) && + (dmat->flags & BUS_DMA_NO_PAGEZERO) == 0) free(vaddr, M_DEVBUF); else { contigfree(vaddr, dmat->maxsize, M_DEVBUF); @@ -1086,15 +1094,13 @@ alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages) struct bounce_page *bpage; bpage = (struct bounce_page *)malloc(sizeof(*bpage), M_DEVBUF, - M_NOWAIT | M_ZERO); - + M_NOWAIT | M_ZERO); if (bpage == NULL) break; bpage->vaddr = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF, - M_NOWAIT, 0ul, - bz->lowaddr, - PAGE_SIZE, - 0); + M_NOWAIT, + (dmat->flags & BUS_DMA_NO_PAGEZERO) != 0 ? PAGE_SIZE : 0, + bz->lowaddr, PAGE_SIZE, 0); if (bpage->vaddr == 0) { free(bpage, M_DEVBUF); break;