diff mbox series

usb: dwc3: gadget: Disable gadget IRQ during pullup disable

Message ID 1621571037-1424-1-git-send-email-wcheng@codeaurora.org (mailing list archive)
State Accepted
Commit 8212937305f84ef73ea81036dafb80c557583d4b
Headers show
Series usb: dwc3: gadget: Disable gadget IRQ during pullup disable | expand

Commit Message

Wesley Cheng May 21, 2021, 4:23 a.m. UTC
Current sequence utilizes dwc3_gadget_disable_irq() alongside
synchronize_irq() to ensure that no further DWC3 events are generated.
However, the dwc3_gadget_disable_irq() API only disables device
specific events.  Endpoint events can still be generated.  Briefly
disable the interrupt line, so that the cleanup code can run to
prevent device and endpoint events. (i.e. __dwc3_gadget_stop() and
dwc3_stop_active_transfers() respectively)

Without doing so, it can lead to both the interrupt handler and the
pullup disable routine both writing to the GEVNTCOUNT register, which
will cause an incorrect count being read from future interrupts.

Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the controller")
Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
---
 drivers/usb/dwc3/gadget.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

Comments

Felipe Balbi June 10, 2021, 11:09 a.m. UTC | #1
Wesley Cheng <wcheng@codeaurora.org> writes:

> Current sequence utilizes dwc3_gadget_disable_irq() alongside
> synchronize_irq() to ensure that no further DWC3 events are generated.
> However, the dwc3_gadget_disable_irq() API only disables device
> specific events.  Endpoint events can still be generated.  Briefly
> disable the interrupt line, so that the cleanup code can run to
> prevent device and endpoint events. (i.e. __dwc3_gadget_stop() and
> dwc3_stop_active_transfers() respectively)
>
> Without doing so, it can lead to both the interrupt handler and the
> pullup disable routine both writing to the GEVNTCOUNT register, which
> will cause an incorrect count being read from future interrupts.
>
> Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the controller")
> Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
> ---
>  drivers/usb/dwc3/gadget.c | 11 +++++------
>  1 file changed, 5 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 49ca5da..89aa9ac 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -2260,13 +2260,10 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
>  	}
>  
>  	/*
> -	 * Synchronize any pending event handling before executing the controller
> -	 * halt routine.
> +	 * Synchronize and disable any further event handling while controller
> +	 * is being enabled/disabled.
>  	 */
> -	if (!is_on) {
> -		dwc3_gadget_disable_irq(dwc);
> -		synchronize_irq(dwc->irq_gadget);
> -	}
> +	disable_irq(dwc->irq_gadget);
>  
>  	spin_lock_irqsave(&dwc->lock, flags);

spin_lock_irqsave() is already disabling interrupt, right? Why do we
need another call to disable_irq()?
Wesley Cheng June 10, 2021, 6:21 p.m. UTC | #2
On 6/10/2021 4:09 AM, Felipe Balbi wrote:
> Wesley Cheng <wcheng@codeaurora.org> writes:
> 
>> Current sequence utilizes dwc3_gadget_disable_irq() alongside
>> synchronize_irq() to ensure that no further DWC3 events are generated.
>> However, the dwc3_gadget_disable_irq() API only disables device
>> specific events.  Endpoint events can still be generated.  Briefly
>> disable the interrupt line, so that the cleanup code can run to
>> prevent device and endpoint events. (i.e. __dwc3_gadget_stop() and
>> dwc3_stop_active_transfers() respectively)
>>
>> Without doing so, it can lead to both the interrupt handler and the
>> pullup disable routine both writing to the GEVNTCOUNT register, which
>> will cause an incorrect count being read from future interrupts.
>>
>> Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the controller")
>> Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
>> ---
>>  drivers/usb/dwc3/gadget.c | 11 +++++------
>>  1 file changed, 5 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index 49ca5da..89aa9ac 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -2260,13 +2260,10 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
>>  	}
>>  
>>  	/*
>> -	 * Synchronize any pending event handling before executing the controller
>> -	 * halt routine.
>> +	 * Synchronize and disable any further event handling while controller
>> +	 * is being enabled/disabled.
>>  	 */
>> -	if (!is_on) {
>> -		dwc3_gadget_disable_irq(dwc);
>> -		synchronize_irq(dwc->irq_gadget);
>> -	}
>> +	disable_irq(dwc->irq_gadget);
>>  
>>  	spin_lock_irqsave(&dwc->lock, flags);
> 
> spin_lock_irqsave() is already disabling interrupt, right? Why do we
> need another call to disable_irq()?
> 

