Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 22 Nov 2014 03:03:12 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r274839 - head/sys/arm/arm
Message-ID:  <201411220303.sAM33C5o035310@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sat Nov 22 03:03:11 2014
New Revision: 274839
URL: https://svnweb.freebsd.org/changeset/base/274839

Log:
  When doing a PREREAD sync of an mbuf-type dma buffer, do a writeback of
  the first cacheline if the buffer start address is not on a cacheline
  boundary.  Normally a buffer which is not cacheline-aligned is bounced,
  but a special rule applies for mbufs, which are always misaligned due to
  the header.  We know the cpu will not write to the header while dma is in
  progress (so we've been told anyway), but it may have written to the
  header shortly before starting a read, so we need to flush that write out
  to memory before invalidating the whole buffer.
  
  In collaboration with Mical Meloun and Svata Kraus.

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	Sat Nov 22 02:44:39 2014	(r274838)
+++ head/sys/arm/arm/busdma_machdep-v6.c	Sat Nov 22 03:03:11 2014	(r274839)
@@ -1456,7 +1456,24 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
 			break;
 
 		case BUS_DMASYNC_PREREAD:
+			/*
+			 * An mbuf may start in the middle of a cacheline. There
+			 * will be no cpu writes to the beginning of that line
+			 * (which contains the mbuf header) while dma is in
+			 * progress.  Handle that case by doing a writeback of
+			 * just the first cacheline before invalidating the
+			 * overall buffer.  Any mbuf in a chain may have this
+			 * misalignment.  Buffers which are not mbufs bounce if
+			 * they are not aligned to a cacheline.
+			 */
 			while (sl != end) {
+				if (sl->vaddr & arm_dcache_align_mask) {
+					KASSERT(map->flags & DMAMAP_MBUF,
+					    ("unaligned buffer is not an mbuf"));
+					cpu_dcache_wb_range(sl->vaddr, 1);
+					l2cache_wb_range(sl->vaddr,
+					    sl->busaddr, 1);
+				}
 				cpu_dcache_inv_range(sl->vaddr, sl->datacount);
 				l2cache_inv_range(sl->vaddr, sl->busaddr, 
 				    sl->datacount);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201411220303.sAM33C5o035310>