diff mbox series

[07/25] dmaengine: dw-edma: Don't permit non-inc interleaved xfers

Message ID 20220324014836.19149-8-Sergey.Semin@baikalelectronics.ru (mailing list archive)
State Superseded
Headers show
Series dmaengine: dw-edma: Add RP/EP local DMA controllers support | expand

Commit Message

Serge Semin March 24, 2022, 1:48 a.m. UTC
DW eDMA controller always increments both source and destination
addresses. Permitting DMA interleaved transfers with no src_inc/dst_inc
flags set may lead to unexpected behaviour for the device users. Let's fix
that by terminating the interleaved transfers if at least one of the
dma_interleaved_template.{src_inc,dst_inc} flag is initialized with false
value. Note in addition to that we need we need to increase the source and
destination addresses accordingly after each iteration.

Fixes: 85e7518f42c8 ("dmaengine: dw-edma: Add device_prep_interleave_dma() support")
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
---
 drivers/dma/dw-edma/dw-edma-core.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

Comments

Serge Semin April 17, 2022, 10:59 p.m. UTC | #1
On Thu, Mar 24, 2022 at 10:45:12PM +0530, Manivannan Sadhasivam wrote:
> On Thu, Mar 24, 2022 at 04:48:18AM +0300, Serge Semin wrote:
> > DW eDMA controller always increments both source and destination
> > addresses. Permitting DMA interleaved transfers with no src_inc/dst_inc
> > flags set may lead to unexpected behaviour for the device users. Let's fix
> > that by terminating the interleaved transfers if at least one of the
> > dma_interleaved_template.{src_inc,dst_inc} flag is initialized with false
> > value. Note in addition to that we need we need to increase the source and
> > destination addresses accordingly after each iteration.
> > 
> 

> Can you please point me where this gets documented in databook?

10.3.1 Source and Destination Address Registers (SAR, DAR)
"...  You program the start of the local and remote data buffers using
these registers, and the DMA increments the SAR and DAR as the DMA
transfer progresses. ..."

[1] DesignWare Cores PCI Express Controller databook, v4.70a, March 2016,
    p. 882.
[2] DesignWare Cores PCI Express Controller databook, v5.40a, March 2019,
    p. 1110.

-Sergey

> 
> Thanks,
> Mani
> 
> > Fixes: 85e7518f42c8 ("dmaengine: dw-edma: Add device_prep_interleave_dma() support")
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > ---
> >  drivers/dma/dw-edma/dw-edma-core.c | 12 ++++++------
> >  1 file changed, 6 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
> > index 2010d7f8191f..f41bde27795c 100644
> > --- a/drivers/dma/dw-edma/dw-edma-core.c
> > +++ b/drivers/dma/dw-edma/dw-edma-core.c
> > @@ -386,6 +386,8 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
> >  			return NULL;
> >  		if (xfer->xfer.il->numf > 0 && xfer->xfer.il->frame_size > 0)
> >  			return NULL;
> > +		if (!xfer->xfer.il->src_inc || !xfer->xfer.il->dst_inc)
> > +			return NULL;
> >  	} else {
> >  		return NULL;
> >  	}
> > @@ -485,15 +487,13 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
> >  			struct dma_interleaved_template *il = xfer->xfer.il;
> >  			struct data_chunk *dc = &il->sgl[i];
> >  
> > -			if (il->src_sgl) {
> > -				src_addr += burst->sz;
> > +			src_addr += burst->sz;
> > +			if (il->src_sgl)
> >  				src_addr += dmaengine_get_src_icg(il, dc);
> > -			}
> >  
> > -			if (il->dst_sgl) {
> > -				dst_addr += burst->sz;
> > +			dst_addr += burst->sz;
> > +			if (il->dst_sgl)
> >  				dst_addr += dmaengine_get_dst_icg(il, dc);
> > -			}
> >  		}
> >  	}
> >  
> > -- 
> > 2.35.1
> >
diff mbox series

Patch

diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 2010d7f8191f..f41bde27795c 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -386,6 +386,8 @@  dw_edma_device_transfer(struct dw_edma_transfer *xfer)
 			return NULL;
 		if (xfer->xfer.il->numf > 0 && xfer->xfer.il->frame_size > 0)
 			return NULL;
+		if (!xfer->xfer.il->src_inc || !xfer->xfer.il->dst_inc)
+			return NULL;
 	} else {
 		return NULL;
 	}
@@ -485,15 +487,13 @@  dw_edma_device_transfer(struct dw_edma_transfer *xfer)
 			struct dma_interleaved_template *il = xfer->xfer.il;
 			struct data_chunk *dc = &il->sgl[i];
 
-			if (il->src_sgl) {
-				src_addr += burst->sz;
+			src_addr += burst->sz;
+			if (il->src_sgl)
 				src_addr += dmaengine_get_src_icg(il, dc);
-			}
 
-			if (il->dst_sgl) {
-				dst_addr += burst->sz;
+			dst_addr += burst->sz;
+			if (il->dst_sgl)
 				dst_addr += dmaengine_get_dst_icg(il, dc);
-			}
 		}
 	}