Skip to contentSkip to conversation

cppi41 dma fixes for v4.10-rc cycle

PATCH Applied Tony Lindgren 3 participants 9 messages Jan 19, 2017 – Jan 25, 2017 2 messages not in the archive dmaengine

lore
Share & tools
lore
#0 lore raw

v4 cover cppi41 dma fixes for v4.10-rc cycle

Hi all,

I'm using v4 naming here as the earlier patch "dmaengine: cppi41: Add dma support to da8xx" has been separated from the error -115 issue. We've identified so far three musb and cppi41 regressions:

1. Error -71 regression with musb

This is not dma related, and fixed with recently posted patch "[PATCH 1/2] usb: musb: Fix host mode error -71 regression".

2. Error -115 regression with cppi41 dma with musb

This regression was caused by commit 098de42ad670 ("dmaengine:
cppi41: Fix unpaired pm runtime when only a USB hub is connected") and causes runtime PM autosuspend delay to time out on active dma transfers when connecting a mass storage device to a usb hub. This is fixed in the first patch in this series.

3. Race with runtime PM and cppi41_dma_issue_pending()

This is really a separate issue from the error -115 problem, and fixed with the second patch in this series. That's minimal v4 version of the "dmaengine: cppi41: Fix oops in cppi41_runtime_resume" patch.

Regards,

Tony

Tony Lindgren (2):
dmaengine: cppi41: Fix runtime PM timeouts with USB mass storage
dmaengine: cppi41: Fix oops in cppi41_runtime_resume

 drivers/dma/cppi41.c | 56 ++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 41 insertions(+), 15 deletions(-)
Signature · 5 lines
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): 20170119164908.9472-1-tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org

#2 lore raw

PATCH v4 1/2 dmaengine: cppi41: Fix runtime PM timeouts with USB mass storage

Commit fdea2d09b997 ("dmaengine: cppi41: Add basic PM runtime support") added runtime PM support for cppi41, but had corner case issues. Some of the issues were fixed with commit 098de42ad670 ("dmaengine: cppi41: Fix unpaired pm runtime when only a USB hub is connected"). That fix however caused a new regression where we can get error -115 messages with USB on BeagleBone when connecting a USB mass storage device to a hub.

This is because when connecting a USB mass storage device to a hub, the initial DMA transfers can take over 200ms to complete and cppi41 autosuspend delay times out.

To fix the issue, we want to implement refcounting for chan_busy array that contains the active dma transfers. Increasing the autosuspend delay won't help as that the delay could be potentially seconds, and it's best to let the USB subsystem to deal with the timeouts on errors.

The earlier attempt for runtime PM was buggy as the pm_runtime_get/put() calls could get unpaired easily as they did not follow the state of the chan_busy array as described in commit 098de42ad670 ("dmaengine:
cppi41: Fix unpaired pm runtime when only a USB hub is connected".

Let's fix the issue by adding pm_runtime_get() to where a new transfer is added to the chan_busy array, and calls to pm_runtime_put() where chan_busy array entry is cleared. This prevents any autosuspend timeouts from happening while dma transfers are active.

Fixes 098de42ad670 ("dmaengine: cppi41: Fix unpaired pm runtime when

only a USB hub is connected")

Fixes fdea2d09b997 ("dmaengine: cppi41: Add basic PM runtime support")
Cc Andy Shevchenko <[email protected]>
Cc Bin Liu <[email protected]>
Cc Grygorii Strashko <[email protected]>
Cc Kevin Hilman <khilman-rdvid1DuHRBWk0Htik3J/[email protected]>
Cc Patrick Titiano <ptitiano-rdvid1DuHRBWk0Htik3J/[email protected]>
Cc Sergei Shtylyov <sergei.shtylyov-M4DtvfQ/[email protected]>
---
 drivers/dma/cppi41.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
drivers/dma/cppi41.c +16 -0
@@ -257,6 +257,10 @@ static struct cppi41_channel *desc_to_chan(struct cppi41_dd *cdd, u32 desc)
 	BUG_ON(desc_num >= ALLOC_DECS_NUM);
 	c = cdd->chan_busy[desc_num];
 	cdd->chan_busy[desc_num] = NULL;
+
+	/* Usecount for chan_busy[], paired with push_desc_queue() */
+	pm_runtime_put(cdd->ddev.dev);
+
 	return c;
 }
 
@@ -447,6 +451,15 @@ static void push_desc_queue(struct cppi41_channel *c)
 	 */
 	__iowmb();
 
+	/*
+	 * DMA transfers can take at least 200ms to complete with USB mass
+	 * storage connected. To prevent autosuspend timeouts, we must use
+	 * pm_runtime_get/put() when chan_busy[] is modified. This will get
+	 * cleared in desc_to_chan() or cppi41_stop_chan() depending on the
+	 * outcome of the transfer.
+	 */
+	pm_runtime_get(cdd->ddev.dev);
+
 	desc_phys = lower_32_bits(c->desc_phys);
 	desc_num = (desc_phys - cdd->descs_phys) / sizeof(struct cppi41_desc);
 	WARN_ON(cdd->chan_busy[desc_num]);
@@ -705,6 +718,9 @@ static int cppi41_stop_chan(struct dma_chan *chan)
 	WARN_ON(!cdd->chan_busy[desc_num]);
 	cdd->chan_busy[desc_num] = NULL;
 
+	/* Usecount for chan_busy[], paired with push_desc_queue() */
+	pm_runtime_put(cdd->ddev.dev);
+
 	return 0;
 }
 
