cppi41 dma fixes for v4.10-rc cycle
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
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.
only a USB hub is connected")
--- 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
PATCH v4 2/2 dmaengine: cppi41: Fix oops in cppi41_runtime_resume
In reply to a message not in the archiveCommit 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.
--- 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
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 incppi41_runtime_resumedrivers/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
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 incppi41_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.0Signature · 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
[PATCHv4 3/2] dmaengine: cppi41: Clean up pointless warnings
In reply to a message not in the archiveWith 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]
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() incppi41_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_suspendedinstead.
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().Signed-off-by Tony Lindgren <[email protected]>---
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
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() incppi41_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_suspendedinstead.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_suspendedcheck? And the comment below for the check implies theWARN_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
Vinod Koul
AppliedQuoted 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