]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.14.111/dmaengine-tegra-avoid-overflow-of-byte-tracking.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.14.111 / dmaengine-tegra-avoid-overflow-of-byte-tracking.patch
CommitLineData
04fd09d4
SL
1From fdec0ac5e8f3bf2a5ccb0cca2e4326eacb70ee02 Mon Sep 17 00:00:00 2001
2From: Ben Dooks <ben.dooks@codethink.co.uk>
3Date: Wed, 21 Nov 2018 16:13:19 +0000
4Subject: dmaengine: tegra: avoid overflow of byte tracking
5
6[ Upstream commit e486df39305864604b7e25f2a95d51039517ac57 ]
7
8The dma_desc->bytes_transferred counter tracks the number of bytes
9moved by the DMA channel. This is then used to calculate the information
10passed back in the in the tegra_dma_tx_status callback, which is usually
11fine.
12
13When the DMA channel is configured as continous, then the bytes_transferred
14counter will increase over time and eventually overflow to become negative
15so the residue count will become invalid and the ALSA sound-dma code will
16report invalid hardware pointer values to the application. This results in
17some users becoming confused about the playout position and putting audio
18data in the wrong place.
19
20To fix this issue, always ensure the bytes_transferred field is modulo the
21size of the request. We only do this for the case of the cyclic transfer
22done ISR as anyone attempting to move 2GiB of DMA data in one transfer
23is unlikely.
24
25Note, we don't fix the issue that we should /never/ transfer a negative
26number of bytes so we could make those fields unsigned.
27
28Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
29Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
30Acked-by: Jon Hunter <jonathanh@nvidia.com>
31Signed-off-by: Vinod Koul <vkoul@kernel.org>
32Signed-off-by: Sasha Levin <sashal@kernel.org>
33---
34 drivers/dma/tegra20-apb-dma.c | 5 ++++-
35 1 file changed, 4 insertions(+), 1 deletion(-)
36
37diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
38index b9d75a54c896..7db2766b5fe9 100644
39--- a/drivers/dma/tegra20-apb-dma.c
40+++ b/drivers/dma/tegra20-apb-dma.c
41@@ -635,7 +635,10 @@ static void handle_cont_sngl_cycle_dma_done(struct tegra_dma_channel *tdc,
42
43 sgreq = list_first_entry(&tdc->pending_sg_req, typeof(*sgreq), node);
44 dma_desc = sgreq->dma_desc;
45- dma_desc->bytes_transferred += sgreq->req_len;
46+ /* if we dma for long enough the transfer count will wrap */
47+ dma_desc->bytes_transferred =
48+ (dma_desc->bytes_transferred + sgreq->req_len) %
49+ dma_desc->bytes_requested;
50
51 /* Callback need to be call */
52 if (!dma_desc->cb_count)
53--
542.19.1
55