Signature · 5 lines
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#3 lore raw

PATCH v4 2/2 dmaengine: cppi41: Fix oops in cppi41_runtime_resume

In reply to a message not in the archive

Commit fdea2d09b997 ("dmaengine: cppi41: Add basic PM runtime support") together with recent MUSB changes allowed USB and DMA on BeagleBone to idle when no cable is connected. But looks like few corner case issues still remain.

Looks like just by re-plugging USB cable about ten or so times on BeagleBone when configured in USB peripheral mode we can get warnings and eventually trigger an oops in cppi41 DMA:

WARNING: CPU: 0 PID: 14 at drivers/dma/cppi41.c:1154 cppi41_runtime_suspend+

x28/0x38 [cppi41]
...

WARNING: CPU: 0 PID: 14 at drivers/dma/cppi41.c:452
push_desc_queue+0x94/0x9c [cppi41]

...

Unable to handle kernel NULL pointer dereference at virtual
address 00000104
pgd = c0004000
[00000104] *pgd=00000000
Internal error: Oops: 805 [#1] SMP ARM

...
[<bf0d92cc>] (cppi41_runtime_resume [cppi41]) from [<c0589838>] (__rpm_callback+0xc0/0x214)
[<c0589838>] (__rpm_callback) from [<c05899ac>] (rpm_callback+0x20/0x80) [<c05899ac>] (rpm_callback) from [<c0589460>] (rpm_resume+0x504/0x78c) [<c0589460>] (rpm_resume) from [<c058a1a0>] (pm_runtime_work+0x60/0xa8) [<c058a1a0>] (pm_runtime_work) from [<c0156120>] (process_one_work+0x2b4/0x808)

This is because of a race with runtime PM and cppi41_dma_issue_pending()
as reported by Alexandre Bailon <abailon-rdvid1DuHRBWk0Htik3J/[email protected]> in earlier set of patches. Based on mailing list discussions we however came to the conclusion that a different fix from Alexandre's fix is needed in order
to guarantee that DMA is really active when we try to use it.

To fix the issue, we need to add a driver specific flag as we otherwise can have -EINPROGRESS state set by runtime PM and can't rely on pm_runtime_active() to tell us when we can use the DMA.

And we need to make sure the DMA transfers get triggered in the queued order. So let's always queue the transfers, then flush the queue
from both cppi41_dma_issue_pending() and cppi41_runtime_resume()
as suggested by Grygorii Strashko <[email protected]> in an earlier example patch.

For reference, this is also documented in Documentation/power/runtime_pm.txt in the example at the end of the file as pointed out by Grygorii Strashko <[email protected]>.

Based on earlier patches from Alexandre Bailon <abailon-rdvid1DuHRBWk0Htik3J/[email protected]> and Grygorii Strashko <[email protected]> modified based on testing and what was discussed on the mailing lists.

Fixes fdea2d09b997 ("dmaengine: cppi41: Add basic PM runtime support")
Cc Andy Shevchenko <[email protected]>
Cc Bin Liu <[email protected]>
Cc Grygorii Strashko <[email protected]>
Cc Kevin Hilman <khilman-rdvid1DuHRBWk0Htik3J/[email protected]>
Cc Patrick Titiano <ptitiano-rdvid1DuHRBWk0Htik3J/[email protected]>
Cc Sergei Shtylyov <sergei.shtylyov-M4DtvfQ/[email protected]>
---
 drivers/dma/cppi41.c | 40 +++++++++++++++++++++++++---------------
 1 file changed, 25 insertions(+), 15 deletions(-)
drivers/dma/cppi41.c +25 -15
@@ -153,6 +153,8 @@ struct cppi41_dd {
 
 	/* context for suspend/resume */
 	unsigned int dma_tdfdq;
+
+	bool is_suspended;
 };
 
 #define FIST_COMPLETION_QUEUE	93
@@ -470,20 +472,26 @@ static void push_desc_queue(struct cppi41_channel *c)
 	cppi_writel(reg, cdd->qmgr_mem + QMGR_QUEUE_D(c->q_num));
 }
 
