]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
dmaengine: sh: rz-dmac: Move CHCTRL updates under spinlock
authorClaudiu Beznea <claudiu.beznea@tuxon.dev>
Mon, 16 Mar 2026 13:32:46 +0000 (15:32 +0200)
committerVinod Koul <vkoul@kernel.org>
Tue, 17 Mar 2026 10:41:11 +0000 (16:11 +0530)
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>
drivers/dma/sh/rz-dmac.c

index 089e1ab29159490c17179d4e0cc88d165e865dc7..f30bdf69c7408ecab1ded4c988e80a5f20f6cf77 100644 (file)
@@ -297,13 +297,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)
@@ -568,8 +565,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;
 
@@ -706,7 +703,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;
        }