linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mans Rullgard <mans@mansr.com>
To: Viresh Kumar <vireshk@kernel.org>,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	Vinod Koul <vinod.koul@intel.com>,
	linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org
Cc: Dan Williams <dan.j.williams@intel.com>
Subject: [PATCH 14/15] dmaengine: dw: move residue to a descriptor
Date: Sun, 24 Jan 2016 19:22:01 +0000	[thread overview]
Message-ID: <1453663322-14474-15-git-send-email-mans@mansr.com> (raw)
In-Reply-To: <1453663322-14474-1-git-send-email-mans@mansr.com>

From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

Residue is a property of any active descriptor. So, any descriptor may be in
different state but residue is a feature of active descriptor. Check if the
asked descriptor is active and return proper residue value for it.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Mans Rullgard <mans@mansr.com>
---
 drivers/dma/dw/core.c | 60 ++++++++++++++++++++++++++++++++++-----------------
 drivers/dma/dw/regs.h |  2 +-
 2 files changed, 41 insertions(+), 21 deletions(-)

diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
index cd345432fa33..b6634adf24f9 100644
--- a/drivers/dma/dw/core.c
+++ b/drivers/dma/dw/core.c
@@ -239,7 +239,7 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
 
 		dwc_initialize(dwc);
 
-		dwc->residue = first->total_len;
+		first->residue = first->total_len;
 		dwc->tx_node_active = &first->tx_list;
 
 		/* Submit first block */
@@ -370,11 +370,11 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
 
 			head = &desc->tx_list;
 			if (active != head) {
-				/* Update desc to reflect last sent one */
-				if (active != head->next)
-					desc = to_dw_desc(active->prev);
-
-				dwc->residue -= desc->len;
+				/* Update residue to reflect last sent descriptor */
+				if (active == head->next)
+					desc->residue -= desc->len;
+				else
+					desc->residue -= to_dw_desc(active->prev)->len;
 
 				child = to_dw_desc(active);
 
@@ -389,8 +389,6 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
 			clear_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags);
 		}
 
-		dwc->residue = 0;
-
 		spin_unlock_irqrestore(&dwc->lock, flags);
 
 		dwc_complete_all(dw, dwc);
@@ -398,7 +396,6 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
 	}
 
 	if (list_empty(&dwc->active_list)) {
-		dwc->residue = 0;
 		spin_unlock_irqrestore(&dwc->lock, flags);
 		return;
 	}