-static void pending_desc(struct cppi41_channel *c)
+/*
+ * Caller must hold cdd->lock to prevent push_desc_queue()
+ * getting called out of order. We have both cppi41_dma_issue_pending()
+ * and cppi41_runtime_resume() call this function.
+ */
+static void cppi41_run_queue(struct cppi41_dd *cdd)
 {
-	struct cppi41_dd *cdd = c->cdd;
-	unsigned long flags;
+	struct cppi41_channel *c, *_c;
 
-	spin_lock_irqsave(&cdd->lock, flags);
-	list_add_tail(&c->node, &cdd->pending);
-	spin_unlock_irqrestore(&cdd->lock, flags);
+	list_for_each_entry_safe(c, _c, &cdd->pending, node) {
+		push_desc_queue(c);
+		list_del(&c->node);
+	}
 }
 
 static void cppi41_dma_issue_pending(struct dma_chan *chan)
 {
 	struct cppi41_channel *c = to_cpp41_chan(chan);
 	struct cppi41_dd *cdd = c->cdd;
+	unsigned long flags;
 	int error;
 
 	error = pm_runtime_get(cdd->ddev.dev);
@@ -495,10 +503,11 @@ static void cppi41_dma_issue_pending(struct dma_chan *chan)
 		return;
 	}
 
-	if (likely(pm_runtime_active(cdd->ddev.dev)))
-		push_desc_queue(c);
-	else
-		pending_desc(c);
+	spin_lock_irqsave(&cdd->lock, flags);
+	list_add_tail(&c->node, &cdd->pending);
+	if (!cdd->is_suspended)
+		cppi41_run_queue(cdd);
+	spin_unlock_irqrestore(&cdd->lock, flags);
 
 	pm_runtime_mark_last_busy(cdd->ddev.dev);
 	pm_runtime_put_autosuspend(cdd->ddev.dev);
@@ -1166,8 +1175,12 @@ static int __maybe_unused cppi41_resume(struct device *dev)
 static int __maybe_unused cppi41_runtime_suspend(struct device *dev)
 {
 	struct cppi41_dd *cdd = dev_get_drvdata(dev);
+	unsigned long flags;
 
+	spin_lock_irqsave(&cdd->lock, flags);
+	cdd->is_suspended = true;
 	WARN_ON(!list_empty(&cdd->pending));
+	spin_unlock_irqrestore(&cdd->lock, flags);
 
 	return 0;
 }
@@ -1175,14 +1188,11 @@ static int __maybe_unused cppi41_runtime_suspend(struct device *dev)
 static int __maybe_unused cppi41_runtime_resume(struct device *dev)
 {
 	struct cppi41_dd *cdd = dev_get_drvdata(dev);
-	struct cppi41_channel *c, *_c;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cdd->lock, flags);
-	list_for_each_entry_safe(c, _c, &cdd->pending, node) {
-		push_desc_queue(c);
-		list_del(&c->node);
-	}
+	cdd->is_suspended = false;
+	cppi41_run_queue(cdd);
 	spin_unlock_irqrestore(&cdd->lock, flags);
 
 	return 0;
Signature · 5 lines
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#4 lore raw
In reply to a message not in the archive
Quoted 5 lines · Tony Lindgren

Hi all,

I'm using v4 naming here as the earlier patch "dmaengine: cppi41: Add dma support to da8xx" has been separated from the error -115 issue. We've identified so far three musb and cppi41 regressions:

Hi,

Can we get some tested-by for this series?

Quoted 35 lines

1. Error -71 regression with musb

This is not dma related, and fixed with recently posted patch "[PATCH 1/2] usb: musb: Fix host mode error -71 regression".

2. Error -115 regression with cppi41 dma with musb

