forked from mirrors/nixpkgs
ubootRaspberryPi4_64bit: add patch for USB stall with non-MSD USB devices
This commit is contained in:
parent
11c1152e0f
commit
cff95d1193
|
@ -425,6 +425,7 @@ in {
|
|||
CONFIG_USB_XHCI_BRCM=y
|
||||
'';
|
||||
extraPatches = [
|
||||
./rpi-cm4/0002-usb-xhci-reset-endpoint-on-USB-stall.patch
|
||||
./rpi-cm4/0003-rpi-add-NVMe-to-boot-order.patch
|
||||
./rpi-cm4/0004-Revert-nvme-Correct-the-prps-per-page-calculation-me.patch
|
||||
./rpi-cm4/0005-usb-xhci-brcm-Make-driver-compatible-with-downstream.patch
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
From c942eb452c1c31fe6259178b6e9fea5456d7fb9c Mon Sep 17 00:00:00 2001
|
||||
Message-Id: <c942eb452c1c31fe6259178b6e9fea5456d7fb9c.1645627172.git.stefan@agner.ch>
|
||||
In-Reply-To: <24b77460dbfa2497ceb7a1611bf28b6eb88a1d74.1645627172.git.stefan@agner.ch>
|
||||
References: <24b77460dbfa2497ceb7a1611bf28b6eb88a1d74.1645627172.git.stefan@agner.ch>
|
||||
From: Stefan Agner <stefan@agner.ch>
|
||||
Date: Mon, 27 Sep 2021 12:28:04 +0200
|
||||
Subject: [PATCH 2/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 35bd5cd29e..430823cb9d 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
|
||||
@@ -928,6 +955,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.35.1
|
||||
|
Loading…
Reference in a new issue