Hi Felipe,

Yes, I remember you brought up that point as well before.  So when I
checked the logs (USB and scheduler ftrace) for this issue, I clearly
saw that we were handling a soft disconnect on CPU3 and then an DWC3 IRQ
being scheduled into CPU0.  Last time we discussed, I mentioned that
spin_lock_irqsave() only disables interrupts on that particular CPU the
thread is running on.

Thanks
Wesley Cheng
Wesley Cheng June 10, 2021, 8:27 p.m. UTC | #3
On 6/10/2021 11:21 AM, Wesley Cheng wrote:
> 
> 
> On 6/10/2021 4:09 AM, Felipe Balbi wrote:
>> Wesley Cheng <wcheng@codeaurora.org> writes:
>>
>>> Current sequence utilizes dwc3_gadget_disable_irq() alongside
>>> synchronize_irq() to ensure that no further DWC3 events are generated.
>>> However, the dwc3_gadget_disable_irq() API only disables device
>>> specific events.  Endpoint events can still be generated.  Briefly
>>> disable the interrupt line, so that the cleanup code can run to
>>> prevent device and endpoint events. (i.e. __dwc3_gadget_stop() and
>>> dwc3_stop_active_transfers() respectively)
>>>
>>> Without doing so, it can lead to both the interrupt handler and the
>>> pullup disable routine both writing to the GEVNTCOUNT register, which
>>> will cause an incorrect count being read from future interrupts.
>>>
>>> Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the controller")
>>> Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
>>> ---
>>>  drivers/usb/dwc3/gadget.c | 11 +++++------
>>>  1 file changed, 5 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>> index 49ca5da..89aa9ac 100644
>>> --- a/drivers/usb/dwc3/gadget.c
>>> +++ b/drivers/usb/dwc3/gadget.c
>>> @@ -2260,13 +2260,10 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
>>>  	}
>>>  
>>>  	/*
>>> -	 * Synchronize any pending event handling before executing the controller
>>> -	 * halt routine.
>>> +	 * Synchronize and disable any further event handling while controller
>>> +	 * is being enabled/disabled.
>>>  	 */
>>> -	if (!is_on) {
>>> -		dwc3_gadget_disable_irq(dwc);
>>> -		synchronize_irq(dwc->irq_gadget);
>>> -	}
>>> +	disable_irq(dwc->irq_gadget);
>>>  
>>>  	spin_lock_irqsave(&dwc->lock, flags);
>>
>> spin_lock_irqsave() is already disabling interrupt, right? Why do we
>> need another call to disable_irq()?
>>
> 
> Hi Felipe,
> 
> Yes, I remember you brought up that point as well before.  So when I
> checked the logs (USB and scheduler ftrace) for this issue, I clearly
> saw that we were handling a soft disconnect on CPU3 and then an DWC3 IRQ
> being scheduled into CPU0.  Last time we discussed, I mentioned that
> spin_lock_irqsave() only disables interrupts on that particular CPU the
> thread is running on.
> 
Hi Felipe,

Let me share the ftrace snippets as well:

USB FTRACE:

<idle>-0    [002]   304.567900:  dwc3_gadget_ep_cmd   name=ep0out
cmd=1030  param0=0  param1=4026523648  param2=0  cmd_status=0
<idle>-0    [004]   304.583225:  dwc3_gadget_ep_cmd   name=ep1out
cmd=134152  param0=0  param1=0  param2=0  cmd_status=0

