Skip to content

Commit

Permalink
Merge tag 'dmaengine-fix-5.1-rc7' of git://git.infradead.org/users/vk…
Browse files Browse the repository at this point in the history
…oul/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
  • Loading branch information
torvalds committed Apr 28, 2019
2 parents 25cce03 + 5bb5c3a commit 72a6e35
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 6 deletions.
2 changes: 1 addition & 1 deletion drivers/dma/bcm2835-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg(
d = bcm2835_dma_create_cb_chain(chan, direction, false,
info, extra,
frames, src, dst, 0, 0,
GFP_KERNEL);
GFP_NOWAIT);
if (!d)
return NULL;

Expand Down
2 changes: 1 addition & 1 deletion drivers/dma/mediatek/mtk-cqdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ static void mtk_cqdma_start(struct mtk_cqdma_pchan *pc,
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
mtk_dma_set(pc, MTK_CQDMA_DST2, cvd->dest >> MTK_CQDMA_ADDR2_SHFIT);
#else
mtk_dma_set(pc, MTK_CQDMA_SRC2, 0);
mtk_dma_set(pc, MTK_CQDMA_DST2, 0);
#endif

/* setup the length */
Expand Down
30 changes: 26 additions & 4 deletions drivers/dma/sh/rcar-dmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -1282,6 +1282,9 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
enum dma_status status;
unsigned int residue = 0;
unsigned int dptr = 0;
unsigned int chcrb;
unsigned int tcrb;
unsigned int i;

if (!desc)
return 0;
Expand Down Expand Up @@ -1329,15 +1332,32 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
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
* by the interrupt handler, find the running descriptor from the
* descriptor pointer field in the CHCRB register. In non-descriptor
* mode just use the running descriptor pointer.
*/
if (desc->hwdescs.use) {
dptr = (rcar_dmac_chan_read(chan, RCAR_DMACHCRB) &
RCAR_DMACHCRB_DPTR_MASK) >> RCAR_DMACHCRB_DPTR_SHIFT;
dptr = chcrb >> RCAR_DMACHCRB_DPTR_SHIFT;
if (dptr == 0)
dptr = desc->nchunks;
dptr--;
Expand All @@ -1355,7 +1375,7 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
}

/* 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;
}
Expand All @@ -1368,17 +1388,19 @@ static enum dma_status rcar_dmac_tx_status(struct dma_chan *chan,
enum dma_status status;
unsigned long flags;
unsigned int residue;
bool cyclic;

status = dma_cookie_status(chan, cookie, txstate);
if (status == DMA_COMPLETE || !txstate)
return status;

spin_lock_irqsave(&rchan->lock, flags);
residue = rcar_dmac_chan_get_residue(rchan, cookie);
cyclic = rchan->desc.running ? rchan->desc.running->cyclic : false;
spin_unlock_irqrestore(&rchan->lock, flags);

/* if there's no residue, the cookie is complete */
if (!residue)
if (!residue && !cyclic)
return DMA_COMPLETE;

dma_set_residue(txstate, residue);
Expand Down

0 comments on commit 72a6e35

Please sign in to comment.