summaryrefslogtreecommitdiffstats
path: root/drivers/dma/stm32-dma.c
diff options
context:
space:
mode:
authorArnaud Pouliquen <arnaud.pouliquen@st.com>2019-05-02 05:28:42 -0400
committerVinod Koul <vkoul@kernel.org>2019-05-04 06:16:58 -0400
commit2a4885abf5fbc2dde4be91a11b00cbce2c923f47 (patch)
tree2e2522bcea427a249000ea93600d6a38a7c37170 /drivers/dma/stm32-dma.c
parent66c30aa679172df624cd68b0e1cfe757f6d1bc72 (diff)
dmaengine: stm32-dma: fix residue calculation in stm32-dma
In double buffer mode, during residue calculation, the DMA can automatically switch to the next transfer. Indeed the CT bit that gives position in the double buffer can has been updated by the hardware, during calculation. In this case the SxNDTR register value can not be trusted. If a transition is detected we consider that the DMA has switched to the beginning of next sg. Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com> Signed-off-by: Pierre-Yves MORDRET <pierre-yves.mordret@st.com> Signed-off-by: Vinod Koul <vkoul@kernel.org>
Diffstat (limited to 'drivers/dma/stm32-dma.c')
-rw-r--r--drivers/dma/stm32-dma.c90
1 files changed, 77 insertions, 13 deletions
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
index dde796686736..88d9c6c4389f 100644
--- a/drivers/dma/stm32-dma.c
+++ b/drivers/dma/stm32-dma.c
@@ -1042,33 +1042,97 @@ static u32 stm32_dma_get_remaining_bytes(struct stm32_dma_chan *chan)
1042 return ndtr << width; 1042 return ndtr << width;
1043} 1043}
1044 1044
1045/**
1046 * stm32_dma_is_current_sg - check that expected sg_req is currently transferred
1047 * @chan: dma channel
1048 *
1049 * This function called when IRQ are disable, checks that the hardware has not
1050 * switched on the next transfer in double buffer mode. The test is done by
1051 * comparing the next_sg memory address with the hardware related register
1052 * (based on CT bit value).
1053 *
1054 * Returns true if expected current transfer is still running or double
1055 * buffer mode is not activated.
1056 */
1057static bool stm32_dma_is_current_sg(struct stm32_dma_chan *chan)
1058{
1059 struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
1060 struct stm32_dma_sg_req *sg_req;
1061 u32 dma_scr, dma_smar, id;
1062
1063 id = chan->id;
1064 dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id));
1065
1066 if (!(dma_scr & STM32_DMA_SCR_DBM))
1067 return true;
1068
1069 sg_req = &chan->desc->sg_req[chan->next_sg];
1070
1071 if (dma_scr & STM32_DMA_SCR_CT) {
1072 dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM0AR(id));
1073 return (dma_smar == sg_req->chan_reg.dma_sm0ar);
1074 }
1075
1076 dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM1AR(id));
1077
1078 return (dma_smar == sg_req->chan_reg.dma_sm1ar);
1079}
1080
1045static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, 1081static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
1046 struct stm32_dma_desc *desc, 1082 struct stm32_dma_desc *desc,
1047 u32 next_sg) 1083 u32 next_sg)
1048{ 1084{
1049 u32 modulo, burst_size; 1085 u32 modulo, burst_size;
1050 u32 residue = 0; 1086 u32 residue;
1087 u32 n_sg = next_sg;
1088 struct stm32_dma_sg_req *sg_req = &chan->desc->sg_req[chan->next_sg];
1051 int i; 1089 int i;
1052 1090
1053 /* 1091 /*
1054 * In cyclic mode, for the last period, residue = remaining bytes from 1092 * Calculate the residue means compute the descriptors
1055 * NDTR 1093 * information:
1094 * - the sg_req currently transferred
1095 * - the Hardware remaining position in this sg (NDTR bits field).
1096 *
1097 * A race condition may occur if DMA is running in cyclic or double
1098 * buffer mode, since the DMA register are automatically reloaded at end
1099 * of period transfer. The hardware may have switched to the next
1100 * transfer (CT bit updated) just before the position (SxNDTR reg) is
1101 * read.
1102 * In this case the SxNDTR reg could (or not) correspond to the new
1103 * transfer position, and not the expected one.
1104 * The strategy implemented in the stm32 driver is to:
1105 * - read the SxNDTR register
1106 * - crosscheck that hardware is still in current transfer.
1107 * In case of switch, we can assume that the DMA is at the beginning of
1108 * the next transfer. So we approximate the residue in consequence, by
1109 * pointing on the beginning of next transfer.
1110 *
1111 * This race condition doesn't apply for none cyclic mode, as double
1112 * buffer is not used. In such situation registers are updated by the
1113 * software.
1056 */ 1114 */
1057 if (chan->desc->cyclic && next_sg == 0) { 1115
1058 residue = stm32_dma_get_remaining_bytes(chan); 1116 residue = stm32_dma_get_remaining_bytes(chan);
1059 goto end; 1117
1118 if (!stm32_dma_is_current_sg(chan)) {
1119 n_sg++;
1120 if (n_sg == chan->desc->num_sgs)
1121 n_sg = 0;
1122 residue = sg_req->len;
1060 } 1123 }
1061 1124
1062 /* 1125 /*
1063 * For all other periods in cyclic mode, and in sg mode, 1126 * In cyclic mode, for the last period, residue = remaining bytes
1064 * residue = remaining bytes from NDTR + remaining periods/sg to be 1127 * from NDTR,
1065 * transferred 1128 * else for all other periods in cyclic mode, and in sg mode,
1129 * residue = remaining bytes from NDTR + remaining
1130 * periods/sg to be transferred
1066 */ 1131 */
1067 for (i = next_sg; i < desc->num_sgs; i++) 1132 if (!chan->desc->cyclic || n_sg != 0)
1068 residue += desc->sg_req[i].len; 1133 for (i = n_sg; i < desc->num_sgs; i++)
1069 residue += stm32_dma_get_remaining_bytes(chan); 1134 residue += desc->sg_req[i].len;
1070 1135
1071end:
1072 if (!chan->mem_burst) 1136 if (!chan->mem_burst)
1073 return residue; 1137 return residue;
1074 1138