Skip to contentSkip to conversation

dma: dw_dmac: add dwc_chan_pause and dwc_chan_resume

PATCH Superseded Andy Shevchenko 2 participants 5 messages Dec 17, 2012 dmaengine

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 dma: dw_dmac: add dwc_chan_pause and dwc_chan_resume

We will use at least the dwc_chan_resume() later.

---
 drivers/dma/dw_dmac.c |   31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)
drivers/dma/dw_dmac.c +22 -9
index 4413f69..687af2a 100644
@@ -1008,6 +1008,26 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
 	return 0;
 }
 
+static inline void dwc_chan_pause(struct dw_dma_chan *dwc)
+{
+	u32 cfglo = channel_readl(dwc, CFG_LO);
+
+	channel_writel(dwc, CFG_LO, cfglo | DWC_CFGL_CH_SUSP);
+	while (!(channel_readl(dwc, CFG_LO) & DWC_CFGL_FIFO_EMPTY))
+		cpu_relax();
+
+	dwc->paused = true;
+}
+
+static inline void dwc_chan_resume(struct dw_dma_chan *dwc)
+{
+	u32 cfglo = channel_readl(dwc, CFG_LO);
+
+	channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP);
+
+	dwc->paused = false;
+}
+
 static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 		       unsigned long arg)
 {
@@ -1015,18 +1035,13 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 	struct dw_dma		*dw = to_dw_dma(chan->device);
 	struct dw_desc		*desc, *_desc;
 	unsigned long		flags;
-	u32			cfglo;
 	LIST_HEAD(list);
 
 	if (cmd == DMA_PAUSE) {
 		spin_lock_irqsave(&dwc->lock, flags);
 
-		cfglo = channel_readl(dwc, CFG_LO);
-		channel_writel(dwc, CFG_LO, cfglo | DWC_CFGL_CH_SUSP);
-		while (!(channel_readl(dwc, CFG_LO) & DWC_CFGL_FIFO_EMPTY))
-			cpu_relax();
+		dwc_chan_pause(dwc);
 
-		dwc->paused = true;
 		spin_unlock_irqrestore(&dwc->lock, flags);
 	} else if (cmd == DMA_RESUME) {
 		if (!dwc->paused)
@@ -1034,9 +1049,7 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 
 		spin_lock_irqsave(&dwc->lock, flags);
 
-		cfglo = channel_readl(dwc, CFG_LO);
-		channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP);
-		dwc->paused = false;
+		dwc_chan_resume(dwc);
 
 		spin_unlock_irqrestore(&dwc->lock, flags);
 	} else if (cmd == DMA_TERMINATE_ALL) {
Signature · 1 line
1.7.10.4
#1 lore raw

PATCH 2/2 dma: dw_dmac: clear suspend during termination

From: Heikki Krogerus <[email protected]>

Clear DWC_CFGL_CH_SUSP bit during termination if the channel was paused.

---
 drivers/dma/dw_dmac.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/dw_dmac.c +1 -1
index 687af2a..8d77643 100644
@@ -1059,7 +1059,7 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 
 		dwc_chan_disable(dw, dwc);
 
-		dwc->paused = false;
+		dwc_chan_resume(dwc);
 
 		/* active_list entries will end up before queued entries */
 		list_splice_init(&dwc->queue, &list);
Signature · 1 line
1.7.10.4
#2 lore raw

Re: [PATCH 2/2] dma: dw_dmac: clear suspend during termination

Quoted 7 lines · Andy Shevchenko

From: Heikki Krogerus <[email protected]>

Clear DWC_CFGL_CH_SUSP bit during termination if the channel was paused.

Insufficient commit log :(
You don't have to say here, what you are doing, but why you are doing it.

Please mention the reason here first, then repost the series after getting my comments

--
viresh

#3 lore raw

Re: [PATCH 2/2] dma: dw_dmac: clear suspend during termination

Quoted 4 lines · Viresh Kumar
Quoted 2 lines · Andy Shevchenko

From: Heikki Krogerus <[email protected]>

Quoted 8 lines
Quoted 5 lines

Clear DWC_CFGL_CH_SUSP bit during termination if the channel was paused.

Insufficient commit log :(
You don't have to say here, what you are doing, but why you are doing it.

Fighting against bug. The workflow in our case is to a) pause the dma,
b) do something in the slave driver, c) terminate all transfers, d) submit new transfer. But d) doesn't happen because the channel is still paused.

Quoted 2 lines

Please mention the reason here first, then repost the series after getting my comments

Okay.

Signature · 2 lines
Andy Shevchenko <[email protected]>
Intel Finland Oy