Re: [PATCH v2 2/2] usb: dwc2: host: Clear interrupts before handling them

2015-11-19 Thread John Youn
On 11/19/2015 10:19 AM, Felipe Balbi wrote:
> 
> Hi,
> 
> Doug Anderson  writes:
> isn't this a regression ? You're first clearing the interrupts and only
> then reading to check what's pending, however, what's pending has just
> been cleared. Seems like this should be:
>
> hprt0 = dwc2_readl(HPRT0);
> dwc2_writeal(PRTINT, GINTSTS);

 Actually, we could probably remove the setting of GINTSTS_PRTINT
 completely.  The docs I have say that the GINTSTS_PRTINT is read only
 and that:

> The core sets this bit to indicate a change in port status of one of the
> DWC_otg core ports in Host mode. The application must read the
> Host Port Control and Status (HPRT) register to determine the exact
> event that caused this interrupt. The application must clear the
> appropriate status bit in the Host Port Control and Status register to
> clear this bit.

 ...so writing PRTINT is probably useless, but John can confirm.

>>>
>>> Yup, it seems it can be removed.
>>
>> How do you guys want this handled?  Should I send up a new version of
>> this patch?  ...or should I send a followon patch that does this
>> removal?
> 
> I'll leave the final decision to John, but my opinion is that a new
> version of the patch would be preferrable.
> 

Hi Doug,

Could you resend with the change?

Regards,
John

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


Re: [PATCH v2 2/2] usb: dwc2: host: Clear interrupts before handling them

2015-11-19 Thread Felipe Balbi

Hi,

Doug Anderson  writes:
 isn't this a regression ? You're first clearing the interrupts and only
 then reading to check what's pending, however, what's pending has just
 been cleared. Seems like this should be:

 hprt0 = dwc2_readl(HPRT0);
 dwc2_writeal(PRTINT, GINTSTS);
>>>
>>> Actually, we could probably remove the setting of GINTSTS_PRTINT
>>> completely.  The docs I have say that the GINTSTS_PRTINT is read only
>>> and that:
>>>
 The core sets this bit to indicate a change in port status of one of the
 DWC_otg core ports in Host mode. The application must read the
 Host Port Control and Status (HPRT) register to determine the exact
 event that caused this interrupt. The application must clear the
 appropriate status bit in the Host Port Control and Status register to
 clear this bit.
>>>
>>> ...so writing PRTINT is probably useless, but John can confirm.
>>>
>>
>> Yup, it seems it can be removed.
>
> How do you guys want this handled?  Should I send up a new version of
> this patch?  ...or should I send a followon patch that does this
> removal?

I'll leave the final decision to John, but my opinion is that a new
version of the patch would be preferrable.

-- 
balbi


signature.asc
Description: PGP signature


Re: [PATCH v2 2/2] usb: dwc2: host: Clear interrupts before handling them

2015-11-19 Thread Doug Anderson
Hi,

