diff mbox

[U-Boot,2/7] usb: dwc2: Resend setup packet in all fail cases

Message ID 1462308680-9366-2-git-send-email-marex@denx.de
State Deferred
Delegated to: Marek Vasut
Headers show

Commit Message

Marek Vasut May 3, 2016, 8:51 p.m. UTC
The USB function can respond to a Setup packet with ACK or, in
case it's busy, it can ignore the Setup packet. The USB function
usually gets busy if we hammer it with Control EP transfers too
much (ie. sending multiple Get Descriptor requests in a single
microframe tends to trigger it on certain USB sticks). The DWC2
controller will interpret not receiving an ACK after Setup packet
as XACTERR. Check for this condition and if it happens, retry
sending the Setup packet.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chin Liang See <clsee@altera.com>
Cc: Dinh Nguyen <dinguyen@opensource.altera.com>
Cc: Hans de Goede <hdegoede@redhat.com>
Cc: Stefan Roese <sr@denx.de>
Cc: Stephen Warren <swarren@nvidia.com>
---
 drivers/usb/host/dwc2.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

Comments

Chin Liang See May 4, 2016, 9:36 a.m. UTC | #1
On Tue, 2016-05-03 at 22:51 +0200, Marek Vasut wrote:
> The USB function can respond to a Setup packet with ACK or, in
> case it's busy, it can ignore the Setup packet. The USB function
> usually gets busy if we hammer it with Control EP transfers too
> much (ie. sending multiple Get Descriptor requests in a single
> microframe tends to trigger it on certain USB sticks). The DWC2
> controller will interpret not receiving an ACK after Setup packet
> as XACTERR. Check for this condition and if it happens, retry
> sending the Setup packet.
> 
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Chin Liang See <clsee@altera.com>
> Cc: Dinh Nguyen <dinguyen@opensource.altera.com>
> Cc: Hans de Goede <hdegoede@redhat.com>
> Cc: Stefan Roese <sr@denx.de>
> Cc: Stephen Warren <swarren@nvidia.com>
> ---
>  drivers/usb/host/dwc2.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 

Reviewed-by: Chin Liang See <clsee@altera.com>
Tested-by: Chin Liang See <clsee@altera.com>

Thanks
Chin Liang
diff mbox

Patch

diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 30b51b3..8d3949e 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -737,6 +737,7 @@  int wait_for_chhltd(struct dwc2_hc_regs *hc_regs, uint32_t *sub, u8 *toggle)
 {
 	int ret;
 	uint32_t hcint, hctsiz;
+	u8 pid = *toggle;
 
 	ret = wait_for_bit(__func__, &hc_regs->hcint, DWC2_HCINT_CHHLTD, true,
 			   1000, false);
@@ -758,6 +759,19 @@  int wait_for_chhltd(struct dwc2_hc_regs *hc_regs, uint32_t *sub, u8 *toggle)
 	if (hcint & (DWC2_HCINT_NAK | DWC2_HCINT_FRMOVRUN))
 		return -EAGAIN;
 
+	/*
+	 * The USB function can respond to a Setup packet with ACK or, in
+	 * case it's busy, it can ignore the Setup packet. The USB function
+	 * usually gets busy if we hammer it with Control EP transfers too
+	 * much (ie. sending multiple Get Descriptor requests in a single
+	 * microframe tends to trigger it on certain USB sticks). The DWC2
+	 * controller will interpret not receiving an ACK after Setup packet
+	 * as XACTERR. Check for this condition and if it happens, retry
+	 * sending the Setup packet.
+	 */
+	if (hcint & DWC2_HCINT_XACTERR && (pid == DWC2_HC_PID_SETUP))
+		return -EAGAIN;
+
 	debug("%s: Error (HCINT=%08x)\n", __func__, hcint);
 	return -EINVAL;
 }