lkml.org 
[lkml]   [2018]   [Apr]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 44/95] dmaengine: at_xdmac: fix rare residue corruption
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Maxime Jayat <maxime.jayat@mobile-devices.fr>

    commit c5637476bbf9bb86c7f0413b8f4822a73d8d2d07 upstream.

    Despite the efforts made to correctly read the NDA and CUBC registers,
    the order in which the registers are read could sometimes lead to an
    inconsistent state.

    Re-using the timeline from the comments, this following timing of
    registers reads could lead to reading NDA with value "@desc2" and
    CUBC with value "MAX desc1":

    INITD -------- ------------
    |____________________|
    _______________________ _______________
    NDA @desc2 \/ @desc3
    _______________________/\_______________
    __________ ___________ _______________
    CUBC 0 \/ MAX desc1 \/ MAX desc2
    __________/\___________/\_______________
    | | | |
    Events:(1)(2) (3)(4)

    (1) check_nda = @desc2
    (2) initd = 1
    (3) cur_ubc = MAX desc1
    (4) cur_nda = @desc2

    This is allowed by the condition ((check_nda == cur_nda) && initd),
    despite cur_ubc and cur_nda being in the precise state we don't want.

    This error leads to incorrect residue computation.

    Fix it by inversing the order in which CUBC and INITD are read. This
    makes sure that NDA and CUBC are always read together either _before_
    INITD goes to 0 or _after_ it is back at 1.
    The case where NDA is read before INITD is at 0 and CUBC is read after
    INITD is back at 1 will be rejected by check_nda and cur_nda being
    different.

    Fixes: 53398f488821 ("dmaengine: at_xdmac: fix residue corruption")
    Cc: stable@vger.kernel.org
    Signed-off-by: Maxime Jayat <maxime.jayat@mobile-devices.fr>
    Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
    Signed-off-by: Vinod Koul <vinod.koul@intel.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/dma/at_xdmac.c | 4 ++--
    1 file changed, 2 insertions(+), 2 deletions(-)

    --- a/drivers/dma/at_xdmac.c
    +++ b/drivers/dma/at_xdmac.c
    @@ -1473,10 +1473,10 @@ at_xdmac_tx_status(struct dma_chan *chan
    for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) {
    check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
    rmb();
    - initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
    - rmb();
    cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
    rmb();
    + initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
    + rmb();
    cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
    rmb();


    \
     
     \ /
      Last update: 2018-04-22 17:02    [W:3.172 / U:1.460 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site