Page MenuHomeFreeBSD

D26735.diff
No OneTemporary

D26735.diff

Index: head/sys/arm64/arm64/busdma_bounce.c
===================================================================
--- head/sys/arm64/arm64/busdma_bounce.c
+++ head/sys/arm64/arm64/busdma_bounce.c
@@ -501,13 +501,6 @@
bounce_bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
bus_dmamap_t *mapp)
{
- /*
- * XXX ARM64TODO:
- * This bus_dma implementation requires IO-Coherent architecutre.
- * If IO-Coherency is not guaranteed, the BUS_DMA_COHERENT flag has
- * to be implented using non-cacheable memory.
- */
-
vm_memattr_t attr;
int mflags;
@@ -830,7 +823,19 @@
sgsize = MIN(buflen, dmat->common.maxsegsz);
if (map->pagesneeded != 0 &&
must_bounce(dmat, map, curaddr, sgsize)) {
- sgsize = MIN(sgsize, PAGE_SIZE - (curaddr & PAGE_MASK));
+ /*
+ * The attempt to split a physically continuous buffer
+ * seems very controversial, it's unclear whether we
+ * can do this in all cases. Also, memory for bounced
+ * buffers is allocated as pages, so we cannot
+ * guarantee multipage alignment.
+ */
+ KASSERT(dmat->common.alignment <= PAGE_SIZE,
+ ("bounced buffer cannot have alignment bigger "
+ "than PAGE_SIZE: %lu", dmat->common.alignment));
+ sgsize = PAGE_SIZE - (curaddr & PAGE_MASK);
+ sgsize = roundup2(sgsize, dmat->common.alignment);
+ sgsize = MIN(sgsize, dmat->common.maxsegsz);
curaddr = add_bounce_page(dmat, map, 0, curaddr,
sgsize);
} else if ((map->flags & DMAMAP_COHERENT) == 0) {
@@ -843,11 +848,11 @@
sl++;
sl->vaddr = 0;
sl->paddr = curaddr;
- sl->datacount = sgsize;
sl->pages = PHYS_TO_VM_PAGE(curaddr);
KASSERT(sl->pages != NULL,
("%s: page at PA:0x%08lx is not in "
"vm_page_array", __func__, curaddr));
+ sl->datacount = sgsize;
} else
sl->datacount += sgsize;
}
@@ -880,6 +885,11 @@
vm_offset_t kvaddr, vaddr, sl_vend;
int error;
+ KASSERT((map->flags & DMAMAP_FROM_DMAMEM) != 0 ||
+ dmat->common.alignment <= PAGE_SIZE,
+ ("loading user buffer with alignment bigger than PAGE_SIZE is not "
+ "supported"));
+
if (segs == NULL)
segs = dmat->segments;
@@ -895,6 +905,11 @@
}
}
+ /*
+ * XXX Optimally we should parse input buffer for physically
+ * continuous segments first and then pass these segment into
+ * load loop.
+ */
sl = map->slist + map->sync_count - 1;
vaddr = (vm_offset_t)buf;
sl_pend = 0;
@@ -916,15 +931,25 @@
* Compute the segment size, and adjust counts.
*/
max_sgsize = MIN(buflen, dmat->common.maxsegsz);
- sgsize = PAGE_SIZE - (curaddr & PAGE_MASK);
+ if ((map->flags & DMAMAP_FROM_DMAMEM) != 0) {
+ sgsize = max_sgsize;
+ } else {
+ sgsize = PAGE_SIZE - (curaddr & PAGE_MASK);
+ sgsize = MIN(sgsize, max_sgsize);
+ }
+
if (map->pagesneeded != 0 &&
must_bounce(dmat, map, curaddr, sgsize)) {
+ /* See comment in bounce_bus_dmamap_load_phys */
+ KASSERT(dmat->common.alignment <= PAGE_SIZE,
+ ("bounced buffer cannot have alignment bigger "
+ "than PAGE_SIZE: %lu", dmat->common.alignment));
+ sgsize = PAGE_SIZE - (curaddr & PAGE_MASK);
sgsize = roundup2(sgsize, dmat->common.alignment);
sgsize = MIN(sgsize, max_sgsize);
curaddr = add_bounce_page(dmat, map, kvaddr, curaddr,
sgsize);
} else if ((map->flags & DMAMAP_COHERENT) == 0) {
- sgsize = MIN(sgsize, max_sgsize);
if (map->sync_count > 0) {
sl_pend = sl->paddr + sl->datacount;
sl_vend = sl->vaddr + sl->datacount;
@@ -934,7 +959,7 @@
(kvaddr != 0 && kvaddr != sl_vend) ||
(curaddr != sl_pend)) {
if (++map->sync_count > dmat->common.nsegments)
- goto cleanup;
+ break;
sl++;
sl->vaddr = kvaddr;
sl->paddr = curaddr;
@@ -950,8 +975,6 @@
sl->datacount = sgsize;
} else
sl->datacount += sgsize;
- } else {
- sgsize = MIN(sgsize, max_sgsize);
}
sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
segp);
@@ -961,7 +984,6 @@
buflen -= sgsize;
}
-cleanup:
/*
* Did we fit?
*/

File Metadata

Mime Type
text/plain
Expires
Mon, Jul 6, 11:22 PM (11 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34772951
Default Alt Text
D26735.diff (3 KB)

Event Timeline