On Wed, Nov 18, 2015 at 5:43 PM, John Youn  wrote:
> On 11/16/2015 9:22 AM, Doug Anderson wrote:
>> Felipe,
>>
>> On Mon, Nov 16, 2015 at 8:28 AM, Felipe Balbi  wrote:
>>>
>>> Hi,
>>>
>>> Douglas Anderson  writes:
 In general it is wise to clear interrupts before processing them.  If
 you don't do that, you can get:
  1. Interrupt happens
  2. You look at system state and process interrupt
  3. A new interrupt happens
  4. You clear interrupt without processing it.

 This patch was actually a first attempt to fix missing device insertions
 as described in (usb: dwc2: host: Fix missing device insertions) and it
 did solve some of the signal bouncing problems but not all of
 them (which is why I submitted the other patch).  Specifically, this
 patch itself would sometimes change:
  1. hardware sees connect
  2. hardware sees disconnect
  3. hardware sees connect
  4. dwc2_port_intr() - clears connect interrupt
  5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect()

 ...to:
  1. hardware sees connect
  2. hardware sees disconnect
  3. dwc2_port_intr() - clears connect interrupt
  4. hardware sees connect
  5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect()

 ...but with different timing then sometimes we'd still miss cable
 insertions.

 In any case, though this patch doesn't fix any (known) problems, it
 still seems wise as a general policy to clear interrupt before handling
 them.

 Signed-off-by: Douglas Anderson 
 ---
 Changes in v2: None

  drivers/usb/dwc2/core_intr.c | 55 
 ++--
  drivers/usb/dwc2/hcd_intr.c  | 16 ++---
  2 files changed, 35 insertions(+), 36 deletions(-)

 diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
 index 61601d16e233..2a166b7eec41 100644
 --- a/drivers/usb/dwc2/core_intr.c
 +++ b/drivers/usb/dwc2/core_intr.c
 @@ -80,15 +80,16 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg 
 *hsotg)
   */
  static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
  {
 - u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
 + u32 hprt0;

 + /* Clear interrupt */
 + dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
 +
 + hprt0 = dwc2_readl(hsotg->regs + HPRT0);
   if (hprt0 & HPRT0_ENACHG) {
   hprt0 &= ~HPRT0_ENA;
   dwc2_writel(hprt0, hsotg->regs + HPRT0);
   }
 -
 - /* Clear interrupt */
 - dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
>>>
>>> isn't this a regression ? You're first clearing the interrupts and only
>>> then reading to check what's pending, however, what's pending has just
>>> been cleared. Seems like this should be:
>>>
>>> hprt0 = dwc2_readl(HPRT0);
>>> dwc2_writeal(PRTINT, GINTSTS);
>>
>> Actually, we could probably remove the setting of GINTSTS_PRTINT
>> completely.  The docs I have say that the GINTSTS_PRTINT is read only
>> and that:
>>
>>> The core sets this bit to indicate a change in port status of one of the
>>> DWC_otg core ports in Host mode. The application must read the
>>> Host Port Control and Status (HPRT) register to determine the exact
>>> event that caused this interrupt. The application must clear the
>>> appropriate status bit in the Host Port Control and Status register to
>>> clear this bit.
>>
>> ...so writing PRTINT is probably useless, but John can confirm.
>>
>
> Yup, it seems it can be removed.

How do you guys want this handled?  Should I send up a new version of
this patch?  ...or should I send a followon patch that does this
removal?

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


Re: [PATCH v2 2/2] usb: dwc2: host: Clear interrupts before handling them

2015-11-18 Thread John Youn
On 11/16/2015 9:22 AM, Doug Anderson wrote:
> Felipe,
> 
> On Mon, Nov 16, 2015 at 8:28 AM, Felipe Balbi  wrote:
>>
>> Hi,
>>
>> Douglas Anderson  writes:
>>> In general it is wise to clear interrupts before processing them.  If
>>> you don't do that, you can get:
>>>  1. Interrupt happens
>>>  2. You look at system state and process interrupt
>>>  3. A new interrupt happens
>>>  4. You clear interrupt without processing it.
>>>
>>> This patch was actually a first attempt to fix missing device insertions
>>> as described in (usb: dwc2: host: Fix missing device insertions) and it
>>> did solve some of the signal bouncing problems but not all of
>>> them (which is why I submitted the other patch).  Specifically, this
>>> patch itself would sometimes change:
>>>  1. hardware sees connect
>>>  2. hardware sees disconnect
>>>  3. hardware sees connect
>>>  4. dwc2_port_intr() - clears connect interrupt
>>>  5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect()
>>>
>>> ...to:
>>>  1. hardware sees connect
>>>  2. hardware sees disconnect
>>>  3. dwc2_port_intr() - clears connect interrupt
>>>  4. hardware sees connect
>>>  5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect()
>>>
>>> ...but with different timing then sometimes we'd still miss cable
>>> insertions.
>>>
>>> In any case, though this patch doesn't fix any (known) problems, it
>>> still seems wise as a general policy to clear interrupt before handling
>>> them.
>>>
>>> Signed-off-by: Douglas Anderson 
>>> ---
>>> Changes in v2: None
>>>
>>>  drivers/usb/dwc2/core_intr.c | 55 
>>> ++--
>>>  drivers/usb/dwc2/hcd_intr.c  | 16 ++---
>>>  2 files changed, 35 insertions(+), 36 deletions(-)
>>>
>>> diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
>>> index 61601d16e233..2a166b7eec41 100644
>>> --- a/drivers/usb/dwc2/core_intr.c
>>> +++ b/drivers/usb/dwc2/core_intr.c
>>> @@ -80,15 +80,16 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg 
>>> *hsotg)
>>>   */
>>>  static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
>>>  {
>>> - u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
>>> + u32 hprt0;
>>>
>>> + /* Clear interrupt */
>>> + dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
>>> +
>>> + hprt0 = dwc2_readl(hsotg->regs + HPRT0);
>>>   if (hprt0 & HPRT0_ENACHG) {
>>>   hprt0 &= ~HPRT0_ENA;
>>>   dwc2_writel(hprt0, hsotg->regs + HPRT0);
>>>   }
>>> -
>>> - /* Clear interrupt */
>>> - dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
>>
>> isn't this a regression ? You're first clearing the interrupts and only
>> then reading to check what's pending, however, what's pending has just
>> been cleared. Seems like this should be:
>>
>> hprt0 = dwc2_readl(HPRT0);
>> dwc2_writeal(PRTINT, GINTSTS);
> 
> Actually, we could probably remove the setting of GINTSTS_PRTINT
> completely.  The docs I have say that the GINTSTS_PRTINT is read only
> and that:
> 
>> The core sets this bit to indicate a change in port status of one of the
>> DWC_otg core ports in Host mode. The application must read the
>> Host Port Control and Status (HPRT) register to determine the exact
>> event that caused this interrupt. The application must clear the
>> appropriate status bit in the Host Port Control and Status register to
>> clear this bit.
> 
> ...so writing PRTINT is probably useless, but John can confirm.
> 

Yup, it seems it can be removed.

John


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


Re: [PATCH v2 2/2] usb: dwc2: host: Clear interrupts before handling them

2015-11-16 Thread Doug Anderson
Felipe,

On Mon, Nov 16, 2015 at 8:28 AM, Felipe Balbi  wrote:
>
> Hi,
>
> Douglas Anderson  writes:
>> In general it is wise to clear interrupts before processing them.  If
>> you don't do that, you can get:
>>  1. Interrupt happens
>>  2. You look at system state and process interrupt
>>  3. A new interrupt happens
>>  4. You clear interrupt without processing it.
>>
>> This patch was actually a first attempt to fix missing device insertions
>> as described in (usb: dwc2: host: Fix missing device insertions) and it
>> did solve some of the signal bouncing problems but not all of
>> them (which is why I submitted the other patch).  Specifically, this
>> patch itself would sometimes change:
>>  1. hardware sees connect
>>  2. hardware sees disconnect
>>  3. hardware sees connect
>>  4. dwc2_port_intr() - clears connect interrupt
>>  5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect()
>>
>> ...to:
>>  1. hardware sees connect
>>  2. hardware sees disconnect
>>  3. dwc2_port_intr() - clears connect interrupt
>>  4. hardware sees connect
>>  5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect()
>>
>> ...but with different timing then sometimes we'd still miss cable
>> insertions.
>>
>> In any case, though this patch doesn't fix any (known) problems, it
>> still seems wise as a general policy to clear interrupt before handling
>> them.
>>
>> Signed-off-by: Douglas Anderson 
>> ---
>> Changes in v2: None
>>
>>  drivers/usb/dwc2/core_intr.c | 55 
>> ++--
>>  drivers/usb/dwc2/hcd_intr.c  | 16 ++---
>>  2 files changed, 35 insertions(+), 36 deletions(-)
>>
>> diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
>> index 61601d16e233..2a166b7eec41 100644
>> --- a/drivers/usb/dwc2/core_intr.c
>> +++ b/drivers/usb/dwc2/core_intr.c
>> @@ -80,15 +80,16 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg 
>> *hsotg)
>>   */
>>  static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
>>  {
>> - u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
>> + u32 hprt0;
>>
>> + /* Clear interrupt */
>> + dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
>> +
>> + hprt0 = dwc2_readl(hsotg->regs + HPRT0);
>>   if (hprt0 & HPRT0_ENACHG) {
>>   hprt0 &= ~HPRT0_ENA;
>>   dwc2_writel(hprt0, hsotg->regs + HPRT0);
>>   }
>> -
>> - /* Clear interrupt */
>> - dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
>
> isn't this a regression ? You're first clearing the interrupts and only
> then reading to check what's pending, however, what's pending has just
> been cleared. Seems like this should be:
>
> hprt0 = dwc2_readl(HPRT0);
> dwc2_writeal(PRTINT, GINTSTS);

Actually, we could probably remove the setting of GINTSTS_PRTINT
completely.  The docs I have say that the GINTSTS_PRTINT is read only
and that:

> The core sets this bit to indicate a change in port status of one of the
> DWC_otg core ports in Host mode. The application must read the
> Host Port Control and Status (HPRT) register to determine the exact
> event that caused this interrupt. The application must clear the
> appropriate status bit in the Host Port Control and Status register to
> clear this bit.

...so writing PRTINT is probably useless, but John can confirm.

...if it wasn't useless to clear PRTINT it would depend on how things
were implemented.  One (purely speculative) case where my patch would
be more correct:

1. Interrupt source 1 in HPRT fires.  PRTINT is latched to 1 and
interrupt handler is called.
2. Read HPRT
3. Interrupt source 2 in HPRT fires.  PRTINT is already 1, so no new
interrupt handler called.
4. Clear PRTINT
5. Handle interrupt source 1

...now we'll never get an interrupt for interrupt source 2.


In any case, I think this particular change is a no-op, but other
changes in this patch (probably) aren't.


> Also, these two patches look very large for the -rc. I'll move them to
> v4.5 merge window unless you can convince me that they are, indeed, the
> smallest change possible to fix the problem you're facing and that they
> are, indeed, regressions.

Patch #2 should definitely _not_ go into the RC.  It is a relatively
intrusive patch, fixes no known issues, and has only had light
testing.  I haven't even landed this change locally in ChromeOS since
it's a bit scary to me I haven't found any good use for it.  I do keep
testing with it to see if it fixes any of my issues, though.  ;)


