diff options
author | Bernardo Meurer <bernardo@meurer.org> | 2022-04-26 15:56:41 -0700 |
---|---|---|
committer | Bernardo Meurer <bernardo@meurer.org> | 2022-04-26 19:05:25 -0700 |
commit | cff95d119343fe2808516a0f8f86c8ba0963b29c (patch) | |
tree | 2b01aa29887da4177a1ccd486e809868d46e7f6a /pkgs/misc/uboot | |
parent | 11c1152e0f4f35e22249bc8d02e1d30e29b53032 (diff) |
ubootRaspberryPi4_64bit: add patch for USB stall with non-MSD USB devices
Diffstat (limited to 'pkgs/misc/uboot')
-rw-r--r-- | pkgs/misc/uboot/default.nix | 1 | ||||
-rw-r--r-- | pkgs/misc/uboot/rpi-cm4/0002-usb-xhci-reset-endpoint-on-USB-stall.patch | 87 |
2 files changed, 88 insertions, 0 deletions
diff --git a/pkgs/misc/uboot/default.nix b/pkgs/misc/uboot/default.nix index 92b03e7d863b..abcf0e027617 100644 --- a/pkgs/misc/uboot/default.nix +++ b/pkgs/misc/uboot/default.nix @@ -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 diff --git a/pkgs/misc/uboot/rpi-cm4/0002-usb-xhci-reset-endpoint-on-USB-stall.patch b/pkgs/misc/uboot/rpi-cm4/0002-usb-xhci-reset-endpoint-on-USB-stall.patch new file mode 100644 index 000000000000..52124de7da14 --- /dev/null +++ b/pkgs/misc/uboot/rpi-cm4/0002-usb-xhci-reset-endpoint-on-USB-stall.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 + |