Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 77bcc497 authored by Andy Shevchenko's avatar Andy Shevchenko Committed by Vinod Koul
Browse files

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: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
parent 5be10f34
Loading
Loading
Loading
Loading
+21 −22
Original line number Diff line number Diff line
@@ -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,30 +616,9 @@ 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);
	}
	}

	/*
	 * Re-enable interrupts.