//We don't have any logging in pullup disable, but this is when that
occurs, as we start to see -ESHUTDOWN statuses due to stop active
transfer.
<idle>-0    [004]   304.583237:  dwc3_gadget_giveback   name=ep1out
req=1243650560  actual=0  length=16384  status=4294967188  zero=0
short_not_ok=0  no_interrupt=0
<idle>-0    [004]   304.583275:  dwc3_gadget_giveback   name=ep1out
req=1243645440  actual=0  length=16384  status=4294967188  zero=0
short_not_ok=0  no_interrupt=0
<idle>-0    [004]   304.583282:  dwc3_gadget_giveback   name=ep1out
req=1243648256  actual=0  length=16384  status=4294967188  zero=0
short_not_ok=0  no_interrupt=0
<idle>-0    [004]   304.583312:  dwc3_gadget_giveback   name=ep1out
req=4075146240  actual=0  length=16384  status=4294967188  zero=0
short_not_ok=0  no_interrupt=0
...
//USB gadget disconnect is printed AFTER the pullup(0) routine is complete.
<idle>-0    [004]   304.584240:  usb_gadget_disconnect   speed=3
max_speed=6  state=7  mA=500  sg_supported=1  is_otg=0
is_a_peripheral=0  b_hnp_enable=0  a_hnp_support=0
hnp_polling_support=0  host_request_flag=0  quirk_ep_out_aligned_size=0
 quirk_altset_not_supp=0  quirk_stall_not_supp=0  quirk_zlp_not_supp=0
is_selfpowered=0  deactivated=0  connected=1  ret=4294967186

---------------------------------------------------------
CPU2 SCHED FTRACE:

kworker/u16:5-192    [002]   304.583354:  irq_handler_entry   irq=343
name=dwc3-msm
kworker/u16:5-192    [002]   304.583356:  irq_handler_exit   irq=343
ret=0
kworker/u16:5-192    [002]   304.583358:  irq_handler_entry   irq=343
name=dwc3
kworker/u16:5-192    [002]   304.583366:  irq_handler_exit   irq=343
ret=2
kworker/u16:5-192    [002]   304.583377:  sched_wakeup
comm=irq/343-dwc3  pid=20174  prio=100  success=1  target_cpu=2
kworker/u16:5-192   [002]  304.583411: sched_switch:
prev_comm=kworker/u16:5 prev_pid=192 prev_prio=120 prev_state=R ==>
next_comm=irq/343-dwc3 next_pid=20174 next_prio=100
irq/343-dwc3-20174    [002]   304.583454:  irq_handler_entry   irq=343
name=dwc3-msm
irq/343-dwc3-20174    [002]   304.583455:  irq_handler_exit   irq=343
ret=0
irq/343-dwc3-20174    [002]   304.583458:  irq_handler_entry   irq=343
name=dwc3
irq/343-dwc3-20174    [002]   304.583465:  irq_handler_exit   irq=343
ret=2

So if we assume that the point of error happens @ 304.567900 due to the
below points:
- DWC3 pullup disable routine synchronized IRQs (w/ previous logic)
before calling stop active transfers.
- DWC3 request statuses shows ESHUTDOWN, which occurs during stop active
transfer, as we call giveback w/ that error code

Then we can see that on CPU2, we're still getting DWC3 core IRQs, and
DWC3 IRQ handler is returning --> 2, which is IRQ_WAKE_THREAD.

Thanks
Wesley Cheng
Felipe Balbi June 11, 2021, 7:23 a.m. UTC | #4
Wesley Cheng <wcheng@codeaurora.org> writes:

