0406-dmaengine-bcm2835-Fix-polling-for-completion-of-DMA-.patch 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. From 42504be159b0fd85d705265dceec01c74d853478 Mon Sep 17 00:00:00 2001
  2. From: Eric Anholt <eric@anholt.net>
  3. Date: Fri, 3 Jun 2016 19:29:11 -0700
  4. Subject: [PATCH] dmaengine: bcm2835: Fix polling for completion of DMA with
  5. interrupts masked.
  6. The tx_status hook is supposed to be safe to call from interrupt
  7. context, but it wouldn't ever return completion for the last transfer,
  8. meaning you couldn't poll for DMA completion with interrupts masked.
  9. This fixes IRQ handling for bcm2835's DSI1, which requires using the
  10. DMA engine to write its registers due to a bug in the AXI bridge.
  11. Signed-off-by: Eric Anholt <eric@anholt.net>
  12. ---
  13. drivers/dma/bcm2835-dma.c | 24 +++++++++++++++++++-----
  14. 1 file changed, 19 insertions(+), 5 deletions(-)
  15. --- a/drivers/dma/bcm2835-dma.c
  16. +++ b/drivers/dma/bcm2835-dma.c
  17. @@ -588,16 +588,16 @@ static enum dma_status bcm2835_dma_tx_st
  18. struct virt_dma_desc *vd;
  19. enum dma_status ret;
  20. unsigned long flags;
  21. + u32 residue;
  22. ret = dma_cookie_status(chan, cookie, txstate);
  23. - if (ret == DMA_COMPLETE || !txstate)
  24. + if (ret == DMA_COMPLETE)
  25. return ret;
  26. spin_lock_irqsave(&c->vc.lock, flags);
  27. vd = vchan_find_desc(&c->vc, cookie);
  28. if (vd) {
  29. - txstate->residue =
  30. - bcm2835_dma_desc_size(to_bcm2835_dma_desc(&vd->tx));
  31. + residue = bcm2835_dma_desc_size(to_bcm2835_dma_desc(&vd->tx));
  32. } else if (c->desc && c->desc->vd.tx.cookie == cookie) {
  33. struct bcm2835_desc *d = c->desc;
  34. dma_addr_t pos;
  35. @@ -609,11 +609,25 @@ static enum dma_status bcm2835_dma_tx_st
  36. else
  37. pos = 0;
  38. - txstate->residue = bcm2835_dma_desc_size_pos(d, pos);
  39. + residue = bcm2835_dma_desc_size_pos(d, pos);
  40. +
  41. + /*
  42. + * If our non-cyclic transfer is done, then report
  43. + * complete and trigger the next tx now. This lets
  44. + * the dmaengine API be used synchronously from an IRQ
  45. + * handler.
  46. + */
  47. + if (!d->cyclic && residue == 0) {
  48. + vchan_cookie_complete(&c->desc->vd);
  49. + bcm2835_dma_start_desc(c);
  50. + ret = dma_cookie_status(chan, cookie, txstate);
  51. + }
  52. } else {
  53. - txstate->residue = 0;
  54. + residue = 0;
  55. }
  56. + dma_set_residue(txstate, residue);
  57. +
  58. spin_unlock_irqrestore(&c->vc.lock, flags);
  59. return ret;