diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-11 07:14:01 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-11 07:14:01 -0700 |
| commit | c7a19c795b4b0a3232c157ed29eea85077e95da6 (patch) | |
| tree | d3916dcdea74b55453694c9f31b95b6d906e3202 /drivers/dma/dw/core.c | |
| parent | 5fd41f2a10b38ab84b4c2436140ce490d34291fa (diff) | |
| parent | a0bbe990c161ddf56444efe80d9d6e15fdc47aca (diff) | |
| download | linux-c7a19c795b4b0a3232c157ed29eea85077e95da6.tar.gz linux-c7a19c795b4b0a3232c157ed29eea85077e95da6.tar.bz2 linux-c7a19c795b4b0a3232c157ed29eea85077e95da6.zip | |
Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma
Pull slave-dma updates from Vinod Koul:
"Some notable changes are:
- new driver for AMBA AXI NBPF by Guennadi
- new driver for sun6i controller by Maxime
- pl330 drivers fixes from Lar's
- sh-dma updates and fixes from Laurent, Geert and Kuninori
- Documentation updates from Geert
- drivers fixes and updates spread over dw, edma, freescale, mpc512x
etc.."
* 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma: (72 commits)
dmaengine: sun6i: depends on RESET_CONTROLLER
dma: at_hdmac: fix invalid remaining bytes detection
dmaengine: nbpfaxi: don't build this driver where it cannot be used
dmaengine: nbpf_error_get_channel() can be static
dma: pl08x: Use correct specifier for size_t values
dmaengine: Remove the context argument to the prep_dma_cyclic operation
dmaengine: nbpfaxi: convert to tasklet
dmaengine: nbpfaxi: fix a theoretical race
dmaengine: add a driver for AMBA AXI NBPF DMAC IP cores
dmaengine: add device tree binding documentation for the nbpfaxi driver
dmaengine: edma: Do not register second device when booted with DT
dmaengine: edma: Do not change the error code returned from edma_alloc_slot
dmaengine: rcar-dmac: Add device tree bindings documentation
dmaengine: shdma: Allocate cyclic sg list dynamically
dmaengine: shdma: Make channel filter ignore unrelated devices
dmaengine: sh: Rework Kconfig and Makefile
dmaengine: sun6i: Fix memory leaks
dmaengine: sun6i: Free the interrupt before killing the tasklet
dmaengine: sun6i: Remove switch statement from buswidth convertion routine
dmaengine: of: kconfig: select DMA_ENGINE when DMA_OF is selected
...
Diffstat (limited to 'drivers/dma/dw/core.c')
| -rw-r--r-- | drivers/dma/dw/core.c | 42 |
1 files changed, 22 insertions, 20 deletions
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index a27ded53ab4f..1af731b83b3f 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -279,6 +279,19 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) channel_set_bit(dw, CH_EN, dwc->mask); } +static void dwc_dostart_first_queued(struct dw_dma_chan *dwc) +{ + struct dw_desc *desc; + + if (list_empty(&dwc->queue)) + return; + + list_move(dwc->queue.next, &dwc->active_list); + desc = dwc_first_active(dwc); + dev_vdbg(chan2dev(&dwc->chan), "%s: started %u\n", __func__, desc->txd.cookie); + dwc_dostart(dwc, desc); +} + /*----------------------------------------------------------------------*/ static void @@ -335,10 +348,7 @@ static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc) * the completed ones. */ list_splice_init(&dwc->active_list, &list); - if (!list_empty(&dwc->queue)) { - list_move(dwc->queue.next, &dwc->active_list); - dwc_dostart(dwc, dwc_first_active(dwc)); - } + dwc_dostart_first_queued(dwc); spin_unlock_irqrestore(&dwc->lock, flags); @@ -467,10 +477,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) /* Try to continue after resetting the channel... */ dwc_chan_disable(dw, dwc); - if (!list_empty(&dwc->queue)) { - list_move(dwc->queue.next, &dwc->active_list); - dwc_dostart(dwc, dwc_first_active(dwc)); - } + dwc_dostart_first_queued(dwc); spin_unlock_irqrestore(&dwc->lock, flags); } @@ -677,17 +684,9 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx) * possible, perhaps even appending to those already submitted * for DMA. But this is hard to do in a race-free manner. */ - if (list_empty(&dwc->active_list)) { - dev_vdbg(chan2dev(tx->chan), "%s: started %u\n", __func__, - desc->txd.cookie); - list_add_tail(&desc->desc_node, &dwc->active_list); - dwc_dostart(dwc, dwc_first_active(dwc)); - } else { - dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__, - desc->txd.cookie); - list_add_tail(&desc->desc_node, &dwc->queue); - } + dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__, desc->txd.cookie); + list_add_tail(&desc->desc_node, &dwc->queue); spin_unlock_irqrestore(&dwc->lock, flags); @@ -1092,9 +1091,12 @@ dwc_tx_status(struct dma_chan *chan, static void dwc_issue_pending(struct dma_chan *chan) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + unsigned long flags; - if (!list_empty(&dwc->queue)) - dwc_scan_descriptors(to_dw_dma(chan->device), dwc); + spin_lock_irqsave(&dwc->lock, flags); + if (list_empty(&dwc->active_list)) + dwc_dostart_first_queued(dwc); + spin_unlock_irqrestore(&dwc->lock, flags); } static int dwc_alloc_chan_resources(struct dma_chan *chan) |
