Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

dmaengine: sh: rz-dmac: Add device_{pause,resume}() callbacks

The RZ/G2L SCIFA driver uses dmaengine_prep_slave_sg() to enqueue DMA
transfers and implements a timeout mechanism on RX to handle cases where
a DMA transfer does not complete. The timeout is implemented using an
hrtimer.

In the hrtimer callback, dmaengine_tx_status() is called (along with
dmaengine_pause()) to retrieve the transfer residue and handle incomplete
DMA transfers.

Add support for device_{pause, resume}() callbacks.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Link: https://patch.msgid.link/20260316133252.240348-9-claudiu.beznea.uj@bp.renesas.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Claudiu Beznea and committed by
Vinod Koul
44f991bd 21323b11

+46 -3
+46 -3
drivers/dma/sh/rz-dmac.c
··· 140 140 #define CHANNEL_8_15_COMMON_BASE 0x0700 141 141 142 142 #define CHSTAT_ER BIT(4) 143 + #define CHSTAT_SUS BIT(3) 143 144 #define CHSTAT_EN BIT(0) 144 145 145 146 #define CHCTRL_CLRINTMSK BIT(17) 146 147 #define CHCTRL_CLRSUS BIT(9) 148 + #define CHCTRL_SETSUS BIT(8) 147 149 #define CHCTRL_CLRTC BIT(6) 148 150 #define CHCTRL_CLREND BIT(5) 149 151 #define CHCTRL_CLRRQ BIT(4) ··· 807 805 if (status == DMA_COMPLETE || !txstate) 808 806 return status; 809 807 810 - scoped_guard(spinlock_irqsave, &channel->vc.lock) 808 + scoped_guard(spinlock_irqsave, &channel->vc.lock) { 809 + u32 val; 810 + 811 811 residue = rz_dmac_chan_get_residue(channel, cookie); 812 812 813 - /* if there's no residue, the cookie is complete */ 814 - if (!residue) 813 + val = rz_dmac_ch_readl(channel, CHSTAT, 1); 814 + if (val & CHSTAT_SUS) 815 + status = DMA_PAUSED; 816 + } 817 + 818 + /* if there's no residue and no paused, the cookie is complete */ 819 + if (!residue && status != DMA_PAUSED) 815 820 return DMA_COMPLETE; 816 821 817 822 dma_set_residue(txstate, residue); 818 823 819 824 return status; 825 + } 826 + 827 + static int rz_dmac_device_pause(struct dma_chan *chan) 828 + { 829 + struct rz_dmac_chan *channel = to_rz_dmac_chan(chan); 830 + u32 val; 831 + 832 + guard(spinlock_irqsave)(&channel->vc.lock); 833 + 834 + val = rz_dmac_ch_readl(channel, CHSTAT, 1); 835 + if (!(val & CHSTAT_EN)) 836 + return 0; 837 + 838 + rz_dmac_ch_writel(channel, CHCTRL_SETSUS, CHCTRL, 1); 839 + return read_poll_timeout_atomic(rz_dmac_ch_readl, val, 840 + (val & CHSTAT_SUS), 1, 1024, 841 + false, channel, CHSTAT, 1); 842 + } 843 + 844 + static int rz_dmac_device_resume(struct dma_chan *chan) 845 + { 846 + struct rz_dmac_chan *channel = to_rz_dmac_chan(chan); 847 + u32 val; 848 + 849 + guard(spinlock_irqsave)(&channel->vc.lock); 850 + 851 + /* Do not check CHSTAT_SUS but rely on HW capabilities. */ 852 + 853 + rz_dmac_ch_writel(channel, CHCTRL_CLRSUS, CHCTRL, 1); 854 + return read_poll_timeout_atomic(rz_dmac_ch_readl, val, 855 + !(val & CHSTAT_SUS), 1, 1024, 856 + false, channel, CHSTAT, 1); 820 857 } 821 858 822 859 /* ··· 1194 1153 engine->device_terminate_all = rz_dmac_terminate_all; 1195 1154 engine->device_issue_pending = rz_dmac_issue_pending; 1196 1155 engine->device_synchronize = rz_dmac_device_synchronize; 1156 + engine->device_pause = rz_dmac_device_pause; 1157 + engine->device_resume = rz_dmac_device_resume; 1197 1158 1198 1159 engine->copy_align = DMAENGINE_ALIGN_1_BYTE; 1199 1160 dma_set_max_seg_size(engine->dev, U32_MAX);