diff mbox series

usb: chipidea: fix RT issue for udc

Message ID 20210810060228.GA3326442@ubuntu
State New
Headers show
Series usb: chipidea: fix RT issue for udc | expand

Commit Message

Jeaho Hwang Aug. 10, 2021, 6:02 a.m. UTC
hw_ep_prime sometimes fails if irq occurs while it rus on RT kernel.
to prevent local_irq_save should keep the function from irqs.

I am not sure where is the best to submit this patch, between RT and USB
community so sending to both. thanks.

Signed-off-by: Jeaho Hwang <jhhwang@rtst.co.kr>
---
 drivers/usb/chipidea/udc.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

Comments

Greg Kroah-Hartman Aug. 13, 2021, 7:08 a.m. UTC | #1
On Tue, Aug 10, 2021 at 03:02:28PM +0900, Jeaho Hwang wrote:
> hw_ep_prime sometimes fails if irq occurs while it rus on RT kernel.

> to prevent local_irq_save should keep the function from irqs.

> 

> I am not sure where is the best to submit this patch, between RT and USB

> community so sending to both. thanks.

> 

> Signed-off-by: Jeaho Hwang <jhhwang@rtst.co.kr>

> ---

>  drivers/usb/chipidea/udc.c | 31 +++++++++++++++++++++++++------

>  1 file changed, 25 insertions(+), 6 deletions(-)

> 

> diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c

> index 5f35cdd2cf1d..a90498f17cc4 100644

> --- a/drivers/usb/chipidea/udc.c

> +++ b/drivers/usb/chipidea/udc.c

> @@ -102,6 +102,9 @@ static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir)

>  {

>  	int n = hw_ep_bit(num, dir);

>  

> +    /* From zynq-7000 TRM, It can take a long time

> +     * so irq disable is not a good option for RT

> +     */


Please use checkpatch.pl when submitting patches :(
Peter Chen Aug. 16, 2021, 12:52 a.m. UTC | #2
On 21-08-10 15:02:28, Jeaho Hwang wrote:
> hw_ep_prime sometimes fails if irq occurs while it rus on RT kernel.

> to prevent local_irq_save should keep the function from irqs.

> 

> I am not sure where is the best to submit this patch, between RT and USB

> community so sending to both. thanks.


Greg, do you have any suggestions about it, the RT kernel schedules the interrupt
handler (top-half) out which causes the USB hardware atomic sequences are broken,
these hardware operations needs to be executed within limited time.

Peter
> 

> Signed-off-by: Jeaho Hwang <jhhwang@rtst.co.kr>

> ---

>  drivers/usb/chipidea/udc.c | 31 +++++++++++++++++++++++++------

>  1 file changed, 25 insertions(+), 6 deletions(-)

> 

> diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c

> index 5f35cdd2cf1d..a90498f17cc4 100644

> --- a/drivers/usb/chipidea/udc.c

> +++ b/drivers/usb/chipidea/udc.c

> @@ -102,6 +102,9 @@ static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir)

>  {

>  	int n = hw_ep_bit(num, dir);

>  

> +    /* From zynq-7000 TRM, It can take a long time

> +     * so irq disable is not a good option for RT

> +     */

>  	do {

>  		/* flush any pending transfer */

>  		hw_write(ci, OP_ENDPTFLUSH, ~0, BIT(n));

> @@ -190,22 +193,32 @@ static int hw_ep_get_halt(struct ci_hdrc *ci, int num, int dir)

>  static int hw_ep_prime(struct ci_hdrc *ci, int num, int dir, int is_ctrl)

>  {

>  	int n = hw_ep_bit(num, dir);

> +	unsigned long flags;

> +	int ret = 0;

>  

>  	/* Synchronize before ep prime */

>  	wmb();

>  

> -	if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num)))

> -		return -EAGAIN;

> +	/* irq affects this routine so irq should be disabled on RT.

> +	 * on standard kernel, irq is already disabled by callers.

> +	 */

> +	local_irq_save(flags);

> +	if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) {

> +		ret = -EAGAIN;

> +	goto out;

> +	}

