From 1f856c46b0ba892911b571f1370bc1a9ccd80ac0 Mon Sep 17 00:00:00 2001 From: Jack Humbert <jack.humb@gmail.com> Date: Fri, 14 Apr 2023 17:15:16 -0400 Subject: [PATCH] disable resetting when endpoint error occurs --- drivers/usb/host/xhci-ring.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b2cfd948f81..bd353aef3c5 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -473,6 +473,35 @@ 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). + * from https://github.com/agners/operating-system/blob/c3288801d7ff35c12d33d0e883dac246c4fc8a5a/buildroot-external/board/raspberrypi/patches/uboot/0005-usb-xhci-reset-endpoint-on-USB-stall.patch + */ +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; + + // bit hard to type with this notification + //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 @@ -918,6 +947,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) -- GitLab