diff options
| author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2013-01-18 14:14:15 +0200 | 
|---|---|---|
| committer | Vinod Koul <vinod.koul@intel.com> | 2013-01-20 20:49:21 -0800 | 
| commit | 77bcc497c60ec62dbb84abc809a6e218d53409e9 (patch) | |
| tree | 6d0f491d55b316010f352934a23b4ecd5d01e118 | |
| parent | 5be10f349bc0a2f3dd2ab6417ffe29746403984c (diff) | |
dw_dmac: move soft LLP code from tasklet to dwc_scan_descriptors
The proper place for the main logic of the soft LLP mode is
dwc_scan_descriptors. It prevents to get the transfer unexpectedly aborted in
case the user calls dwc_tx_status.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
| -rw-r--r-- | drivers/dma/dw_dmac.c | 43 | 
1 files changed, 21 insertions, 22 deletions
| diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 635a4a5d31ae..dc3b9558a25c 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -400,6 +400,20 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)  	if (status_xfer & dwc->mask) {  		/* Everything we've submitted is done */  		dma_writel(dw, CLEAR.XFER, dwc->mask); + +		if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags)) { +			if (dwc->tx_node_active != dwc->tx_list) { +				desc = to_dw_desc(dwc->tx_node_active); + +				/* Submit next block */ +				dwc_do_single_block(dwc, desc); +				spin_unlock_irqrestore(&dwc->lock, flags); + +				return; +			} +			/* We are done here */ +			clear_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags); +		}  		spin_unlock_irqrestore(&dwc->lock, flags);  		dwc_complete_all(dw, dwc); @@ -411,6 +425,12 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)  		return;  	} +	if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags)) { +		dev_vdbg(chan2dev(&dwc->chan), "%s: soft LLP mode\n", __func__); +		spin_unlock_irqrestore(&dwc->lock, flags); +		return; +	} +  	dev_vdbg(chan2dev(&dwc->chan), "%s: llp=0x%llx\n", __func__,  			(unsigned long long)llp); @@ -596,29 +616,8 @@ static void dw_dma_tasklet(unsigned long data)  			dwc_handle_cyclic(dw, dwc, status_err, status_xfer);  		else if (status_err & (1 << i))  			dwc_handle_error(dw, dwc); -		else if (status_xfer & (1 << i)) { -			unsigned long flags; - -			spin_lock_irqsave(&dwc->lock, flags); -			if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags)) { -				if (dwc->tx_node_active != dwc->tx_list) { -					struct dw_desc *desc = -						to_dw_desc(dwc->tx_node_active); - -					dma_writel(dw, CLEAR.XFER, dwc->mask); - -					dwc_do_single_block(dwc, desc); - -					spin_unlock_irqrestore(&dwc->lock, flags); -					continue; -				} -				/* we are done here */ -				clear_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags); -			} -			spin_unlock_irqrestore(&dwc->lock, flags); - +		else if (status_xfer & (1 << i))  			dwc_scan_descriptors(dw, dwc); -		}  	}  	/* | 
