Skip to content

Commit

Permalink
Add USB stall handling for U-Boot (home-assistant#1011, home-assistan…
Browse files Browse the repository at this point in the history
…t#1544)

Some USB devices cause the USB stack to get stuck with a TRB stall
error. This adds a patch which recovers from this situation.

This avoids an U-Boot crash when Arduino Mega R3 devices are connected,
which cause an USB stall when trying to read the product string.
  • Loading branch information
agners committed Sep 27, 2021
1 parent 1e7cd66 commit c328880
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 14 deletions.
@@ -1,8 +1,8 @@
From 9cb97076d98f7f68534abb3d1f596644ae730841 Mon Sep 17 00:00:00 2001
Message-Id: <9cb97076d98f7f68534abb3d1f596644ae730841.1631043469.git.stefan@agner.ch>
Message-Id: <9cb97076d98f7f68534abb3d1f596644ae730841.1632740631.git.stefan@agner.ch>
From: Pascal Vizeli <pvizeli@syshack.ch>
Date: Tue, 10 Dec 2019 09:48:46 +0000
Subject: [PATCH 1/4] rpi: Use CONFIG_OF_BOARD instead of CONFIG_EMBED
Subject: [PATCH 1/5] rpi: Use CONFIG_OF_BOARD instead of CONFIG_EMBED

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>
---
Expand Down
@@ -1,10 +1,10 @@
From 69ac2930e69ca876f8da95d80f4a1cb8cc23bb6a Mon Sep 17 00:00:00 2001
Message-Id: <69ac2930e69ca876f8da95d80f4a1cb8cc23bb6a.1631043469.git.stefan@agner.ch>
In-Reply-To: <9cb97076d98f7f68534abb3d1f596644ae730841.1631043469.git.stefan@agner.ch>
References: <9cb97076d98f7f68534abb3d1f596644ae730841.1631043469.git.stefan@agner.ch>
Message-Id: <69ac2930e69ca876f8da95d80f4a1cb8cc23bb6a.1632740631.git.stefan@agner.ch>
In-Reply-To: <9cb97076d98f7f68534abb3d1f596644ae730841.1632740631.git.stefan@agner.ch>
References: <9cb97076d98f7f68534abb3d1f596644ae730841.1632740631.git.stefan@agner.ch>
From: Florin Sarbu <florin@balena.io>
Date: Thu, 12 Sep 2019 12:31:31 +0200
Subject: [PATCH 2/4] raspberrypi: Disable simple framebuffer support
Subject: [PATCH 2/5] raspberrypi: Disable simple framebuffer support

On 4.19 kernels this u-boot driver clashes with bcm2708_fb.
So let's disable it from here so that we have bcm2708_fb
Expand Down
@@ -1,10 +1,10 @@
From 72619dd5d0be59e702fd7b7090916ee688c34180 Mon Sep 17 00:00:00 2001
Message-Id: <72619dd5d0be59e702fd7b7090916ee688c34180.1631043469.git.stefan@agner.ch>
In-Reply-To: <9cb97076d98f7f68534abb3d1f596644ae730841.1631043469.git.stefan@agner.ch>
References: <9cb97076d98f7f68534abb3d1f596644ae730841.1631043469.git.stefan@agner.ch>
Message-Id: <72619dd5d0be59e702fd7b7090916ee688c34180.1632740631.git.stefan@agner.ch>
In-Reply-To: <9cb97076d98f7f68534abb3d1f596644ae730841.1632740631.git.stefan@agner.ch>
References: <9cb97076d98f7f68534abb3d1f596644ae730841.1632740631.git.stefan@agner.ch>
From: Marek Szyprowski <m.szyprowski@samsung.com>
Date: Thu, 17 Jun 2021 11:22:03 +0200
Subject: [PATCH 3/4] ARM: bcm283x: change the virtual address of the XHCI PCI
Subject: [PATCH 3/5] ARM: bcm283x: change the virtual address of the XHCI PCI
device base

Move the XHCI PCI device base up in the virtual address space. This fixes
Expand Down
@@ -1,10 +1,10 @@
From 0a33e4e03b9266818d6f0a6d566bf12be55c657c Mon Sep 17 00:00:00 2001
Message-Id: <0a33e4e03b9266818d6f0a6d566bf12be55c657c.1631043469.git.stefan@agner.ch>
In-Reply-To: <9cb97076d98f7f68534abb3d1f596644ae730841.1631043469.git.stefan@agner.ch>
References: <9cb97076d98f7f68534abb3d1f596644ae730841.1631043469.git.stefan@agner.ch>
Message-Id: <0a33e4e03b9266818d6f0a6d566bf12be55c657c.1632740631.git.stefan@agner.ch>
In-Reply-To: <9cb97076d98f7f68534abb3d1f596644ae730841.1632740631.git.stefan@agner.ch>
References: <9cb97076d98f7f68534abb3d1f596644ae730841.1632740631.git.stefan@agner.ch>
From: Yuichiro Goto <goto@k-tech.co.jp>
Date: Mon, 26 Apr 2021 08:08:03 +0900
Subject: [PATCH 4/4] IOMUX: Fix buffer overflow in iomux_replace_device()
Subject: [PATCH 4/5] IOMUX: Fix buffer overflow in iomux_replace_device()

Use of strcat() against an uninitialized buffer would lead
to buffer overflow. This patch fixes it.
Expand Down
@@ -0,0 +1,87 @@
From 194a2cb0e38c8684e9c98aa66ba3d3a838fce9d6 Mon Sep 17 00:00:00 2001
Message-Id: <194a2cb0e38c8684e9c98aa66ba3d3a838fce9d6.1632740631.git.stefan@agner.ch>
In-Reply-To: <9cb97076d98f7f68534abb3d1f596644ae730841.1632740631.git.stefan@agner.ch>
References: <9cb97076d98f7f68534abb3d1f596644ae730841.1632740631.git.stefan@agner.ch>
From: Stefan Agner <stefan@agner.ch>
Date: Mon, 27 Sep 2021 12:28:04 +0200
Subject: [PATCH 5/5] usb: xhci: reset endpoint on USB stall

There are devices which cause a USB stall when trying to read strings.
Specifically Arduino Mega R3 stalls when trying to read the product
string.

The stall currently remains unhandled, and subsequent retries submit new
transfers on a stopped endpoint which ultimately cause a crash in
abort_td():
WARN halted endpoint, queueing URB anyway.
XHCI control transfer timed out, aborting...
Unexpected XHCI event TRB, skipping... (3affe040 00000000 13000000 02008401)
BUG at drivers/usb/host/xhci-ring.c:505/abort_td()!
BUG!
resetting ...

Linux seems to be able to recover from the stall by issuing a
TRB_RESET_EP command.

Introduce reset_ep() which issues a TRB_RESET_EP followed by setting the
transfer ring dequeue pointer via TRB_SET_DEQ. This allows to properly
recover from a USB stall error and continue communicating with the USB
device.

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
drivers/usb/host/xhci-ring.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 46c137f857..667e9fbf5e 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -481,6 +481,33 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected)
BUG();
}

