Index: interface/vchiq_arm/vchiq_2835_arm.c =================================================================== --- interface/vchiq_arm/vchiq_2835_arm.c (revision 278430) +++ interface/vchiq_arm/vchiq_2835_arm.c (working copy) @@ -353,6 +353,16 @@ * Local functions */ +static void +pagelist_page_free(vm_page_t pp) +{ + vm_page_lock(pp); + vm_page_unwire(pp, PQ_INACTIVE); + if (pp->wire_count == 0 && pp->object == NULL) + vm_page_free(pp); + vm_page_unlock(pp); +} + /* There is a potential problem with partial cache lines (pages?) ** at the ends of the block when reading. If the CPU accessed anything in ** the same line (page?) then it may have pulled old data into the cache, @@ -406,8 +416,6 @@ NULL, NULL, /* lockfunc, lockarg */ &bi->pagelist_dma_tag); - - err = bus_dmamem_alloc(bi->pagelist_dma_tag, (void **)&pagelist, BUS_DMA_COHERENT | BUS_DMA_WAITOK, &bi->pagelist_dma_map); if (err) { @@ -444,6 +452,13 @@ return (-ENOMEM); } + for (i = 0; i < actual_pages; i++) { + vm_page_lock(pages[i]); + vm_page_wire(pages[i]); + vm_page_unhold(pages[i]); + vm_page_unlock(pages[i]); + } + pagelist->length = count; pagelist->type = type; pagelist->offset = offset; @@ -496,9 +511,10 @@ g_fragments_base); } - /* XXX: optimize? INV operation for read WBINV for write? */ cpu_dcache_wbinv_range((vm_offset_t)buf, count); + bus_dmamap_sync(bi->pagelist_dma_tag, bi->pagelist_dma_map, BUS_DMASYNC_PREWRITE); + bi->pagelist = pagelist; return 0; @@ -563,12 +579,12 @@ } for (i = 0; i < num_pages; i++) { - if (pagelist->type != PAGELIST_WRITE) + if (pagelist->type != PAGELIST_WRITE) { vm_page_dirty(pages[i]); + pagelist_page_free(pages[i]); + } } - vm_page_unhold_pages(pages, num_pages); - bus_dmamap_unload(bi->pagelist_dma_tag, bi->pagelist_dma_map); bus_dmamem_free(bi->pagelist_dma_tag, bi->pagelist, bi->pagelist_dma_map); bus_dmamap_destroy(bi->pagelist_dma_tag, bi->pagelist_dma_map);