]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
dmaengine: sh: rz-dmac: Fix rz_dmac_terminate_all()
authorBiju Das <biju.das.jz@bp.renesas.com>
Thu, 13 Nov 2025 19:50:48 +0000 (19:50 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 6 Feb 2026 15:44:02 +0000 (16:44 +0100)
commit 747213b08a1ab6a76e3e3b3e7a209cc1d402b5d0 upstream.

After audio full duplex testing, playing the recorded file contains a few
playback frames from the previous time. The rz_dmac_terminate_all() does
not reset all the hardware descriptors queued previously, leading to the
wrong descriptor being picked up during the next DMA transfer. Fix the
above issue by resetting all the descriptor headers for a channel in
rz_dmac_terminate_all() as rz_dmac_lmdesc_recycle() points to the proper
descriptor header filled by the rz_dmac_prepare_descs_for_slave_sg().

Cc: stable@kernel.org
Fixes: 5000d37042a6 ("dmaengine: sh: Add DMAC driver for RZ/G2L SoC")
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Tested-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Link: https://patch.msgid.link/20251113195052.564338-1-biju.das.jz@bp.renesas.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/dma/sh/rz-dmac.c

index 2967141f4e7b2ce8c2dcff9a8f0669f2c3898116..2f40e8df64b2b82bf312092bfdf587e164a2f77a 100644 (file)
@@ -533,11 +533,16 @@ rz_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 static int rz_dmac_terminate_all(struct dma_chan *chan)
 {
        struct rz_dmac_chan *channel = to_rz_dmac_chan(chan);
+       struct rz_lmdesc *lmdesc = channel->lmdesc.base;
        unsigned long flags;
+       unsigned int i;
        LIST_HEAD(head);
 
        rz_dmac_disable_hw(channel);
        spin_lock_irqsave(&channel->vc.lock, flags);
+       for (i = 0; i < DMAC_NR_LMDESC; i++)
+               lmdesc[i].header = 0;
+
        list_splice_tail_init(&channel->ld_active, &channel->ld_free);
        list_splice_tail_init(&channel->ld_queue, &channel->ld_free);
        spin_unlock_irqrestore(&channel->vc.lock, flags);