forked from home-assistant/operating-system
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add USB stall handling for U-Boot (home-assistant#1011, home-assistan…
…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
Showing
5 changed files
with
101 additions
and
14 deletions.
There are no files selected for viewing
4 changes: 2 additions & 2 deletions
4
...oard/raspberrypi/patches/uboot/0001-rpi-Use-CONFIG_OF_BOARD-instead-of-CONFIG_EMBED.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 4 additions & 4 deletions
8
...board/raspberrypi/patches/uboot/0002-raspberrypi-Disable-simple-framebuffer-support.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 4 additions & 4 deletions
8
...raspberrypi/patches/uboot/0003-ARM-bcm283x-change-the-virtual-address-of-the-XHCI-P.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 4 additions & 4 deletions
8
...rd/raspberrypi/patches/uboot/0004-IOMUX-Fix-buffer-overflow-in-iomux_replace_device.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
...-external/board/raspberrypi/patches/uboot/0005-usb-xhci-reset-endpoint-on-USB-stall.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|