summaryrefslogtreecommitdiff
path: root/drivers/dma
diff options
context:
space:
mode:
authorClaudiu Beznea <claudiu.beznea@tuxon.dev>2026-03-16 15:32:46 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-04-11 14:16:15 +0200
commit0356c8e0e5cf3c0d633c189bb12ac75aeb57a859 (patch)
treed61addc1e35e2950201087fb16801df695fca5ab /drivers/dma
parent96708f9398102f9297b3d8538bcc88d94d53671b (diff)
downloadlinux-0356c8e0e5cf3c0d633c189bb12ac75aeb57a859.tar.gz
linux-0356c8e0e5cf3c0d633c189bb12ac75aeb57a859.tar.bz2
linux-0356c8e0e5cf3c0d633c189bb12ac75aeb57a859.zip
dmaengine: sh: rz-dmac: Move CHCTRL updates under spinlock
commit 89a8567d84bde88cb7cdbbac2ab2299c4f991490 upstream. Both rz_dmac_disable_hw() and rz_dmac_irq_handle_channel() update the CHCTRL register. To avoid concurrency issues when configuring functionalities exposed by this registers, take the virtual channel lock. All other CHCTRL updates were already protected by the same lock. Previously, rz_dmac_disable_hw() disabled and re-enabled local IRQs, before accessing CHCTRL registers but this does not ensure race-free access. Remove the local IRQ disable/enable code as well. Fixes: 5000d37042a6 ("dmaengine: sh: Add DMAC driver for RZ/G2L SoC") Cc: stable@vger.kernel.org Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com> Link: https://patch.msgid.link/20260316133252.240348-3-claudiu.beznea.uj@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.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index f61b7362e976..498e6e24ab0a 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -286,13 +286,10 @@ static void rz_dmac_disable_hw(struct rz_dmac_chan *channel)
{
struct dma_chan *chan = &channel->vc.chan;
struct rz_dmac *dmac = to_rz_dmac(chan->device);
- unsigned long flags;
dev_dbg(dmac->dev, "%s channel %d\n", __func__, channel->index);
- local_irq_save(flags);
rz_dmac_ch_writel(channel, CHCTRL_DEFAULT, CHCTRL, 1);
- local_irq_restore(flags);
}
static void rz_dmac_set_dmars_register(struct rz_dmac *dmac, int nr, u32 dmars)
@@ -545,8 +542,8 @@ static int rz_dmac_terminate_all(struct dma_chan *chan)
unsigned int i;
LIST_HEAD(head);
- rz_dmac_disable_hw(channel);
spin_lock_irqsave(&channel->vc.lock, flags);
+ rz_dmac_disable_hw(channel);
for (i = 0; i < DMAC_NR_LMDESC; i++)
lmdesc[i].header = 0;
@@ -676,7 +673,9 @@ static void rz_dmac_irq_handle_channel(struct rz_dmac_chan *channel)
if (chstat & CHSTAT_ER) {
dev_err(dmac->dev, "DMAC err CHSTAT_%d = %08X\n",
channel->index, chstat);
- rz_dmac_ch_writel(channel, CHCTRL_DEFAULT, CHCTRL, 1);
+
+ scoped_guard(spinlock_irqsave, &channel->vc.lock)
+ rz_dmac_ch_writel(channel, CHCTRL_DEFAULT, CHCTRL, 1);
goto done;
}