summaryrefslogtreecommitdiff
path: root/drivers/dma
diff options
context:
space:
mode:
authorBiju Das <biju.das.jz@bp.renesas.com>2025-11-13 22:50:48 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-01-30 12:27:29 +0300
commit4e45ae701b81680d16ff1f79b794d20bf578c511 (patch)
treeb122aadff1cf4f4c70cde7cb9352236f89b45b1c /drivers/dma
parent6bf4ef078fd11910988889a6c0b3698d2e0c89af (diff)
downloadlinux-4e45ae701b81680d16ff1f79b794d20bf578c511.tar.xz
dmaengine: sh: rz-dmac: Fix rz_dmac_terminate_all()
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>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/sh/rz-dmac.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index f777addda8ba..d11be1884774 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -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);