Commit 72a6e35d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'dmaengine-fix-5.1-rc7' of git://git.infradead.org/users/vkoul/slave-dma

Pull dmaengine fixes from Vinod Koul:

 - fix for wrong register use in mediatek driver

 - fix in sh driver for glitch is tx_status and treating 0 a valid
   residue for cyclic

 - fix in bcm driver for using right memory allocation flag

* tag 'dmaengine-fix-5.1-rc7' of git://git.infradead.org/users/vkoul/slave-dma:
  dmaengine: mediatek-cqdma: fix wrong register usage in mtk_cqdma_start
  dmaengine: sh: rcar-dmac: Fix glitch in dmaengine_tx_status
  dmaengine: sh: rcar-dmac: With cyclic DMA residue 0 is valid
  dmaengine: bcm2835: Avoid GFP_KERNEL in device_prep_slave_sg
parents 25cce03b 5bb5c3a3
...@@ -671,7 +671,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( ...@@ -671,7 +671,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg(
d = bcm2835_dma_create_cb_chain(chan, direction, false, d = bcm2835_dma_create_cb_chain(chan, direction, false,
info, extra, info, extra,
frames, src, dst, 0, 0, frames, src, dst, 0, 0,
GFP_KERNEL); GFP_NOWAIT);
if (!d) if (!d)
return NULL; return NULL;
......
...@@ -253,7 +253,7 @@ static void mtk_cqdma_start(struct mtk_cqdma_pchan *pc, ...@@ -253,7 +253,7 @@ static void mtk_cqdma_start(struct mtk_cqdma_pchan *pc,
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
mtk_dma_set(pc, MTK_CQDMA_DST2, cvd->dest >> MTK_CQDMA_ADDR2_SHFIT); mtk_dma_set(pc, MTK_CQDMA_DST2, cvd->dest >> MTK_CQDMA_ADDR2_SHFIT);
#else #else
mtk_dma_set(pc, MTK_CQDMA_SRC2, 0); mtk_dma_set(pc, MTK_CQDMA_DST2, 0);
#endif #endif
/* setup the length */ /* setup the length */
......
...@@ -1282,6 +1282,9 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan, ...@@ -1282,6 +1282,9 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
enum dma_status status; enum dma_status status;
unsigned int residue = 0; unsigned int residue = 0;
unsigned int dptr = 0; unsigned int dptr = 0;
unsigned int chcrb;
unsigned int tcrb;
unsigned int i;
if (!desc) if (!desc)
return 0; return 0;
...@@ -1329,6 +1332,24 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan, ...@@ -1329,6 +1332,24 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
return 0; return 0;
} }
/*
* We need to read two registers.
* Make sure the control register does not skip to next chunk
* while reading the counter.
* Trying it 3 times should be enough: Initial read, retry, retry
* for the paranoid.
*/
for (i = 0; i < 3; i++) {
chcrb = rcar_dmac_chan_read(chan, RCAR_DMACHCRB) &
RCAR_DMACHCRB_DPTR_MASK;
tcrb = rcar_dmac_chan_read(chan, RCAR_DMATCRB);
/* Still the same? */
if (chcrb == (rcar_dmac_chan_read(chan, RCAR_DMACHCRB) &
RCAR_DMACHCRB_DPTR_MASK))
break;
}
WARN_ONCE(i >= 3, "residue might be not continuous!");
/* /*
* In descriptor mode the descriptor running pointer is not maintained * In descriptor mode the descriptor running pointer is not maintained
* by the interrupt handler, find the running descriptor from the * by the interrupt handler, find the running descriptor from the
...@@ -1336,8 +1357,7 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan, ...@@ -1336,8 +1357,7 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
* mode just use the running descriptor pointer. * mode just use the running descriptor pointer.
*/ */
if (desc->hwdescs.use) { if (desc->hwdescs.use) {
dptr = (rcar_dmac_chan_read(chan, RCAR_DMACHCRB) & dptr = chcrb >> RCAR_DMACHCRB_DPTR_SHIFT;
RCAR_DMACHCRB_DPTR_MASK) >> RCAR_DMACHCRB_DPTR_SHIFT;
if (dptr == 0) if (dptr == 0)
dptr = desc->nchunks; dptr = desc->nchunks;
dptr--; dptr--;
...@@ -1355,7 +1375,7 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan, ...@@ -1355,7 +1375,7 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
} }
/* Add the residue for the current chunk. */ /* Add the residue for the current chunk. */
residue += rcar_dmac_chan_read(chan, RCAR_DMATCRB) << desc->xfer_shift; residue += tcrb << desc->xfer_shift;
return residue; return residue;
} }
...@@ -1368,6 +1388,7 @@ static enum dma_status rcar_dmac_tx_status(struct dma_chan *chan, ...@@ -1368,6 +1388,7 @@ static enum dma_status rcar_dmac_tx_status(struct dma_chan *chan,
enum dma_status status; enum dma_status status;
unsigned long flags; unsigned long flags;
unsigned int residue; unsigned int residue;
bool cyclic;
status = dma_cookie_status(chan, cookie, txstate); status = dma_cookie_status(chan, cookie, txstate);
if (status == DMA_COMPLETE || !txstate) if (status == DMA_COMPLETE || !txstate)
...@@ -1375,10 +1396,11 @@ static enum dma_status rcar_dmac_tx_status(struct dma_chan *chan, ...@@ -1375,10 +1396,11 @@ static enum dma_status rcar_dmac_tx_status(struct dma_chan *chan,
spin_lock_irqsave(&rchan->lock, flags); spin_lock_irqsave(&rchan->lock, flags);
residue = rcar_dmac_chan_get_residue(rchan, cookie); residue = rcar_dmac_chan_get_residue(rchan, cookie);
cyclic = rchan->desc.running ? rchan->desc.running->cyclic : false;
spin_unlock_irqrestore(&rchan->lock, flags); spin_unlock_irqrestore(&rchan->lock, flags);
/* if there's no residue, the cookie is complete */ /* if there's no residue, the cookie is complete */
if (!residue) if (!residue && !cyclic)
return DMA_COMPLETE; return DMA_COMPLETE;
dma_set_residue(txstate, residue); dma_set_residue(txstate, residue);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment