svn commit: r203080 - head/sys/mips/mips

Alexander Kabaev kan at FreeBSD.org
Wed Jan 27 17:15:18 UTC 2010


Author: kan
Date: Wed Jan 27 17:15:17 2010
New Revision: 203080
URL: http://svn.freebsd.org/changeset/base/203080

Log:
  Do not leave dirty cache lines behind if bus_dmamap_sync was called
  to invalidate memory chunk that starts or ends in the middle of
  cache line.
  
  This was responsible for one half of the problem preventing umass
  to work reliably on some MIPS32 platforms. USBng needs to stop
  sharing cache lines between DMA-able memory and other structures
  to cure the other half.
  
  Discussed with: imp, gonzo

Modified:
  head/sys/mips/mips/busdma_machdep.c

Modified: head/sys/mips/mips/busdma_machdep.c
==============================================================================
--- head/sys/mips/mips/busdma_machdep.c	Wed Jan 27 17:03:40 2010	(r203079)
+++ head/sys/mips/mips/busdma_machdep.c	Wed Jan 27 17:15:17 2010	(r203080)
@@ -1066,10 +1066,22 @@ bus_dmamap_sync_buf(void *buf, int len, 
 			memcpy ((void*)buf_cl, tmp_cl, size_cl);
 		if (size_clend)
 			memcpy ((void*)buf_clend, tmp_clend, size_clend);
+		/* 
+		 * Copies above have brought corresponding memory
+		 * cache lines back into dirty state. Write them back
+		 * out and invalidate affected cache lines again if
+		 * necessary.
+		 */
+		if (size_cl)
+			mips_dcache_wbinv_range((vm_offset_t)buf_cl, size_cl);
+		if (size_clend && (size_cl == 0 ||
+                    buf_clend - buf_cl > mips_pdcache_linesize))
+			mips_dcache_wbinv_range((vm_offset_t)buf_clend,
+			   size_clend);
 		break;
 
 	case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE:
-		mips_dcache_wbinv_range((vm_offset_t)buf, len);
+		mips_dcache_wbinv_range((vm_offset_t)buf_cl, len);
 		break;
 
 	case BUS_DMASYNC_PREREAD:
@@ -1088,6 +1100,18 @@ bus_dmamap_sync_buf(void *buf, int len, 
 			memcpy ((void *)buf_cl, tmp_cl, size_cl);
 		if (size_clend)
 			memcpy ((void *)buf_clend, tmp_clend, size_clend);
+		/* 
+		 * Copies above have brought corresponding memory
+		 * cache lines back into dirty state. Write them back
+		 * out and invalidate affected cache lines again if
+		 * necessary.
+		 */
+		if (size_cl)
+			mips_dcache_wbinv_range((vm_offset_t)buf_cl, size_cl);
+		if (size_clend && (size_cl == 0 ||
+                    buf_clend - buf_cl > mips_pdcache_linesize))
+			mips_dcache_wbinv_range((vm_offset_t)buf_clend,
+			   size_clend);
 		break;
 
 	case BUS_DMASYNC_PREWRITE:


More information about the svn-src-all mailing list