@@ -413,7 +410,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
 
 	list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) {
 		/* Initial residue value */
-		dwc->residue = desc->total_len;
+		desc->residue = desc->total_len;
 
 		/* Check first descriptors addr */
 		if (desc->txd.phys == DWC_LLP_LOC(llp)) {
@@ -424,20 +421,20 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
 		/* Check first descriptors llp */
 		if (lli_read(desc, llp) == llp) {
 			/* This one is currently in progress */
-			dwc->residue -= dwc_get_sent(dwc);
+			desc->residue -= dwc_get_sent(dwc);
 			spin_unlock_irqrestore(&dwc->lock, flags);
 			return;
 		}
 
-		dwc->residue -= desc->len;
+		desc->residue -= desc->len;
 		list_for_each_entry(child, &desc->tx_list, desc_node) {
 			if (lli_read(child, llp) == llp) {
 				/* Currently in progress */
-				dwc->residue -= dwc_get_sent(dwc);
+				desc->residue -= dwc_get_sent(dwc);
 				spin_unlock_irqrestore(&dwc->lock, flags);
 				return;
 			}
-			dwc->residue -= child->len;
+			desc->residue -= child->len;
 		}
 
 		/*
@@ -1040,16 +1037,37 @@ static int dwc_terminate_all(struct dma_chan *chan)
 	return 0;
 }
 
-static inline u32 dwc_get_residue(struct dw_dma_chan *dwc)
+static struct dw_desc *dwc_find_desc(struct dw_dma_chan *dwc, dma_cookie_t c)
 {
+	struct dw_desc *desc;
+
+	list_for_each_entry(desc, &dwc->active_list, desc_node)
+		if (desc->txd.cookie == c)
+			return desc;
+
+	return NULL;
+}
+
+static u32 dwc_get_residue(struct dw_dma_chan *dwc, dma_cookie_t cookie)
+{
+	struct dw_desc *desc;
 	unsigned long flags;
 	u32 residue;
 
 	spin_lock_irqsave(&dwc->lock, flags);
 
-	residue = dwc->residue;
-	if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags) && residue)
-		residue -= dwc_get_sent(dwc);
+	desc = dwc_find_desc(dwc, cookie);
+	if (desc) {
+		if (desc == dwc_first_active(dwc)) {
+			residue = desc->residue;
+			if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags) && residue)
+				residue -= dwc_get_sent(dwc);
+		} else {
+			residue = desc->total_len;
+		}
+	} else {
+		residue = 0;
+	}
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 	return residue;
@@ -1070,8 +1088,10 @@ dwc_tx_status(struct dma_chan *chan,
 	dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
 
 	ret = dma_cookie_status(chan, cookie, txstate);
-	if (ret != DMA_COMPLETE)
-		dma_set_residue(txstate, dwc_get_residue(dwc));
+	if (ret == DMA_COMPLETE)
+		return ret;
+
+	dma_set_residue(txstate, dwc_get_residue(dwc, cookie));
 
 	if (test_bit(DW_DMA_IS_PAUSED, &dwc->flags) && ret == DMA_IN_PROGRESS)
 		return DMA_PAUSED;
diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h
index 0deb04562c33..180a0cc00e41 100644
--- a/drivers/dma/dw/regs.h
+++ b/drivers/dma/dw/regs.h
@@ -237,7 +237,6 @@ struct dw_dma_chan {
 	struct list_head	active_list;
 	struct list_head	queue;
 	struct list_head	free_list;
-	u32			residue;
 	struct dw_cyclic_desc	*cdesc;
 
 	unsigned int		descs_allocated;
@@ -351,6 +350,7 @@ struct dw_desc {
 	struct dma_async_tx_descriptor	txd;
 	size_t				len;
 	size_t				total_len;
+	u32				residue;
 };
 
 #define to_dw_desc(h)	list_entry(h, struct dw_desc, desc_node)
-- 
2.7.0

  parent reply	other threads:[~2016-01-24 19:26 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-24 19:21 [PATCH 00/15] dmaengine: dw: various fixes and cleanups Mans Rullgard
2016-01-24 19:21 ` [PATCH 01/15] dmaengine: dw: fix byte order of hw descriptor fields Mans Rullgard
2016-01-24 19:21 ` [PATCH 02/15] dmaengine: dw: clear LLP_[SD]_EN bits in last descriptor of a chain Mans Rullgard
2016-01-24 19:21 ` [PATCH 03/15] dmaengine: dw: rename masters to reflect actual topology Mans Rullgard
2016-01-24 20:09   ` Hans-Christian Noren Egtvedt
2016-01-24 20:19     ` Måns Rullgård
2016-01-24 20:37       ` Hans-Christian Noren Egtvedt
2016-01-24 20:57         ` Måns Rullgård
2016-01-24 22:36   ` Mark Brown
2016-01-24 22:38     ` Måns Rullgård
2016-01-25  6:03       ` Viresh Kumar
2016-01-25 12:05       ` Vinod Koul
2016-01-25 12:23       ` Mark Brown
2016-01-25  8:35     ` Andy Shevchenko
2016-01-25 12:24       ` Mark Brown
2016-01-25 14:01         ` Andy Shevchenko
2016-01-27 12:47   ` Mark Brown
2016-01-24 19:21 ` [PATCH 04/15] dmaengine: dw: set src and dst master select according to xfer direction Mans Rullgard
2016-01-24 19:21 ` [PATCH 05/15] dmaengine: dw: set LMS field in descriptors Mans Rullgard
2016-01-24 19:21 ` [PATCH 06/15] dmaengine: dw: substitute dma_read_byaddr by dma_readl_native Mans Rullgard
2016-01-24 19:21 ` [PATCH 07/15] dmaengine: dw: revisit data_width property Mans Rullgard
2016-01-25  7:32   ` Vineet Gupta
2016-01-25  8:45     ` Andy Shevchenko
2016-01-25 10:31       ` Måns Rullgård
2016-01-25 10:36         ` Andy Shevchenko
2016-01-25  8:42   ` Andy Shevchenko
2016-01-26 21:07   ` Rob Herring
2016-01-27 12:26     ` Andy Shevchenko
2016-01-24 19:21 ` [PATCH 08/15] dmaengine: dw: define counter variables as unsigned int Mans Rullgard
2016-01-24 19:21 ` [PATCH 09/15] dmaengine: dw: keep entire platform data in struct dw_dma Mans Rullgard
2016-01-24 19:21 ` [PATCH 10/15] dmaengine: dw: pass platform data via struct dw_dma_chip Mans Rullgard
2016-01-24 19:21 ` [PATCH 11/15] dmaengine: dw: platform: use field-by-field initialization Mans Rullgard
2016-01-25  8:48   ` Andy Shevchenko
2016-01-24 19:21 ` [PATCH 12/15] dmaengine: dw: move dwc->paused to dwc->flags Mans Rullgard
2016-01-24 19:22 ` [PATCH 13/15] dmaengine: dw: move dwc->initialized " Mans Rullgard
2016-01-24 19:22 ` Mans Rullgard [this message]
2016-01-24 19:22 ` [PATCH 15/15] dmaengine: dw: set cdesc to NULL when free cyclic transfers Mans Rullgard
2016-01-25 10:37 ` [PATCH 00/15] dmaengine: dw: various fixes and cleanups Andy Shevchenko
2016-01-25 12:07 ` Vinod Koul

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1453663322-14474-15-git-send-email-mans@mansr.com \
    --to=mans@mansr.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=dan.j.williams@intel.com \
    --cc=dmaengine@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=vinod.koul@intel.com \
    --cc=vireshk@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).