I'd like to see patch #1 should go into the RC since it fixes problems
that are really easy to reproduce.  IMHO It's also neither big nor
scary.  FWIW it's already landed in the ChromeOS tree as of Oct 20th
(almost a month).  While it hasn't hit stable channel yet, it's been
on beta channel and nobody has discovered any issues with it yet.


Thanks!  :)

-Doug
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.ker

Re: [PATCH v2 2/2] usb: dwc2: host: Clear interrupts before handling them

2015-11-16 Thread Felipe Balbi

Hi,

Douglas Anderson  writes:
> In general it is wise to clear interrupts before processing them.  If
> you don't do that, you can get:
>  1. Interrupt happens
>  2. You look at system state and process interrupt
>  3. A new interrupt happens
>  4. You clear interrupt without processing it.
>
> This patch was actually a first attempt to fix missing device insertions
> as described in (usb: dwc2: host: Fix missing device insertions) and it
> did solve some of the signal bouncing problems but not all of
> them (which is why I submitted the other patch).  Specifically, this
> patch itself would sometimes change:
>  1. hardware sees connect
>  2. hardware sees disconnect
>  3. hardware sees connect
>  4. dwc2_port_intr() - clears connect interrupt
>  5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect()
>
> ...to:
>  1. hardware sees connect
>  2. hardware sees disconnect
>  3. dwc2_port_intr() - clears connect interrupt
>  4. hardware sees connect
>  5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect()
>
> ...but with different timing then sometimes we'd still miss cable
> insertions.
>
> In any case, though this patch doesn't fix any (known) problems, it
> still seems wise as a general policy to clear interrupt before handling
> them.
>
> Signed-off-by: Douglas Anderson 
> ---
> Changes in v2: None
>
>  drivers/usb/dwc2/core_intr.c | 55 
> ++--
>  drivers/usb/dwc2/hcd_intr.c  | 16 ++---
>  2 files changed, 35 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
> index 61601d16e233..2a166b7eec41 100644
> --- a/drivers/usb/dwc2/core_intr.c
> +++ b/drivers/usb/dwc2/core_intr.c
> @@ -80,15 +80,16 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg 
> *hsotg)
>   */
>  static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
>  {
> - u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
> + u32 hprt0;
>  
> + /* Clear interrupt */
> + dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
> +
> + hprt0 = dwc2_readl(hsotg->regs + HPRT0);
>   if (hprt0 & HPRT0_ENACHG) {
>   hprt0 &= ~HPRT0_ENA;
>   dwc2_writel(hprt0, hsotg->regs + HPRT0);
>   }
> -
> - /* Clear interrupt */
> - dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);