> On 6/10/2021 11:21 AM, Wesley Cheng wrote:
>> 
>> 
>> On 6/10/2021 4:09 AM, Felipe Balbi wrote:
>>> Wesley Cheng <wcheng@codeaurora.org> writes:
>>>
>>>> Current sequence utilizes dwc3_gadget_disable_irq() alongside
>>>> synchronize_irq() to ensure that no further DWC3 events are generated.
>>>> However, the dwc3_gadget_disable_irq() API only disables device
>>>> specific events.  Endpoint events can still be generated.  Briefly
>>>> disable the interrupt line, so that the cleanup code can run to
>>>> prevent device and endpoint events. (i.e. __dwc3_gadget_stop() and
>>>> dwc3_stop_active_transfers() respectively)
>>>>
>>>> Without doing so, it can lead to both the interrupt handler and the
>>>> pullup disable routine both writing to the GEVNTCOUNT register, which
>>>> will cause an incorrect count being read from future interrupts.
>>>>
>>>> Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the controller")
>>>> Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
>>>> ---
>>>>  drivers/usb/dwc3/gadget.c | 11 +++++------
>>>>  1 file changed, 5 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>>> index 49ca5da..89aa9ac 100644
>>>> --- a/drivers/usb/dwc3/gadget.c
>>>> +++ b/drivers/usb/dwc3/gadget.c
>>>> @@ -2260,13 +2260,10 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
>>>>  	}
>>>>  
>>>>  	/*
>>>> -	 * Synchronize any pending event handling before executing the controller
>>>> -	 * halt routine.
>>>> +	 * Synchronize and disable any further event handling while controller
>>>> +	 * is being enabled/disabled.
>>>>  	 */
>>>> -	if (!is_on) {
>>>> -		dwc3_gadget_disable_irq(dwc);
>>>> -		synchronize_irq(dwc->irq_gadget);
>>>> -	}
>>>> +	disable_irq(dwc->irq_gadget);
>>>>  
>>>>  	spin_lock_irqsave(&dwc->lock, flags);
>>>
>>> spin_lock_irqsave() is already disabling interrupt, right? Why do we
>>> need another call to disable_irq()?
>>>
>> 
>> Hi Felipe,
>> 
>> Yes, I remember you brought up that point as well before.  So when I
>> checked the logs (USB and scheduler ftrace) for this issue, I clearly
>> saw that we were handling a soft disconnect on CPU3 and then an DWC3 IRQ
>> being scheduled into CPU0.  Last time we discussed, I mentioned that
>> spin_lock_irqsave() only disables interrupts on that particular CPU the
>> thread is running on.
>> 
> Hi Felipe,
>
> Let me share the ftrace snippets as well:
>
> USB FTRACE:
>
> <idle>-0    [002]   304.567900:  dwc3_gadget_ep_cmd name=ep0out cmd=1030  param0=0  param1=4026523648  param2=0  cmd_status=0
> <idle>-0    [004]   304.583225:  dwc3_gadget_ep_cmd name=ep1out cmd=134152  param0=0  param1=0  param2=0  cmd_status=0
>
> //We don't have any logging in pullup disable, but this is when that
> occurs, as we start to see -ESHUTDOWN statuses due to stop active
> transfer.

argh, maybe we should add :-)

I noticed that the logs here look different. Did you modify dwc3 trace
events or is it a special tracer (just curious)? Anyway...

> <idle>-0    [004]   304.583237:  dwc3_gadget_giveback name=ep1out req=1243650560  actual=0  length=16384  status=4294967188  zero=0 short_not_ok=0  no_interrupt=0
> <idle>-0    [004]   304.583275:  dwc3_gadget_giveback name=ep1out req=1243645440  actual=0  length=16384  status=4294967188  zero=0 short_not_ok=0  no_interrupt=0
> <idle>-0    [004]   304.583282:  dwc3_gadget_giveback name=ep1out req=1243648256  actual=0  length=16384  status=4294967188  zero=0 short_not_ok=0  no_interrupt=0
> <idle>-0    [004]   304.583312:  dwc3_gadget_giveback name=ep1out req=4075146240  actual=0  length=16384  status=4294967188  zero=0 short_not_ok=0  no_interrupt=0
> ...
> //USB gadget disconnect is printed AFTER the pullup(0) routine is complete.
> <idle>-0    [004]   304.584240:  usb_gadget_disconnect   speed=3 max_speed=6  state=7  mA=500  sg_supported=1  is_otg=0 is_a_peripheral=0  b_hnp_enable=0  a_hnp_support=0 hnp_polling_support=0  host_request_flag=0  quirk_ep_out_aligned_size=0 quirk_altset_not_supp=0  quirk_stall_not_supp=0  quirk_zlp_not_supp=0 is_selfpowered=0  deactivated=0  connected=1  ret=4294967186
>
> ---------------------------------------------------------
> CPU2 SCHED FTRACE:
>
> kworker/u16:5-192    [002]   304.583354:  irq_handler_entry   irq=343 name=dwc3-msm
> kworker/u16:5-192    [002]   304.583356:  irq_handler_exit   irq=343 ret=0
> kworker/u16:5-192    [002]   304.583358:  irq_handler_entry   irq=343 name=dwc3
> kworker/u16:5-192    [002]   304.583366:  irq_handler_exit   irq=343 ret=2
> kworker/u16:5-192    [002]   304.583377:  sched_wakeup comm=irq/343-dwc3  pid=20174  prio=100  success=1  target_cpu=2
> kworker/u16:5-192   [002]  304.583411: sched_switch: prev_comm=kworker/u16:5 prev_pid=192 prev_prio=120 prev_state=R ==> next_comm=irq/343-dwc3 next_pid=20174 next_prio=100
> irq/343-dwc3-20174    [002]   304.583454:  irq_handler_entry   irq=343 name=dwc3-msm
> irq/343-dwc3-20174    [002]   304.583455:  irq_handler_exit   irq=343 ret=0
> irq/343-dwc3-20174    [002]   304.583458:  irq_handler_entry   irq=343 name=dwc3
> irq/343-dwc3-20174    [002]   304.583465:  irq_handler_exit   irq=343 ret=2
>
> So if we assume that the point of error happens @ 304.567900 due to the
> below points:
> - DWC3 pullup disable routine synchronized IRQs (w/ previous logic)
> before calling stop active transfers.
> - DWC3 request statuses shows ESHUTDOWN, which occurs during stop active
> transfer, as we call giveback w/ that error code
>
> Then we can see that on CPU2, we're still getting DWC3 core IRQs, and
> DWC3 IRQ handler is returning --> 2, which is IRQ_WAKE_THREAD.

