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-all mailing list