On Fri, Jun 03, 2016 at 07:29:11PM -0700, Eric Anholt wrote: > The tx_status hook is supposed to be safe to call from interrupt > context, but it wouldn't ever return completion for the last transfer, > meaning you couldn't poll for DMA completion with interrupts masked. and why is that? > This fixes IRQ handling for bcm2835's DSI1, which requires using the > DMA engine to write its registers due to a bug in the AXI bridge. > > Signed-off-by: Eric Anholt <eric@xxxxxxxxxx> > --- > drivers/dma/bcm2835-dma.c | 24 +++++++++++++++++++----- > 1 file changed, 19 insertions(+), 5 deletions(-) > > diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c > index 6149b27c33ad..320461c578e3 100644 > --- a/drivers/dma/bcm2835-dma.c > +++ b/drivers/dma/bcm2835-dma.c > @@ -570,16 +570,16 @@ static enum dma_status bcm2835_dma_tx_status(struct dma_chan *chan, > struct virt_dma_desc *vd; > enum dma_status ret; > unsigned long flags; > + u32 residue; > > ret = dma_cookie_status(chan, cookie, txstate); > - if (ret == DMA_COMPLETE || !txstate) > + if (ret == DMA_COMPLETE) Why do you change this? txstate can be NULL, so no point calculating reside for those cases > return ret; > > spin_lock_irqsave(&c->vc.lock, flags); > vd = vchan_find_desc(&c->vc, cookie); > if (vd) { > - txstate->residue = > - bcm2835_dma_desc_size(to_bcm2835_dma_desc(&vd->tx)); > + residue = bcm2835_dma_desc_size(to_bcm2835_dma_desc(&vd->tx)); > } else if (c->desc && c->desc->vd.tx.cookie == cookie) { > struct bcm2835_desc *d = c->desc; > dma_addr_t pos; > @@ -591,11 +591,25 @@ static enum dma_status bcm2835_dma_tx_status(struct dma_chan *chan, > else > pos = 0; > > - txstate->residue = bcm2835_dma_desc_size_pos(d, pos); > + residue = bcm2835_dma_desc_size_pos(d, pos); > + > + /* > + * If our non-cyclic transfer is done, then report > + * complete and trigger the next tx now. This lets > + * the dmaengine API be used synchronously from an IRQ > + * handler. > + */ > + if (!d->cyclic && residue == 0) { > + vchan_cookie_complete(&c->desc->vd); > + bcm2835_dma_start_desc(c); > + ret = dma_cookie_status(chan, cookie, txstate); > + } > } else { > - txstate->residue = 0; > + residue = 0; > } > > + dma_set_residue(txstate, residue); > + > spin_unlock_irqrestore(&c->vc.lock, flags); > > return ret; > -- > 2.8.0.rc3 > -- ~Vinod -- To unsubscribe from this list: send the line "unsubscribe dmaengine" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html