]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.16.4/dmaengine-at_xdmac-fix-rare-residue-corruption.patch
Fixes for 4.19
[thirdparty/kernel/stable-queue.git] / releases / 4.16.4 / dmaengine-at_xdmac-fix-rare-residue-corruption.patch
CommitLineData
7f30898e
GKH
1From c5637476bbf9bb86c7f0413b8f4822a73d8d2d07 Mon Sep 17 00:00:00 2001
2From: Maxime Jayat <maxime.jayat@mobile-devices.fr>
3Date: Thu, 22 Feb 2018 12:39:55 +0100
4Subject: dmaengine: at_xdmac: fix rare residue corruption
5
6From: Maxime Jayat <maxime.jayat@mobile-devices.fr>
7
8commit c5637476bbf9bb86c7f0413b8f4822a73d8d2d07 upstream.
9
10Despite the efforts made to correctly read the NDA and CUBC registers,
11the order in which the registers are read could sometimes lead to an
12inconsistent state.
13
14Re-using the timeline from the comments, this following timing of
15registers reads could lead to reading NDA with value "@desc2" and
16CUBC with value "MAX desc1":
17
18 INITD -------- ------------
19 |____________________|
20 _______________________ _______________
21 NDA @desc2 \/ @desc3
22 _______________________/\_______________
23 __________ ___________ _______________
24 CUBC 0 \/ MAX desc1 \/ MAX desc2
25 __________/\___________/\_______________
26 | | | |
27Events:(1)(2) (3)(4)
28
29(1) check_nda = @desc2
30(2) initd = 1
31(3) cur_ubc = MAX desc1
32(4) cur_nda = @desc2
33
34This is allowed by the condition ((check_nda == cur_nda) && initd),
35despite cur_ubc and cur_nda being in the precise state we don't want.
36
37This error leads to incorrect residue computation.
38
39Fix it by inversing the order in which CUBC and INITD are read. This
40makes sure that NDA and CUBC are always read together either _before_
41INITD goes to 0 or _after_ it is back at 1.
42The case where NDA is read before INITD is at 0 and CUBC is read after
43INITD is back at 1 will be rejected by check_nda and cur_nda being
44different.
45
46Fixes: 53398f488821 ("dmaengine: at_xdmac: fix residue corruption")
47Cc: stable@vger.kernel.org
48Signed-off-by: Maxime Jayat <maxime.jayat@mobile-devices.fr>
49Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
50Signed-off-by: Vinod Koul <vinod.koul@intel.com>
51Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
52
53---
54 drivers/dma/at_xdmac.c | 4 ++--
55 1 file changed, 2 insertions(+), 2 deletions(-)
56
57--- a/drivers/dma/at_xdmac.c
58+++ b/drivers/dma/at_xdmac.c
59@@ -1471,10 +1471,10 @@ at_xdmac_tx_status(struct dma_chan *chan
60 for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) {
61 check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
62 rmb();
63- initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
64- rmb();
65 cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
66 rmb();
67+ initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
68+ rmb();
69 cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
70 rmb();
71