Patchwork fsldma: snooping is not enabled for last entry in descriptor chain

login
register
mail settings
Submitter Ira Snyder
Date May 15, 2009, 6:33 p.m.
Message ID <20090515183320.GB858@ovro.caltech.edu>
Download mbox | patch
Permalink /patch/27276/
State Accepted, archived
Delegated to: Kumar Gala
Headers show

Comments

Ira Snyder - May 15, 2009, 6:33 p.m.
On the 83xx controller, snooping is necessary for the DMA controller to
ensure cache coherence with the CPU when transferring to/from RAM.

The last descriptor in a chain will always have the End-of-Chain interrupt
bit set, so we can set the snoop bit while adding the End-of-Chain
interrupt bit.

Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---

While working on adding the DMA_SLAVE feature, I noticed that the last
descriptor in a chain does not have the snoop bits enabled.

This is easily verified by doing the following:
1) set FSL_DMA_BCR_MAX_CNT = (1 << 18)
2) #define DEBUG 1
3) #define FSL_DMA_LD_DEBUG 1
4) setup a 1MB memcpy operation

The memcpy must be set up on an idle channel, and must be submitted
without any other transactions. dma_async_memcpy_issue_pending() must be
called without queueing any more transactions. You will see that the
snoop bit (bit 4) is not set in the last descriptor.

 drivers/dma/fsldma.c |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)

Patch

diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 4264c98..dba0b58 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -179,9 +179,14 @@  static void dma_halt(struct fsl_dma_chan *fsl_chan)
 static void set_ld_eol(struct fsl_dma_chan *fsl_chan,
 			struct fsl_desc_sw *desc)
 {
+	u64 snoop_bits;
+
+	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
+		? FSL_DMA_SNEN : 0;
+
 	desc->hw.next_ln_addr = CPU_TO_DMA(fsl_chan,
-		DMA_TO_CPU(fsl_chan, desc->hw.next_ln_addr, 64)	| FSL_DMA_EOL,
-		64);
+		DMA_TO_CPU(fsl_chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
+			| snoop_bits, 64);
 }
 
 static void append_ld_queue(struct fsl_dma_chan *fsl_chan,