+/*
+ * Issue reset endpoint command for an endpoint. This is required to recover
+ * a halted endpoint (e.g. due to a stall error).
+ */
+static void reset_ep(struct usb_device *udev, int ep_index)
+{
+ struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
+ struct xhci_ring *ring = ctrl->devs[udev->slot_id]->eps[ep_index].ring;
+ union xhci_trb *event;
+ u32 field;
+
+ printf("Resetting EP...\n");
+ xhci_queue_command(ctrl, NULL, udev->slot_id, ep_index, TRB_RESET_EP);
+ event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
+ field = le32_to_cpu(event->trans_event.flags);
+ BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id);
+ xhci_acknowledge_event(ctrl);
+
+ xhci_queue_command(ctrl, (void *)((uintptr_t)ring->enqueue |
+ ring->cycle_state), udev->slot_id, ep_index, TRB_SET_DEQ);
+ event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
+ BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags))
+ != udev->slot_id || GET_COMP_CODE(le32_to_cpu(
+ event->event_cmd.status)) != COMP_SUCCESS);
+ xhci_acknowledge_event(ctrl);
+}
+
/*
* Stops transfer processing for an endpoint and throws away all unprocessed
* TRBs by setting the xHC's dequeue pointer to our enqueue pointer. The next
@@ -931,6 +958,10 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,

record_transfer_result(udev, event, length);
xhci_acknowledge_event(ctrl);
+ if (udev->status == USB_ST_STALLED) {
+ reset_ep(udev, ep_index);
+ return -EPIPE;
+ }

/* Invalidate buffer to make it available to usb-core */
if (length > 0)
--
2.33.0

0 comments on commit c328880

Please sign in to comment.