Skip to contentSkip to conversation

usb: chipidea: fix RT issue for udc

PATCH In review Jeaho Hwang 4 participants 8 messages Aug 10, 2021 – Aug 16, 2021

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 usb: chipidea: fix RT issue for udc

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.

---
 drivers/usb/chipidea/udc.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)
drivers/usb/chipidea/udc.c +17 -4
index 5f35cdd2cf1d..a90498f17cc4 100644
@@ -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;
 }
 
 /**
Signature · 1 line
2.25.1
#1 lore raw
Quoted 16 lines · Jeaho Hwang

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.

---
 drivers/usb/chipidea/udc.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)
drivers/usb/chipidea/udc.c +0 -0
index 5f35cdd2cf1d..a90498f17cc4 100644

drivers/usb/chipidea/udc.c static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir) · line 107

Quoted 6 lines
drivers/usb/chipidea/udc.c +3 -0
@@ -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 :(

maintainer
#2 lore raw
In reply to Jeaho Hwang
Quoted 5 lines · Jeaho Hwang

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

Quoted 60 lines
---
 drivers/usb/chipidea/udc.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)
drivers/usb/chipidea/udc.c +17 -4
index 5f35cdd2cf1d..a90498f17cc4 100644
@@ -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;
 }
 
 /**
Signature · 1 line
2.25.1
Signature · 2 lines
Thanks,
Peter Chen
#3 lore raw
Quoted 10 lines · Peter Chen
Quoted 5 lines · Jeaho Hwang

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

#4 lore raw

2021년 8월 16일 (월) 오전 10:03, Alan Stern <[email protected]>님이 작성:

Quoted 9 lines · Peter Chen
Quoted 7 lines · Jeaho Hwang
Quoted 5 lines

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.

Quoted 8 lines
Quoted 3 lines

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.

Quoted 2 lines

Alan Stern

#5 lore raw
In reply to Peter Chen
Quoted 10 lines · Peter Chen
Quoted 5 lines · Jeaho Hwang

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.

#6 lore raw

2021년 8월 16일 (월) 오후 2:22, Greg Kroah-Hartman <[email protected]>님이 작성:

Quoted 6 lines · Peter Chen
Quoted 4 lines · Jeaho Hwang
Quoted 3 lines

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.

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

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?

Signature · 2 lines
황재호, Jay Hwang, linux team manager of RTst
010-7242-1593
#7 lore raw
Quoted 10 lines · Jeaho Hwang

2021년 8월 16일 (월) 오후 2:22, Greg Kroah-Hartman <[email protected]>님이 작성:

Quoted 9 lines · Peter Chen
Quoted 7 lines · Jeaho Hwang
Quoted 5 lines

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.

Quoted 8 lines
Quoted 5 lines
Quoted 3 lines

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