This regression was caused by commit 098de42ad670 ("dmaengine:
cppi41: Fix unpaired pm runtime when only a USB hub is connected") and causes runtime PM autosuspend delay to time out on active dma transfers when connecting a mass storage device to a usb hub. This is fixed in the first patch in this series.

3. Race with runtime PM and cppi41_dma_issue_pending()

This is really a separate issue from the error -115 problem, and fixed with the second patch in this series. That's minimal v4 version of the "dmaengine: cppi41: Fix oops in cppi41_runtime_resume" patch.

Regards,

Tony

Tony Lindgren (2):
dmaengine: cppi41: Fix runtime PM timeouts with USB mass storage
dmaengine: cppi41: Fix oops in cppi41_runtime_resume

 drivers/dma/cppi41.c | 56 ++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 41 insertions(+), 15 deletions(-)
Signature · 1 line
2.11.0
Signature · 5 lines
~Vinod
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tested-by Acked-by
#5 lore raw
Quoted 10 lines · Vinod Koul
Quoted 5 lines · Tony Lindgren

Hi all,

I'm using v4 naming here as the earlier patch "dmaengine: cppi41: Add dma support to da8xx" has been separated from the error -115 issue. We've identified so far three musb and cppi41 regressions:

Hi,

Can we get some tested-by for this series?

Regards,
-Bin.

Quoted 31 lines
Quoted 31 lines

1. Error -71 regression with musb

This is not dma related, and fixed with recently posted patch "[PATCH 1/2] usb: musb: Fix host mode error -71 regression".

2. Error -115 regression with cppi41 dma with musb

This regression was caused by commit 098de42ad670 ("dmaengine:
cppi41: Fix unpaired pm runtime when only a USB hub is connected") and causes runtime PM autosuspend delay to time out on active dma transfers when connecting a mass storage device to a usb hub. This is fixed in the first patch in this series.

3. Race with runtime PM and cppi41_dma_issue_pending()

This is really a separate issue from the error -115 problem, and fixed with the second patch in this series. That's minimal v4 version of the "dmaengine: cppi41: Fix oops in cppi41_runtime_resume" patch.

Regards,

Tony

Tony Lindgren (2):
dmaengine: cppi41: Fix runtime PM timeouts with USB mass storage
dmaengine: cppi41: Fix oops in cppi41_runtime_resume

Quoted 8 lines
Quoted 5 lines
 drivers/dma/cppi41.c | 56 ++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 41 insertions(+), 15 deletions(-)
Signature · 1 line
2.11.0
Signature · 1 line
~Vinod

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#6 lore raw

[PATCHv4 3/2] dmaengine: cppi41: Clean up pointless warnings

In reply to a message not in the archive

With patches "dmaengine: cppi41: Fix runtime PM timeouts with USB mass storage", and "dmaengine: cppi41: Fix oops in cppi41_runtime_resume", the pm_runtime_get/put() in cppi41_irq() is no longer needed. We now guarantee that cppi41 is enabled when dma is in use.

We can still get pointless error -115 when musb is configured as a usb peripheral. That's because we should now check for the state of is_suspended instead.

Let's just remove the now useless code and replace it with a WARN().

---

Found one more cosmetic issue. With patches 1/2 and 2/2 fixing the problems, this can now wait if considered not suitable for the -rc cycle.

---
 drivers/dma/cppi41.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)
drivers/dma/cppi41.c +5 -5
@@ -323,12 +323,12 @@ static irqreturn_t cppi41_irq(int irq, void *data)
 
 		while (val) {
 			u32 desc, len;
-			int error;
 
-			error = pm_runtime_get(cdd->ddev.dev);
-			if (error < 0)
-				dev_err(cdd->ddev.dev, "%s pm runtime get: %i\n",
-					__func__, error);
+			/*
+			 * This should never trigger, see the comments in
+			 * push_desc_queue()
+			 */
+			WARN_ON(cdd->is_suspended);
 
 			q_num = __fls(val);
 			val &= ~(1 << q_num);
@@ -349,9 +349,6 @@ static irqreturn_t cppi41_irq(int irq, void *data)
 			c->residue = pd_trans_len(c->desc->pd6) - len;
 			dma_cookie_complete(&c->txd);
 			dmaengine_desc_get_callback_invoke(&c->txd, NULL);

A message that is not in the archive (sent off-list or not yet received): [email protected]

#8 lore raw

Re: [PATCHv4 3/2] dmaengine: cppi41: Clean up pointless warnings

Quoted 8 lines · Tony Lindgren

With patches "dmaengine: cppi41: Fix runtime PM timeouts with USB mass storage", and "dmaengine: cppi41: Fix oops in cppi41_runtime_resume", the pm_runtime_get/put() in cppi41_irq() is no longer needed. We now guarantee that cppi41 is enabled when dma is in use.

We can still get pointless error -115 when musb is configured as a usb peripheral. That's because we should now check for the state of is_suspended instead.

I am not sure I understand this paragraph. Do you mean we still get harmless -115 in peripheral mode? If so how is it caused by is_suspended check? And the comment below for the check implies the WARN_ON() never happens...

Regards,
-Bin.

Quoted 47 lines

Let's just remove the now useless code and replace it with a WARN().

---

Found one more cosmetic issue. With patches 1/2 and 2/2 fixing the problems, this can now wait if considered not suitable for the -rc cycle.

---
 drivers/dma/cppi41.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)
drivers/dma/cppi41.c +5 -8
@@ -323,12 +323,12 @@ static irqreturn_t cppi41_irq(int irq, void *data)
 
 		while (val) {
 			u32 desc, len;
-			int error;
 
-			error = pm_runtime_get(cdd->ddev.dev);
-			if (error < 0)
-				dev_err(cdd->ddev.dev, "%s pm runtime get: %i\n",
-					__func__, error);
+			/*
+			 * This should never trigger, see the comments in
+			 * push_desc_queue()
+			 */
+			WARN_ON(cdd->is_suspended);
 
 			q_num = __fls(val);
 			val &= ~(1 << q_num);
@@ -349,9 +349,6 @@ static irqreturn_t cppi41_irq(int irq, void *data)
 			c->residue = pd_trans_len(c->desc->pd6) - len;
 			dma_cookie_complete(&c->txd);
 			dmaengine_desc_get_callback_invoke(&c->txd, NULL);
-
-			pm_runtime_mark_last_busy(cdd->ddev.dev);
-			pm_runtime_put_autosuspend(cdd->ddev.dev);
 		}
 	}
 	return IRQ_HANDLED;