>  

>  	hw_write(ci, OP_ENDPTPRIME, ~0, BIT(n));

>  

>  	while (hw_read(ci, OP_ENDPTPRIME, BIT(n)))

>  		cpu_relax();

>  	if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num)))

> -		return -EAGAIN;

> +		ret = -EAGAIN;

>  

> +out:

> +	local_irq_restore(flags);

>  	/* status shoult be tested according with manual but it doesn't work */

> -	return 0;

> +	return ret;

>  }

>  

>  /**

> -- 

> 2.25.1

> 


-- 

Thanks,
Peter Chen
Alan Stern Aug. 16, 2021, 1:03 a.m. UTC | #3
On Mon, Aug 16, 2021 at 08:52:06AM +0800, Peter Chen wrote:
> On 21-08-10 15:02:28, Jeaho Hwang wrote:

> > hw_ep_prime sometimes fails if irq occurs while it rus on RT kernel.

> > to prevent local_irq_save should keep the function from irqs.

> > 

> > I am not sure where is the best to submit this patch, between RT and USB

> > community so sending to both. thanks.

> 

> Greg, do you have any suggestions about it, the RT kernel schedules the interrupt

> handler (top-half) out which causes the USB hardware atomic sequences are broken,

> these hardware operations needs to be executed within limited time.


The RT kernel does its scheduling based on priorities.  If the 
interrupt handler is scheduled out, it's because some other process 
with a higher priority needs to run.  The answer should be to increase 
the handler's priority.

Alan Stern
Jeaho Hwang Aug. 16, 2021, 3:52 a.m. UTC | #4
2021년 8월 16일 (월) 오전 10:03, Alan Stern <stern@rowland.harvard.edu>님이 작성:
>

> On Mon, Aug 16, 2021 at 08:52:06AM +0800, Peter Chen wrote:

> > On 21-08-10 15:02:28, Jeaho Hwang wrote:

> > > hw_ep_prime sometimes fails if irq occurs while it rus on RT kernel.

> > > to prevent local_irq_save should keep the function from irqs.

> > >

> > > I am not sure where is the best to submit this patch, between RT and USB

> > > community so sending to both. thanks.

> >

> > Greg, do you have any suggestions about it, the RT kernel schedules the interrupt

> > handler (top-half) out which causes the USB hardware atomic sequences are broken,

> > these hardware operations needs to be executed within limited time.

>

> The RT kernel does its scheduling based on priorities.  If the

> interrupt handler is scheduled out, it's because some other process

> with a higher priority needs to run.  The answer should be to increase

> the handler's priority.


It is not a schedule issue. Priority does not prevent atomic sequences from irq
handlers which run in interrupt context. So we added local_irq_save to protect
explicitly and asked if it is the right approach.

In addition, I've checked if all functions in udc.c, which have the comment
"execute without interruption", need to be protected from irqs. And I think no
need for the others since they don't seem to have any contention between
tasks and the chip as hw_ep_prime has.

Thanks.
>

> Alan Stern
Greg Kroah-Hartman Aug. 16, 2021, 5:22 a.m. UTC | #5
On Mon, Aug 16, 2021 at 08:52:06AM +0800, Peter Chen wrote:
> On 21-08-10 15:02:28, Jeaho Hwang wrote:

> > hw_ep_prime sometimes fails if irq occurs while it rus on RT kernel.

> > to prevent local_irq_save should keep the function from irqs.

> > 

> > I am not sure where is the best to submit this patch, between RT and USB

> > community so sending to both. thanks.

> 

> Greg, do you have any suggestions about it, the RT kernel schedules the interrupt

> handler (top-half) out which causes the USB hardware atomic sequences are broken,

> these hardware operations needs to be executed within limited time.


Try working with the RT developers on this.
Jeaho Hwang Aug. 16, 2021, 7:10 a.m. UTC | #6
2021년 8월 16일 (월) 오후 2:22, Greg Kroah-Hartman <gregkh@linuxfoundation.org>님이 작성:
>

> On Mon, Aug 16, 2021 at 08:52:06AM +0800, Peter Chen wrote:

> > On 21-08-10 15:02:28, Jeaho Hwang wrote:

> > > hw_ep_prime sometimes fails if irq occurs while it rus on RT kernel.

> > > to prevent local_irq_save should keep the function from irqs.

> > >

> > > I am not sure where is the best to submit this patch, between RT and USB

> > > community so sending to both. thanks.

> >

> > Greg, do you have any suggestions about it, the RT kernel schedules the interrupt

> > handler (top-half) out which causes the USB hardware atomic sequences are broken,

> > these hardware operations needs to be executed within limited time.

>

> Try working with the RT developers on this.


Then do you think those kinds of patches should be applied to linux-rt
instead of mainline?

-- 
황재호, Jay Hwang, linux team manager of RTst
010-7242-1593
Greg Kroah-Hartman Aug. 16, 2021, 7:16 a.m. UTC | #7
On Mon, Aug 16, 2021 at 04:10:46PM +0900, Jeaho Hwang wrote:
> 2021년 8월 16일 (월) 오후 2:22, Greg Kroah-Hartman <gregkh@linuxfoundation.org>님이 작성:
> >
> > On Mon, Aug 16, 2021 at 08:52:06AM +0800, Peter Chen wrote:
> > > On 21-08-10 15:02:28, Jeaho Hwang wrote:
> > > > hw_ep_prime sometimes fails if irq occurs while it rus on RT kernel.
> > > > to prevent local_irq_save should keep the function from irqs.
> > > >
> > > > I am not sure where is the best to submit this patch, between RT and USB
> > > > community so sending to both. thanks.
> > >
> > > Greg, do you have any suggestions about it, the RT kernel schedules the interrupt
> > > handler (top-half) out which causes the USB hardware atomic sequences are broken,
> > > these hardware operations needs to be executed within limited time.
> >
> > Try working with the RT developers on this.
> 
> Then do you think those kinds of patches should be applied to linux-rt
> instead of mainline?

Depends on the resulting patch, if it is something that works for
mainline, then we will take it, otherwise if it is rt-only and is not
acceptable for mainline at this point in time, then it needs to go to
the rt tree until someone fixes it up there such that it can be
accepted.

thanks,

greg k-h
diff mbox series

Patch

diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 5f35cdd2cf1d..a90498f17cc4 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -102,6 +102,9 @@  static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir)
 {
 	int n = hw_ep_bit(num, dir);
 
+    /* From zynq-7000 TRM, It can take a long time
+     * so irq disable is not a good option for RT
+     */
 	do {
 		/* flush any pending transfer */
 		hw_write(ci, OP_ENDPTFLUSH, ~0, BIT(n));
@@ -190,22 +193,32 @@  static int hw_ep_get_halt(struct ci_hdrc *ci, int num, int dir)
 static int hw_ep_prime(struct ci_hdrc *ci, int num, int dir, int is_ctrl)
 {
 	int n = hw_ep_bit(num, dir);
+	unsigned long flags;
+	int ret = 0;
 
 	/* Synchronize before ep prime */
 	wmb();
 
-	if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num)))
-		return -EAGAIN;
+	/* irq affects this routine so irq should be disabled on RT.
+	 * on standard kernel, irq is already disabled by callers.
+	 */
+	local_irq_save(flags);
+	if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) {
+		ret = -EAGAIN;
+	goto out;
+	}
 
 	hw_write(ci, OP_ENDPTPRIME, ~0, BIT(n));
 
 	while (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
 		cpu_relax();
 	if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num)))
-		return -EAGAIN;
+		ret = -EAGAIN;
 
+out:
+	local_irq_restore(flags);
 	/* status shoult be tested according with manual but it doesn't work */
-	return 0;
+	return ret;
 }
 
 /**