openwrt/target/linux/brcm2708/patches-4.4/0408-dmaengine-bcm2835-Fix-polling-for-completion-of-DMA-.patch
Álvaro Fernández Rojas 20402106a3 brcm2708: update linux 4.4 patches to latest version
As usual these patches were extracted and rebased from the raspberry pi repo:
https://github.com/raspberrypi/linux/tree/rpi-4.4.y

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2016-07-09 16:29:18 +02:00

69 lines
2.1 KiB
Diff

From 467c8219ee56e75ab53f29b569f9fb5d033f57d4 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Fri, 3 Jun 2016 19:29:11 -0700
Subject: [PATCH 408/423] dmaengine: bcm2835: Fix polling for completion of DMA
with interrupts masked.
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.
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@anholt.net>
---
drivers/dma/bcm2835-dma.c | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -588,16 +588,16 @@ static enum dma_status bcm2835_dma_tx_st
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)
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;
@@ -609,11 +609,25 @@ static enum dma_status bcm2835_dma_tx_st
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;