aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorM'boumba Cedric Madianga <cedric.madianga@gmail.com>2016-12-13 08:40:48 -0500
committerVinod Koul <vinod.koul@intel.com>2017-01-02 22:53:17 -0500
commit2b12c5580e0a4c0ffd513d1522dd39b2464fb207 (patch)
tree8ab19ceb150fc730169f485c105591e11a3e31e6
parent8d1b76f031ce60c50d03674e6d1db0c5e5f55945 (diff)
dmaengine: stm32-dma: Fix residue computation issue in cyclic mode
This patch resolves the residue computation issue detected in cyclic mode. Now, in cyclic mode, we increment next_sg variable as soon as a period is transferred instead of after pushing a new sg request. Then, we take into account that after transferring a complete buffer, the next_sg variable is equal to 0. Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com> Reviewed-by: Ludovic BARRE <ludovic.barre@st.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--drivers/dma/stm32-dma.c39
1 files changed, 26 insertions, 13 deletions
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
index a8c2ad686173..8a29b028d39e 100644
--- a/drivers/dma/stm32-dma.c
+++ b/drivers/dma/stm32-dma.c
@@ -500,8 +500,6 @@ static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan)
500 dev_dbg(chan2dev(chan), "CT=0 <=> SM1AR: 0x%08x\n", 500 dev_dbg(chan2dev(chan), "CT=0 <=> SM1AR: 0x%08x\n",
501 stm32_dma_read(dmadev, STM32_DMA_SM1AR(id))); 501 stm32_dma_read(dmadev, STM32_DMA_SM1AR(id)));
502 } 502 }
503
504 chan->next_sg++;
505 } 503 }
506} 504}
507 505
@@ -510,6 +508,7 @@ static void stm32_dma_handle_chan_done(struct stm32_dma_chan *chan)
510 if (chan->desc) { 508 if (chan->desc) {
511 if (chan->desc->cyclic) { 509 if (chan->desc->cyclic) {
512 vchan_cyclic_callback(&chan->desc->vdesc); 510 vchan_cyclic_callback(&chan->desc->vdesc);
511 chan->next_sg++;
513 stm32_dma_configure_next_sg(chan); 512 stm32_dma_configure_next_sg(chan);
514 } else { 513 } else {
515 chan->busy = false; 514 chan->busy = false;
@@ -846,26 +845,40 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
846 return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); 845 return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
847} 846}
848 847
848static u32 stm32_dma_get_remaining_bytes(struct stm32_dma_chan *chan)
849{
850 u32 dma_scr, width, ndtr;
851 struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
852
853 dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id));
854 width = STM32_DMA_SCR_PSIZE_GET(dma_scr);
855 ndtr = stm32_dma_read(dmadev, STM32_DMA_SNDTR(chan->id));
856
857 return ndtr << width;
858}
859
849static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, 860static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
850 struct stm32_dma_desc *desc, 861 struct stm32_dma_desc *desc,
851 u32 next_sg) 862 u32 next_sg)
852{ 863{
853 struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); 864 u32 residue = 0;
854 u32 dma_scr, width, residue, count;
855 int i; 865 int i;
856 866
857 residue = 0; 867 /*
868 * In cyclic mode, for the last period, residue = remaining bytes from
869 * NDTR
870 */
871 if (chan->desc->cyclic && next_sg == 0)
872 return stm32_dma_get_remaining_bytes(chan);
858 873
874 /*
875 * For all other periods in cyclic mode, and in sg mode,
876 * residue = remaining bytes from NDTR + remaining periods/sg to be
877 * transferred
878 */
859 for (i = next_sg; i < desc->num_sgs; i++) 879 for (i = next_sg; i < desc->num_sgs; i++)
860 residue += desc->sg_req[i].len; 880 residue += desc->sg_req[i].len;
861 881 residue += stm32_dma_get_remaining_bytes(chan);
862 if (next_sg != 0) {
863 dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id));
864 width = STM32_DMA_SCR_PSIZE_GET(dma_scr);
865 count = stm32_dma_read(dmadev, STM32_DMA_SNDTR(chan->id));
866
867 residue += count << width;
868 }
869 882
870 return residue; 883 return residue;
871} 884}