All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] usb: dwc2: retry NAK'd interrupt transfers
@ 2015-04-12  3:52 Stephen Warren
  2015-04-12 23:19 ` Marek Vasut
  0 siblings, 1 reply; 2+ messages in thread
From: Stephen Warren @ 2015-04-12  3:52 UTC (permalink / raw)
  To: u-boot

IIUC, interrupt transfers are NAK'd by devices until they wish to trigger
an interrupt, and e.g. EHCI controllers retry these in HW until they are
ACK'd. However, DWC2 doesn't seem to retry, so we need to do this in SW.
In practice, I've seen DWC2_HCINT_FRMOVRUN happen too. I'm not quite sure
what this error implies; perhaps it's related to how near the end of a
USB frame we're at when the interrupt transfer is initiated? Anyway,
retrying this temporary error seems to be necessary too.

With all these commits applied, both my USB keyboards (one LS Lenovo and
one FS Dell) work correctly when there is no USB hub between the SoC and
the keyboard; We still need split transactions to be implemented for hubs
to work.

Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>
---
This replaces [RFC PATCH] usb: kbd: add transfer error interrupt handling.

Tested with this series on top of u-boot-usb/topic/dwc2 plus a patch to
enable USB keyboard in include/configs/rpi-common.h (see my github):

Model A, model A+:
* USB SD card reader
* Both keyboards
Early model B, model B, model B+, RPi 2:
* USB SD card reader
* Built-in Ethernet
Compute module:
* USB SD card reader
* For some reason, the keyboards are enumerated by don't yield keyboard
  events. I don't know why this is. Perhaps a USB power issue?
NVIDIA Tegra Seabord
* Built-in USB keyboard
---
 drivers/usb/host/dwc2.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index f3fbe76acf9b..2ac00177a20c 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -723,6 +723,8 @@ int wait_for_chhltd(uint32_t *sub, int *toggle, bool ignore_ack)
 		return ret;
 
 	hcint = readl(&hc_regs->hcint);
+	if (hcint & (DWC2_HCINT_NAK | DWC2_HCINT_FRMOVRUN))
+		return -EAGAIN;
 	if (ignore_ack)
 		hcint &= ~DWC2_HCINT_ACK;
 	else
@@ -758,7 +760,7 @@ int chunk_msg(struct usb_device *dev, unsigned long pipe, int *pid, int in,
 	int max = usb_maxpacket(dev, pipe);
 	int eptype = dwc2_eptype[usb_pipetype(pipe)];
 	int done = 0;
-	int ret;
+	int ret = 0;
 	uint32_t sub;
 	uint32_t xfer_len;
 	uint32_t num_packets;
@@ -813,10 +815,8 @@ int chunk_msg(struct usb_device *dev, unsigned long pipe, int *pid, int in,
 				DWC2_HCCHAR_CHEN);
 
 		ret = wait_for_chhltd(&sub, pid, ignore_ack);
-		if (ret) {
-			stop_transfer = 1;
+		if (ret)
 			break;
-		}
 
 		if (in) {
 			xfer_len -= sub;
@@ -835,7 +835,7 @@ int chunk_msg(struct usb_device *dev, unsigned long pipe, int *pid, int in,
 	dev->status = 0;
 	dev->act_len = done;
 
-	return 0;
+	return ret;
 }
 
 /* U-Boot USB transmission interface */
@@ -904,8 +904,21 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 		   int len, int interval)
 {
+	unsigned long timeout;
+	int ret;
+
 	/* FIXME: what is interval? */
-	return submit_bulk_msg(dev, pipe, buffer, len);
+
+	timeout = get_timer(0) + USB_TIMEOUT_MS(pipe);
+	for (;;) {
+		if (get_timer(0) > timeout) {
+			printf("Timeout poll on interrupt endpoint\n");
+			return -ETIMEDOUT;
+		}
+		ret = submit_bulk_msg(dev, pipe, buffer, len);
+		if (ret != -EAGAIN)
+			return ret;
+	}
 }
 
 /* U-Boot USB control interface */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [U-Boot] [PATCH] usb: dwc2: retry NAK'd interrupt transfers
  2015-04-12  3:52 [U-Boot] [PATCH] usb: dwc2: retry NAK'd interrupt transfers Stephen Warren
@ 2015-04-12 23:19 ` Marek Vasut
  0 siblings, 0 replies; 2+ messages in thread
From: Marek Vasut @ 2015-04-12 23:19 UTC (permalink / raw)
  To: u-boot

On Sunday, April 12, 2015 at 05:52:02 AM, Stephen Warren wrote:
> IIUC, interrupt transfers are NAK'd by devices until they wish to trigger
> an interrupt, and e.g. EHCI controllers retry these in HW until they are
> ACK'd. However, DWC2 doesn't seem to retry, so we need to do this in SW.
> In practice, I've seen DWC2_HCINT_FRMOVRUN happen too. I'm not quite sure
> what this error implies; perhaps it's related to how near the end of a
> USB frame we're at when the interrupt transfer is initiated? Anyway,
> retrying this temporary error seems to be necessary too.
> 
> With all these commits applied, both my USB keyboards (one LS Lenovo and
> one FS Dell) work correctly when there is no USB hub between the SoC and
> the keyboard; We still need split transactions to be implemented for hubs
> to work.
> 
> Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>

Applied to u-boot-usb/topic/dwc2 , thanks!

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-04-12 23:19 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-12  3:52 [U-Boot] [PATCH] usb: dwc2: retry NAK'd interrupt transfers Stephen Warren
2015-04-12 23:19 ` Marek Vasut

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.