svn commit: r291018 - head/sys/arm/arm
Michal Meloun
mmel at FreeBSD.org
Wed Nov 18 16:07:03 UTC 2015
Author: mmel
Date: Wed Nov 18 16:07:01 2015
New Revision: 291018
URL: https://svnweb.freebsd.org/changeset/base/291018
Log:
ARM: Fix dma_dcache_sync() for early allocated memory.
Drivers can request DMA to buffers that are not in memory represented
in the vm page arrays. Because of this, store KVA of already mapped
buffer to synclist and use it in dma_dcache_sync().
Reviewed by: jah
Approved by: kib (mentor)
Differential Revision: https://reviews.freebsd.org/D4120
Modified:
head/sys/arm/arm/busdma_machdep-v6.c
Modified: head/sys/arm/arm/busdma_machdep-v6.c
==============================================================================
--- head/sys/arm/arm/busdma_machdep-v6.c Wed Nov 18 15:12:24 2015 (r291017)
+++ head/sys/arm/arm/busdma_machdep-v6.c Wed Nov 18 16:07:01 2015 (r291018)
@@ -117,8 +117,8 @@ struct bounce_page {
struct sync_list {
vm_offset_t vaddr; /* kva of client data */
+ bus_addr_t paddr; /* physical address */
vm_page_t pages; /* starting page of client data */
- vm_offset_t dataoffs; /* page offset of client data */
bus_size_t datacount; /* client data count */
};
@@ -1076,17 +1076,19 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat
sgsize);
} else {
if (map->sync_count > 0)
- sl_end = VM_PAGE_TO_PHYS(sl->pages) +
- sl->dataoffs + sl->datacount;
+ sl_end = sl->paddr + sl->datacount;
if (map->sync_count == 0 || curaddr != sl_end) {
if (++map->sync_count > dmat->nsegments)
break;
sl++;
sl->vaddr = 0;
+ sl->paddr = curaddr;
sl->datacount = sgsize;
sl->pages = PHYS_TO_VM_PAGE(curaddr);
- sl->dataoffs = curaddr & PAGE_MASK;
+ KASSERT(sl->pages != NULL,
+ ("%s: page at PA:0x%08lx is not in "
+ "vm_page_array", __func__, curaddr));
} else
sl->datacount += sgsize;
}
@@ -1188,8 +1190,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm
sgsize);
} else {
if (map->sync_count > 0) {
- sl_pend = VM_PAGE_TO_PHYS(sl->pages) +
- sl->dataoffs + sl->datacount;
+ sl_pend = sl->paddr + sl->datacount;
sl_vend = sl->vaddr + sl->datacount;
}
@@ -1201,9 +1202,17 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm
goto cleanup;
sl++;
sl->vaddr = kvaddr;
+ sl->paddr = curaddr;
+ if (kvaddr != 0) {
+ sl->pages = NULL;
+ } else {
+ 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;
- sl->pages = PHYS_TO_VM_PAGE(curaddr);
- sl->dataoffs = curaddr & PAGE_MASK;
} else
sl->datacount += sgsize;
}
@@ -1299,10 +1308,10 @@ dma_dcache_sync(struct sync_list *sl, bu
vm_offset_t va, tempva;
bus_size_t size;
- offset = sl->dataoffs;
+ offset = sl->paddr & PAGE_MASK;
m = sl->pages;
size = sl->datacount;
- pa = VM_PAGE_TO_PHYS(m) | offset;
+ pa = sl->paddr;
for ( ; size != 0; size -= len, pa += len, offset = 0, ++m) {
tempva = 0;
@@ -1310,13 +1319,13 @@ dma_dcache_sync(struct sync_list *sl, bu
len = min(PAGE_SIZE - offset, size);
tempva = pmap_quick_enter_page(m);
va = tempva | offset;
+ KASSERT(pa == (VM_PAGE_TO_PHYS(m) | offset),
+ ("unexpected vm_page_t phys: 0x%08x != 0x%08x",
+ VM_PAGE_TO_PHYS(m) | offset, pa));
} else {
len = sl->datacount;
va = sl->vaddr;
}
- KASSERT(pa == (VM_PAGE_TO_PHYS(m) | offset),
- ("unexpected vm_page_t phys: 0x%08x != 0x%08x",
- VM_PAGE_TO_PHYS(m) | offset, pa));
switch (op) {
case BUS_DMASYNC_PREWRITE:
More information about the svn-src-head
mailing list