Index: head/sys/arm/arm/busdma_machdep-v6.c =================================================================== --- head/sys/arm/arm/busdma_machdep-v6.c +++ head/sys/arm/arm/busdma_machdep-v6.c @@ -491,6 +491,7 @@ newtag->highaddr = MAX(parent->highaddr, newtag->highaddr); newtag->alignment = MAX(parent->alignment, newtag->alignment); newtag->flags |= parent->flags & BUS_DMA_COULD_BOUNCE; + newtag->flags |= parent->flags & BUS_DMA_COHERENT; if (newtag->boundary == 0) newtag->boundary = parent->boundary; else if (parent->boundary != 0) @@ -755,11 +756,19 @@ } map->flags = DMAMAP_DMAMEM_ALLOC; - /* Choose a busdma buffer allocator based on memory type flags. */ - if (flags & BUS_DMA_COHERENT) { + /* For coherent memory, set the map flag that disables sync ops. */ + if (flags & BUS_DMA_COHERENT) + map->flags |= DMAMAP_COHERENT; + + /* + * Choose a busdma buffer allocator based on memory type flags. + * If the tag's COHERENT flag is set, that means normal memory + * is already coherent, use the normal allocator. + */ + if ((flags & BUS_DMA_COHERENT) && + ((dmat->flags & BUS_DMA_COHERENT) == 0)) { memattr = VM_MEMATTR_UNCACHEABLE; ba = coherent_allocator; - map->flags |= DMAMAP_COHERENT; } else { memattr = VM_MEMATTR_DEFAULT; ba = standard_allocator; @@ -829,7 +838,8 @@ struct busdma_bufzone *bufzone; busdma_bufalloc_t ba; - if (map->flags & DMAMAP_COHERENT) + if ((map->flags & DMAMAP_COHERENT) && + ((dmat->flags & BUS_DMA_COHERENT) == 0)) ba = coherent_allocator; else ba = standard_allocator; @@ -1030,7 +1040,7 @@ sgsize = MIN(sgsize, PAGE_SIZE - (curaddr & PAGE_MASK)); curaddr = add_bounce_page(dmat, map, 0, curaddr, sgsize); - } else { + } else if ((dmat->flags & BUS_DMA_COHERENT) == 0) { if (map->sync_count > 0) sl_end = sl->paddr + sl->datacount; @@ -1144,7 +1154,7 @@ sgsize)) { curaddr = add_bounce_page(dmat, map, kvaddr, curaddr, sgsize); - } else { + } else if ((dmat->flags & BUS_DMA_COHERENT) == 0) { if (map->sync_count > 0) { sl_pend = sl->paddr + sl->datacount; sl_vend = sl->vaddr + sl->datacount; @@ -1353,8 +1363,9 @@ bpage->datacount); if (tempvaddr != 0) pmap_quick_remove_page(tempvaddr); - dcache_wb_poc(bpage->vaddr, bpage->busaddr, - bpage->datacount); + if ((dmat->flags & BUS_DMA_COHERENT) == 0) + dcache_wb_poc(bpage->vaddr, + bpage->busaddr, bpage->datacount); bpage = STAILQ_NEXT(bpage, links); } dmat->bounce_zone->total_bounced++; @@ -1374,8 +1385,9 @@ if ((op & BUS_DMASYNC_PREREAD) && !(op & BUS_DMASYNC_PREWRITE)) { bpage = STAILQ_FIRST(&map->bpages); while (bpage != NULL) { - dcache_inv_poc_dma(bpage->vaddr, bpage->busaddr, - bpage->datacount); + if ((dmat->flags & BUS_DMA_COHERENT) == 0) + dcache_inv_poc_dma(bpage->vaddr, + bpage->busaddr, bpage->datacount); bpage = STAILQ_NEXT(bpage, links); } } @@ -1391,8 +1403,9 @@ */ if (op & BUS_DMASYNC_POSTREAD) { while (bpage != NULL) { - dcache_inv_poc(bpage->vaddr, bpage->busaddr, - bpage->datacount); + if ((dmat->flags & BUS_DMA_COHERENT) == 0) + dcache_inv_poc(bpage->vaddr, + bpage->busaddr, bpage->datacount); tempvaddr = 0; datavaddr = bpage->datavaddr; if (datavaddr == 0) { @@ -1421,7 +1434,8 @@ if (map->flags & DMAMAP_COHERENT) { if (op & BUS_DMASYNC_PREWRITE) { dsb(); - cpu_l2cache_drain_writebuf(); + if ((dmat->flags & BUS_DMA_COHERENT) == 0) + cpu_l2cache_drain_writebuf(); } return; }