diff options
author | M'boumba Cedric Madianga <cedric.madianga@gmail.com> | 2016-12-13 08:40:48 -0500 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2017-01-02 22:53:17 -0500 |
commit | 2b12c5580e0a4c0ffd513d1522dd39b2464fb207 (patch) | |
tree | 8ab19ceb150fc730169f485c105591e11a3e31e6 | |
parent | 8d1b76f031ce60c50d03674e6d1db0c5e5f55945 (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.c | 39 |
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 | ||
848 | static 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 | |||
849 | static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, | 860 | static 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 | } |