summaryrefslogtreecommitdiffstats
path: root/sys/mips/mips/busdma_machdep.c
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2010-01-27 17:15:17 +0000
committerkan <kan@FreeBSD.org>2010-01-27 17:15:17 +0000
commit5f3c60fd26cab91d29c1c2e279031850c4688e5e (patch)
treecb4a57049aeb29cdc03ab47f68dadb16a4087951 /sys/mips/mips/busdma_machdep.c
parent20d736f89d96ce90e52941860c31c5212229bfed (diff)
downloadFreeBSD-src-5f3c60fd26cab91d29c1c2e279031850c4688e5e.zip
FreeBSD-src-5f3c60fd26cab91d29c1c2e279031850c4688e5e.tar.gz
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
Diffstat (limited to 'sys/mips/mips/busdma_machdep.c')
-rw-r--r--sys/mips/mips/busdma_machdep.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/sys/mips/mips/busdma_machdep.c b/sys/mips/mips/busdma_machdep.c
index 5271148..4e7b45f 100644
--- a/sys/mips/mips/busdma_machdep.c
+++ b/sys/mips/mips/busdma_machdep.c
@@ -1066,10 +1066,22 @@ bus_dmamap_sync_buf(void *buf, int len, bus_dmasync_op_t op)
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, bus_dmasync_op_t op)
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:
OpenPOWER on IntegriCloud