diff options
author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2016-02-10 15:59:42 +0200 |
---|---|---|
committer | Sasha Levin <sasha.levin@oracle.com> | 2016-03-04 10:18:42 -0500 |
commit | c9e0fc1438aef0b9706a7162f130167f3864c2df (patch) | |
tree | 589993bb9f0cd597c745959a56181f05cafd07a9 | |
parent | 0bacc2d3137b3e77248b8a7e256f2806bfc7d705 (diff) | |
download | lwn-c9e0fc1438aef0b9706a7162f130167f3864c2df.tar.gz lwn-c9e0fc1438aef0b9706a7162f130167f3864c2df.zip |
dmaengine: dw: disable BLOCK IRQs for non-cyclic xfer
[ Upstream commit ee1cdcdae59563535485a5f56ee72c894ab7d7ad ]
The commit 2895b2cad6e7 ("dmaengine: dw: fix cyclic transfer callbacks")
re-enabled BLOCK interrupts with regard to make cyclic transfers work. However,
this change becomes a regression for non-cyclic transfers as interrupt counters
under stress test had been grown enormously (approximately per 4-5 bytes in the
UART loop back test).
Taking into consideration above enable BLOCK interrupts if and only if channel
is programmed to perform cyclic transfer.
Fixes: 2895b2cad6e7 ("dmaengine: dw: fix cyclic transfer callbacks")
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Mans Rullgard <mans@mansr.com>
Tested-by: Mans Rullgard <mans@mansr.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
-rw-r--r-- | drivers/dma/dw/core.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index ec233a5888e8..d95e1d0fcc18 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -148,7 +148,6 @@ static void dwc_initialize(struct dw_dma_chan *dwc) /* Enable interrupts */ channel_set_bit(dw, MASK.XFER, dwc->mask); - channel_set_bit(dw, MASK.BLOCK, dwc->mask); channel_set_bit(dw, MASK.ERROR, dwc->mask); dwc->initialized = true; @@ -580,6 +579,9 @@ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc, spin_unlock_irqrestore(&dwc->lock, flags); } + + /* Re-enable interrupts */ + channel_set_bit(dw, MASK.BLOCK, dwc->mask); } /* ------------------------------------------------------------------------- */ @@ -610,11 +612,8 @@ static void dw_dma_tasklet(unsigned long data) dwc_scan_descriptors(dw, dwc); } - /* - * Re-enable interrupts. - */ + /* Re-enable interrupts */ channel_set_bit(dw, MASK.XFER, dw->all_chan_mask); - channel_set_bit(dw, MASK.BLOCK, dw->all_chan_mask); channel_set_bit(dw, MASK.ERROR, dw->all_chan_mask); } @@ -1249,6 +1248,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan) int dw_dma_cyclic_start(struct dma_chan *chan) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dw_dma *dw = to_dw_dma(chan->device); unsigned long flags; if (!test_bit(DW_DMA_IS_CYCLIC, &dwc->flags)) { @@ -1257,7 +1257,12 @@ int dw_dma_cyclic_start(struct dma_chan *chan) } spin_lock_irqsave(&dwc->lock, flags); + + /* Enable interrupts to perform cyclic transfer */ + channel_set_bit(dw, MASK.BLOCK, dwc->mask); + dwc_dostart(dwc, dwc->cdesc->desc[0]); + spin_unlock_irqrestore(&dwc->lock, flags); return 0; |