busdma: Panic if the kmalloc_powerof2() fails to meet the dma requirement
[dragonfly.git] / sys / platform / pc32 / i386 / busdma_machdep.c
index b6e7a8a..ae451fb 100644 (file)
@@ -511,17 +511,17 @@ check_kmalloc(bus_dma_tag_t dmat, const void *vaddr0, int verify)
        uintptr_t vaddr = (uintptr_t)vaddr0;
 
        if ((vaddr ^ (vaddr + dmat->maxsize - 1)) & ~PAGE_MASK) {
-               if (verify || bootverbose)
-                       kprintf("boundary check failed\n");
                if (verify)
-                       print_backtrace(-1); /* XXX panic */
+                       panic("boundary check failed\n");
+               if (bootverbose)
+                       kprintf("boundary check failed\n");
                maxsize = dmat->maxsize;
        }
        if (vaddr & (dmat->alignment - 1)) {
-               if (verify || bootverbose)
-                       kprintf("alignment check failed\n");
                if (verify)
-                       print_backtrace(-1); /* XXX panic */
+                       panic("alignment check failed\n");
+               if (bootverbose)
+                       kprintf("alignment check failed\n");
                if (dmat->maxsize < dmat->alignment)
                        maxsize = dmat->alignment;
                else
@@ -573,13 +573,8 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddr, int flags,
                 */
                maxsize = check_kmalloc(dmat, *vaddr, 0);
                if (maxsize) {
-                       size_t size;
-
                        kfree(*vaddr, M_DEVBUF);
-                       /* XXX check for overflow? */
-                       for (size = 1; size <= maxsize; size <<= 1)
-                               ;
-                       *vaddr = kmalloc(size, M_DEVBUF, mflags);
+                       *vaddr = kmalloc_powerof2(maxsize, M_DEVBUF, mflags);
                        check_kmalloc(dmat, *vaddr, 1);
                }
        } else {
@@ -1371,6 +1366,11 @@ add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr,
 
        BZ_UNLOCK(bz);
 
+       if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
+               /* Page offset needs to be preserved. */
+               bpage->vaddr |= vaddr & PAGE_MASK;
+               bpage->busaddr |= vaddr & PAGE_MASK;
+       }
        bpage->datavaddr = vaddr;
        bpage->datacount = size;
        STAILQ_INSERT_TAIL(&map->bpages, bpage, links);
@@ -1386,6 +1386,16 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
        bpage->datavaddr = 0;
        bpage->datacount = 0;
 
+       if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
+               /*
+                * Reset the bounce page to start at offset 0.  Other uses
+                * of this bounce page may need to store a full page of
+                * data and/or assume it starts on a page boundary.
+                */
+               bpage->vaddr &= ~PAGE_MASK;
+               bpage->busaddr &= ~PAGE_MASK;
+       }
+
        BZ_LOCK(bz);
 
        STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);