very good breakdown of the problem, thank you :-) What if we move the
spin_lock_irqsave() before that !is_on check and do away with
synchronize IRQ?

Then the only thing left would be ignore the interrupt events if they
still come, no?

Something like:

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 612825a39f82..aff9a4673830 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2260,20 +2260,12 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
                return 0;
        }

-       /*
-        * Synchronize any pending event handling before executing the controller
-        * halt routine.
-        */
-       if (!is_on) {
-               dwc3_gadget_disable_irq(dwc);
-               synchronize_irq(dwc->irq_gadget);
-       }
-
        spin_lock_irqsave(&dwc->lock, flags);

        if (!is_on) {
                u32 count;

+               dwc3_gadget_disable_irq(dwc);
                dwc->connected = false;
                /*
                 * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
@@ -3873,6 +3865,9 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
        if (!count)
                return IRQ_NONE;

+       if (!dwc->connected)
+               goto out_ignore;
+
        evt->count = count;
        evt->flags |= DWC3_EVENT_PENDING;

@@ -3887,6 +3882,7 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
        if (amount < count)
                memcpy(evt->cache, evt->buf, count - amount);

+out_ignore:
        dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);

        return IRQ_WAKE_THREAD;


(totally untested, mind you :)

Ignoring the events in dwc3_check_event_buf() may be unnecessary since
we're already doing that in dwc3_pullup() after __dwc3_gadget_stop().

What do you think?
Jack Pham June 14, 2021, 7:39 a.m. UTC | #5
On Fri, Jun 11, 2021 at 10:23:43AM +0300, Felipe Balbi wrote:
> Wesley Cheng <wcheng@codeaurora.org> writes:

<snip>

> > Hi Felipe,
> >
> > Let me share the ftrace snippets as well:
> >
> > USB FTRACE:
> >
> > <idle>-0    [002]   304.567900:  dwc3_gadget_ep_cmd name=ep0out cmd=1030  param0=0  param1=4026523648  param2=0  cmd_status=0
> > <idle>-0    [004]   304.583225:  dwc3_gadget_ep_cmd name=ep1out cmd=134152  param0=0  param1=0  param2=0  cmd_status=0
> >
> > //We don't have any logging in pullup disable, but this is when that
> > occurs, as we start to see -ESHUTDOWN statuses due to stop active
> > transfer.
> 
> argh, maybe we should add :-)
> 
> I noticed that the logs here look different. Did you modify dwc3 trace
> events or is it a special tracer (just curious)? Anyway...

These logs come from an internal tool that extracts the traces from a
complete RAM dump from a crashed device. One of the limitations is that
the script doesn't (yet) understand the event printk-formats so we're
left with just the raw field contents of the TP_STRUCT__entry. Not
pretty at all but it's *lot* better than nothing especially for
post-mortem analysis.

Yes there is crash-utility [1] which does all of this already but
logistically our internal tooling is not very well equipped (i.e. is
Windows-based) to make use of this, not without going through some
hoops. Been meaning to play around with it some more though to reduce
the need for our home-rolled solution.

[1] https://github.com/crash-utility

> > <idle>-0    [004]   304.583237:  dwc3_gadget_giveback name=ep1out req=1243650560  actual=0  length=16384  status=4294967188  zero=0 short_not_ok=0  no_interrupt=0
> > <idle>-0    [004]   304.583275:  dwc3_gadget_giveback name=ep1out req=1243645440  actual=0  length=16384  status=4294967188  zero=0 short_not_ok=0  no_interrupt=0
> > <idle>-0    [004]   304.583282:  dwc3_gadget_giveback name=ep1out req=1243648256  actual=0  length=16384  status=4294967188  zero=0 short_not_ok=0  no_interrupt=0
> > <idle>-0    [004]   304.583312:  dwc3_gadget_giveback name=ep1out req=4075146240  actual=0  length=16384  status=4294967188  zero=0 short_not_ok=0  no_interrupt=0
> > ...
> > //USB gadget disconnect is printed AFTER the pullup(0) routine is complete.
> > <idle>-0    [004]   304.584240:  usb_gadget_disconnect   speed=3 max_speed=6  state=7  mA=500  sg_supported=1  is_otg=0 is_a_peripheral=0  b_hnp_enable=0  a_hnp_support=0 hnp_polling_support=0  host_request_flag=0  quirk_ep_out_aligned_size=0 quirk_altset_not_supp=0  quirk_stall_not_supp=0  quirk_zlp_not_supp=0 is_selfpowered=0  deactivated=0  connected=1  ret=4294967186
> >
> > ---------------------------------------------------------
> > CPU2 SCHED FTRACE:
> >
> > kworker/u16:5-192    [002]   304.583354:  irq_handler_entry   irq=343 name=dwc3-msm
> > kworker/u16:5-192    [002]   304.583356:  irq_handler_exit   irq=343 ret=0
> > kworker/u16:5-192    [002]   304.583358:  irq_handler_entry   irq=343 name=dwc3
> > kworker/u16:5-192    [002]   304.583366:  irq_handler_exit   irq=343 ret=2
> > kworker/u16:5-192    [002]   304.583377:  sched_wakeup comm=irq/343-dwc3  pid=20174  prio=100  success=1  target_cpu=2
> > kworker/u16:5-192   [002]  304.583411: sched_switch: prev_comm=kworker/u16:5 prev_pid=192 prev_prio=120 prev_state=R ==> next_comm=irq/343-dwc3 next_pid=20174 next_prio=100
> > irq/343-dwc3-20174    [002]   304.583454:  irq_handler_entry   irq=343 name=dwc3-msm
> > irq/343-dwc3-20174    [002]   304.583455:  irq_handler_exit   irq=343 ret=0
> > irq/343-dwc3-20174    [002]   304.583458:  irq_handler_entry   irq=343 name=dwc3
> > irq/343-dwc3-20174    [002]   304.583465:  irq_handler_exit   irq=343 ret=2

Jack
diff mbox series

Patch

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 49ca5da..89aa9ac 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2260,13 +2260,10 @@  static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 	}
 
 	/*
-	 * Synchronize any pending event handling before executing the controller
-	 * halt routine.
+	 * Synchronize and disable any further event handling while controller
+	 * is being enabled/disabled.
 	 */
-	if (!is_on) {
-		dwc3_gadget_disable_irq(dwc);
-		synchronize_irq(dwc->irq_gadget);
-	}
+	disable_irq(dwc->irq_gadget);
 
 	spin_lock_irqsave(&dwc->lock, flags);
 
@@ -2304,6 +2301,8 @@  static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 
 	ret = dwc3_gadget_run_stop(dwc, is_on, false);
 	spin_unlock_irqrestore(&dwc->lock, flags);
+	enable_irq(dwc->irq_gadget);
+
 	pm_runtime_put(dwc->dev);
 
 	return ret;