isn't this a regression ? You're first clearing the interrupts and only
then reading to check what's pending, however, what's pending has just
been cleared. Seems like this should be:

hprt0 = dwc2_readl(HPRT0);
dwc2_writeal(PRTINT, GINTSTS);


Also, these two patches look very large for the -rc. I'll move them to
v4.5 merge window unless you can convince me that they are, indeed, the
smallest change possible to fix the problem you're facing and that they
are, indeed, regressions.

-- 
balbi


signature.asc
Description: PGP signature


Re: [PATCH v2 2/2] usb: dwc2: host: Clear interrupts before handling them

2015-11-04 Thread John Youn
On 11/3/2015 12:31 PM, Douglas Anderson wrote:
> In general it is wise to clear interrupts before processing them.  If
> you don't do that, you can get:
>  1. Interrupt happens
>  2. You look at system state and process interrupt
>  3. A new interrupt happens
>  4. You clear interrupt without processing it.
> 
> This patch was actually a first attempt to fix missing device insertions
> as described in (usb: dwc2: host: Fix missing device insertions) and it
> did solve some of the signal bouncing problems but not all of
> them (which is why I submitted the other patch).  Specifically, this
> patch itself would sometimes change:
>  1. hardware sees connect
>  2. hardware sees disconnect
>  3. hardware sees connect
>  4. dwc2_port_intr() - clears connect interrupt
>  5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect()
> 
> ...to:
>  1. hardware sees connect
>  2. hardware sees disconnect
>  3. dwc2_port_intr() - clears connect interrupt
>  4. hardware sees connect
>  5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect()
> 
> ...but with different timing then sometimes we'd still miss cable
> insertions.
> 
> In any case, though this patch doesn't fix any (known) problems, it
> still seems wise as a general policy to clear interrupt before handling
> them.
> 
> Signed-off-by: Douglas Anderson 
> ---
> Changes in v2: None
> 
>  drivers/usb/dwc2/core_intr.c | 55 
> ++--
>  drivers/usb/dwc2/hcd_intr.c  | 16 ++---
>  2 files changed, 35 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
> index 61601d16e233..2a166b7eec41 100644
> --- a/drivers/usb/dwc2/core_intr.c
> +++ b/drivers/usb/dwc2/core_intr.c
> @@ -80,15 +80,16 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg 
> *hsotg)
>   */
>  static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
>  {
> - u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
> + u32 hprt0;
>  
> + /* Clear interrupt */
> + dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
> +
> + hprt0 = dwc2_readl(hsotg->regs + HPRT0);
>   if (hprt0 & HPRT0_ENACHG) {
>   hprt0 &= ~HPRT0_ENA;
>   dwc2_writel(hprt0, hsotg->regs + HPRT0);
>   }
> -
> - /* Clear interrupt */
> - dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
>  }
>  
>  /**
> @@ -98,11 +99,11 @@ static void dwc2_handle_usb_port_intr(struct dwc2_hsotg 
> *hsotg)
>   */
>  static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg)
>  {
> - dev_warn(hsotg->dev, "Mode Mismatch Interrupt: currently in %s mode\n",
> -  dwc2_is_host_mode(hsotg) ? "Host" : "Device");
> -
>   /* Clear interrupt */
>   dwc2_writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
> +
> + dev_warn(hsotg->dev, "Mode Mismatch Interrupt: currently in %s mode\n",
> +  dwc2_is_host_mode(hsotg) ? "Host" : "Device");
>  }
>  
>  /**
> @@ -276,9 +277,13 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg 
> *hsotg)
>   */
>  static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
>  {
> - u32 gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
> + u32 gintmsk;
> +
> + /* Clear interrupt */
> + dwc2_writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
>  
>   /* Need to disable SOF interrupt immediately */
> + gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
>   gintmsk &= ~GINTSTS_SOF;
>   dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
>  
> @@ -295,9 +300,6 @@ static void dwc2_handle_conn_id_status_change_intr(struct 
> dwc2_hsotg *hsotg)
>   queue_work(hsotg->wq_otg, &hsotg->wf_otg);
>   spin_lock(&hsotg->lock);
>   }
> -
> - /* Clear interrupt */
> - dwc2_writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
>  }
>  
>  /**
> @@ -315,12 +317,12 @@ static void dwc2_handle_session_req_intr(struct 
> dwc2_hsotg *hsotg)
>  {
>   int ret;
>  
> - dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
> - hsotg->lx_state);
> -
>   /* Clear interrupt */
>   dwc2_writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
>  
> + dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
> + hsotg->lx_state);
> +
>   if (dwc2_is_device_mode(hsotg)) {
>   if (hsotg->lx_state == DWC2_L2) {
>   ret = dwc2_exit_hibernation(hsotg, true);
> @@ -347,6 +349,10 @@ static void dwc2_handle_session_req_intr(struct 
> dwc2_hsotg *hsotg)
>  static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
>  {
>   int ret;
> +
> + /* Clear interrupt */
> + dwc2_writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
> +
>   dev_dbg(hsotg->dev, "++Resume or Remote Wakeup Detected Interrupt++\n");
>   dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);
>  
> @@ -368,10 +374,9 @@ static void 

[PATCH v2 2/2] usb: dwc2: host: Clear interrupts before handling them

2015-11-03 Thread Douglas Anderson
In general it is wise to clear interrupts before processing them.  If
you don't do that, you can get:
 1. Interrupt happens
 2. You look at system state and process interrupt
 3. A new interrupt happens
 4. You clear interrupt without processing it.

This patch was actually a first attempt to fix missing device insertions
as described in (usb: dwc2: host: Fix missing device insertions) and it
did solve some of the signal bouncing problems but not all of
them (which is why I submitted the other patch).  Specifically, this
patch itself would sometimes change:
 1. hardware sees connect
 2. hardware sees disconnect
 3. hardware sees connect
 4. dwc2_port_intr() - clears connect interrupt
 5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect()

...to:
 1. hardware sees connect
 2. hardware sees disconnect
 3. dwc2_port_intr() - clears connect interrupt
 4. hardware sees connect
 5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect()

...but with different timing then sometimes we'd still miss cable
insertions.

In any case, though this patch doesn't fix any (known) problems, it
still seems wise as a general policy to clear interrupt before handling
them.

Signed-off-by: Douglas Anderson 
---
Changes in v2: None

 drivers/usb/dwc2/core_intr.c | 55 ++--
 drivers/usb/dwc2/hcd_intr.c  | 16 ++---
 2 files changed, 35 insertions(+), 36 deletions(-)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 61601d16e233..2a166b7eec41 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -80,15 +80,16 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg 
*hsotg)
  */
 static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
 {
-   u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
+   u32 hprt0;
 
+   /* Clear interrupt */
+   dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
+
+   hprt0 = dwc2_readl(hsotg->regs + HPRT0);
if (hprt0 & HPRT0_ENACHG) {
hprt0 &= ~HPRT0_ENA;
dwc2_writel(hprt0, hsotg->regs + HPRT0);
}
-
-   /* Clear interrupt */
-   dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
 }
 
 /**
@@ -98,11 +99,11 @@ static void dwc2_handle_usb_port_intr(struct dwc2_hsotg 
*hsotg)
  */
 static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg)
 {
-   dev_warn(hsotg->dev, "Mode Mismatch Interrupt: currently in %s mode\n",
-dwc2_is_host_mode(hsotg) ? "Host" : "Device");
-
/* Clear interrupt */
dwc2_writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
+
+   dev_warn(hsotg->dev, "Mode Mismatch Interrupt: currently in %s mode\n",
+dwc2_is_host_mode(hsotg) ? "Host" : "Device");
 }
 
 /**
@@ -276,9 +277,13 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
  */
 static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
 {
-   u32 gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
+   u32 gintmsk;
+
+   /* Clear interrupt */
+   dwc2_writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
 
/* Need to disable SOF interrupt immediately */
+   gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
gintmsk &= ~GINTSTS_SOF;
dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
 
@@ -295,9 +300,6 @@ static void dwc2_handle_conn_id_status_change_intr(struct 
dwc2_hsotg *hsotg)
queue_work(hsotg->wq_otg, &hsotg->wf_otg);
spin_lock(&hsotg->lock);
}
-
-   /* Clear interrupt */
-   dwc2_writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
 }
 
 /**
@@ -315,12 +317,12 @@ static void dwc2_handle_session_req_intr(struct 
dwc2_hsotg *hsotg)
 {
int ret;
 
-   dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
-   hsotg->lx_state);
-
/* Clear interrupt */
dwc2_writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
 
+   dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
+   hsotg->lx_state);
+
if (dwc2_is_device_mode(hsotg)) {
if (hsotg->lx_state == DWC2_L2) {
ret = dwc2_exit_hibernation(hsotg, true);
@@ -347,6 +349,10 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg 
*hsotg)
 static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
 {
int ret;
+
+   /* Clear interrupt */
+   dwc2_writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
+
dev_dbg(hsotg->dev, "++Resume or Remote Wakeup Detected Interrupt++\n");
dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);
 
@@ -368,10 +374,9 @@ static void dwc2_handle_wakeup_detected_intr(struct 
dwc2_hsotg *hsotg)
/* Change to L0 state */
hsotg->lx_state = DWC2_L0;
} else {
-   if (hsotg->core_params->hibernation) {
-