Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 31 Dec 2012 21:00:38 +0000 (UTC)
From:      Oleksandr Tymoshenko <gonzo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r244912 - head/sys/arm/arm
Message-ID:  <201212312100.qBVL0c8Q006103@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gonzo
Date: Mon Dec 31 21:00:38 2012
New Revision: 244912
URL: http://svnweb.freebsd.org/changeset/base/244912

Log:
  Merge r234561 from busdma_machdep.c to ARMv6 version of busdma:
  
  Interrupts must be disabled while handling a partial cache line flush,
  as otherwise the interrupt handling code may modify data in the non-DMA
  part of the cache line while we have it stashed away in the temporary
  stack buffer, then we end up restoring a stale value.
  
  PR:             160431
  Submitted by:   Ian Lepore

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	Mon Dec 31 16:52:52 2012	(r244911)
+++ head/sys/arm/arm/busdma_machdep-v6.c	Mon Dec 31 21:00:38 2012	(r244912)
@@ -1347,35 +1347,49 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
 			while (sl != NULL) {
 					/* write back the unaligned portions */
 				vm_paddr_t physaddr;
+				register_t s = 0;
+
 				buf = sl->vaddr;
 				len = sl->datacount;
 				physaddr = sl->busaddr;
 				bbuf = buf & ~arm_dcache_align_mask;
 				ebuf = buf + len;
 				physaddr = physaddr & ~arm_dcache_align_mask;
-				unalign = buf & arm_dcache_align_mask;
-				if (unalign) {
-					memcpy(_tmp_cl, (void *)bbuf, unalign);
-					len += unalign; /* inv entire cache line */
-				}
-				unalign = ebuf & arm_dcache_align_mask;
-				if (unalign) {
-					unalign = arm_dcache_align - unalign;
-					memcpy(_tmp_clend, (void *)ebuf, unalign);
-					len += unalign; /* inv entire cache line */
+
+
+				if ((buf & arm_dcache_align_mask) ||
+				    (ebuf & arm_dcache_align_mask)) {
+					s = intr_disable();
+					unalign = buf & arm_dcache_align_mask;
+					if (unalign) {
+						memcpy(_tmp_cl, (void *)bbuf, unalign);
+						len += unalign; /* inv entire cache line */
+					}
+
+					unalign = ebuf & arm_dcache_align_mask;
+					if (unalign) {
+						unalign = arm_dcache_align - unalign;
+						memcpy(_tmp_clend, (void *)ebuf, unalign);
+						len += unalign; /* inv entire cache line */
+					}
 				}
-					/* inv are cache length aligned */
+
+				/* inv are cache length aligned */
 				cpu_dcache_inv_range(bbuf, len);
 				l2cache_inv_range(bbuf, physaddr, len);
 
-				unalign = (vm_offset_t)buf & arm_dcache_align_mask;
-				if (unalign) {
-					memcpy((void *)bbuf, _tmp_cl, unalign);
-				}
-				unalign = ebuf & arm_dcache_align_mask;
-				if (unalign) {
-					unalign = arm_dcache_align - unalign;
-					memcpy((void *)ebuf, _tmp_clend, unalign);
+				if ((buf & arm_dcache_align_mask) ||
+				    (ebuf & arm_dcache_align_mask)) {
+					unalign = (vm_offset_t)buf & arm_dcache_align_mask;
+					if (unalign)
+						memcpy((void *)bbuf, _tmp_cl, unalign);
+
+					unalign = ebuf & arm_dcache_align_mask;
+					if (unalign)
+						memcpy((void *)ebuf, _tmp_clend,
+						    arm_dcache_align - unalign);
+
+					intr_restore(s);
 				}
 				sl = STAILQ_NEXT(sl, slinks);
 			}



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