Signature · 1 line
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#9 lore raw

Re: [PATCHv4 3/2] dmaengine: cppi41: Clean up pointless warnings

Quoted 6 lines · Bin Liu
Quoted 5 lines · Tony Lindgren

With patches "dmaengine: cppi41: Fix runtime PM timeouts with USB mass storage", and "dmaengine: cppi41: Fix oops in cppi41_runtime_resume", the pm_runtime_get/put() in cppi41_irq() is no longer needed. We now guarantee that cppi41 is enabled when dma is in use.

Quoted 8 lines
Quoted 3 lines

We can still get pointless error -115 when musb is configured as a usb peripheral. That's because we should now check for the state of is_suspended instead.

I am not sure I understand this paragraph. Do you mean we still get harmless -115 in peripheral mode? If so how is it caused by is_suspended check? And the comment below for the check implies the WARN_ON() never happens...

Yes I noticed we can still get it in peripheral mode. And it's a bogus warning now because we should now be using the new cdd->is_suspended instead.

It happens because cppi41_runtime_resume() has not yet completed and is calling cppi41_run_queue() that produces the interrupt. So that that point we have cppi41 active with !cdd->is_suspended, but pm_runtime_get() still returns -EINPROGRESS (115).

Regards,

Tony

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

Applied
#10 lore raw
In reply to a message not in the archive
Quoted 19 lines · Tony Lindgren

Hi all,

I'm using v4 naming here as the earlier patch "dmaengine: cppi41: Add dma support to da8xx" has been separated from the error -115 issue. We've identified so far three musb and cppi41 regressions:

1. Error -71 regression with musb

This is not dma related, and fixed with recently posted patch "[PATCH 1/2] usb: musb: Fix host mode error -71 regression".

2. Error -115 regression with cppi41 dma with musb

This regression was caused by commit 098de42ad670 ("dmaengine:
cppi41: Fix unpaired pm runtime when only a USB hub is connected") and causes runtime PM autosuspend delay to time out on active dma transfers when connecting a mass storage device to a usb hub. This is fixed in the first patch in this series.

Quoted 6 lines

3. Race with runtime PM and cppi41_dma_issue_pending()

This is really a separate issue from the error -115 problem, and fixed with the second patch in this series. That's minimal v4 version of the "dmaengine: cppi41: Fix oops in cppi41_runtime_resume" patch.

Applied, thanks

Signature · 5 lines
~Vinod
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html