From aab169feaa776f02bcffc67718efa1f75fa939dd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 2 Dec 2024 10:13:59 +0100 Subject: [PATCH] drop queue-6.6/xhci-dbc-fix-stall-transfer-event-handling.patch --- queue-6.6/series | 1 - ...bc-fix-stall-transfer-event-handling.patch | 283 ------------------ 2 files changed, 284 deletions(-) delete mode 100644 queue-6.6/xhci-dbc-fix-stall-transfer-event-handling.patch diff --git a/queue-6.6/series b/queue-6.6/series index 55d103486c1..4c19a4adea0 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -451,4 +451,3 @@ asoc-amd-yc-fix-for-enabling-dmic-on-acp6x-via-_dsd-.patch gfs2-don-t-set-glf_lock-in-gfs2_dispose_glock_lru.patch gfs2-remove-and-replace-gfs2_glock_queue_work.patch f2fs-fix-fiemap-failure-issue-when-page-size-is-16kb.patch -xhci-dbc-fix-stall-transfer-event-handling.patch diff --git a/queue-6.6/xhci-dbc-fix-stall-transfer-event-handling.patch b/queue-6.6/xhci-dbc-fix-stall-transfer-event-handling.patch deleted file mode 100644 index 5389473afb9..00000000000 --- a/queue-6.6/xhci-dbc-fix-stall-transfer-event-handling.patch +++ /dev/null @@ -1,283 +0,0 @@ -From 9044ad57b60b0556d42b6f8aa218a68865e810a4 Mon Sep 17 00:00:00 2001 -From: Mathias Nyman -Date: Thu, 5 Sep 2024 17:32:49 +0300 -Subject: xhci: dbc: Fix STALL transfer event handling -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -From: Mathias Nyman - -commit 9044ad57b60b0556d42b6f8aa218a68865e810a4 upstream. - -Don't flush all pending DbC data requests when an endpoint halts. - -An endpoint may halt and xHC DbC triggers a STALL error event if there's -an issue with a bulk data transfer. The transfer should restart once xHC -DbC receives a ClearFeature(ENDPOINT_HALT) request from the host. - -Once xHC DbC restarts it will start from the TRB pointed to by dequeue -field in the endpoint context, which might be the same TRB we got the -STALL event for. Turn the TRB to a no-op in this case to make sure xHC -DbC doesn't reuse and tries to retransmit this same TRB after we already -handled it, and gave its corresponding data request back. - -Other STALL events might be completely bogus. -Lukasz Bartosik discovered that xHC DbC might issue spurious STALL events -if hosts sends a ClearFeature(ENDPOINT_HALT) request to non-halted -endpoints even without any active bulk transfers. - -Assume STALL event is spurious if it reports 0 bytes transferred, and -the endpoint stopped on the STALLED TRB. -Don't give back the data request corresponding to the TRB in this case. - -The halted status is per endpoint. Track it with a per endpoint flag -instead of the driver invented DbC wide DS_STALLED state. -DbC remains in DbC-Configured state even if endpoints halt. There is no -Stalled state in the DbC Port state Machine (xhci section 7.6.6) - -Reported-by: Łukasz Bartosik -Closes: https://lore.kernel.org/linux-usb/20240725074857.623299-1-ukaszb@chromium.org/ -Tested-by: Łukasz Bartosik -Signed-off-by: Mathias Nyman -Link: https://lore.kernel.org/r/20240905143300.1959279-2-mathias.nyman@linux.intel.com -Signed-off-by: Greg Kroah-Hartman ---- - drivers/usb/host/xhci-dbgcap.c | 132 +++++++++++++++++++++++++---------------- - drivers/usb/host/xhci-dbgcap.h | 2 - 2 files changed, 83 insertions(+), 51 deletions(-) - ---- a/drivers/usb/host/xhci-dbgcap.c -+++ b/drivers/usb/host/xhci-dbgcap.c -@@ -158,16 +158,18 @@ static void xhci_dbc_giveback(struct dbc - spin_lock(&dbc->lock); - } - --static void xhci_dbc_flush_single_request(struct dbc_request *req) -+static void trb_to_noop(union xhci_trb *trb) - { -- union xhci_trb *trb = req->trb; -- - trb->generic.field[0] = 0; - trb->generic.field[1] = 0; - trb->generic.field[2] = 0; - trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE); - trb->generic.field[3] |= cpu_to_le32(TRB_TYPE(TRB_TR_NOOP)); -+} - -+static void xhci_dbc_flush_single_request(struct dbc_request *req) -+{ -+ trb_to_noop(req->trb); - xhci_dbc_giveback(req, -ESHUTDOWN); - } - -@@ -637,7 +639,6 @@ static void xhci_dbc_stop(struct xhci_db - case DS_DISABLED: - return; - case DS_CONFIGURED: -- case DS_STALLED: - if (dbc->driver->disconnect) - dbc->driver->disconnect(dbc); - break; -@@ -658,6 +659,23 @@ static void xhci_dbc_stop(struct xhci_db - } - - static void -+handle_ep_halt_changes(struct xhci_dbc *dbc, struct dbc_ep *dep, bool halted) -+{ -+ if (halted) { -+ dev_info(dbc->dev, "DbC Endpoint halted\n"); -+ dep->halted = 1; -+ -+ } else if (dep->halted) { -+ dev_info(dbc->dev, "DbC Endpoint halt cleared\n"); -+ dep->halted = 0; -+ -+ if (!list_empty(&dep->list_pending)) -+ writel(DBC_DOOR_BELL_TARGET(dep->direction), -+ &dbc->regs->doorbell); -+ } -+} -+ -+static void - dbc_handle_port_status(struct xhci_dbc *dbc, union xhci_trb *event) - { - u32 portsc; -@@ -685,6 +703,7 @@ static void dbc_handle_xfer_event(struct - struct xhci_ring *ring; - int ep_id; - int status; -+ struct xhci_ep_ctx *ep_ctx; - u32 comp_code; - size_t remain_length; - struct dbc_request *req = NULL, *r; -@@ -694,8 +713,30 @@ static void dbc_handle_xfer_event(struct - ep_id = TRB_TO_EP_ID(le32_to_cpu(event->generic.field[3])); - dep = (ep_id == EPID_OUT) ? - get_out_ep(dbc) : get_in_ep(dbc); -+ ep_ctx = (ep_id == EPID_OUT) ? -+ dbc_bulkout_ctx(dbc) : dbc_bulkin_ctx(dbc); - ring = dep->ring; - -+ /* Match the pending request: */ -+ list_for_each_entry(r, &dep->list_pending, list_pending) { -+ if (r->trb_dma == event->trans_event.buffer) { -+ req = r; -+ break; -+ } -+ if (r->status == -COMP_STALL_ERROR) { -+ dev_warn(dbc->dev, "Give back stale stalled req\n"); -+ ring->num_trbs_free++; -+ xhci_dbc_giveback(r, 0); -+ } -+ } -+ -+ if (!req) { -+ dev_warn(dbc->dev, "no matched request\n"); -+ return; -+ } -+ -+ trace_xhci_dbc_handle_transfer(ring, &req->trb->generic); -+ - switch (comp_code) { - case COMP_SUCCESS: - remain_length = 0; -@@ -706,31 +747,49 @@ static void dbc_handle_xfer_event(struct - case COMP_TRB_ERROR: - case COMP_BABBLE_DETECTED_ERROR: - case COMP_USB_TRANSACTION_ERROR: -- case COMP_STALL_ERROR: - dev_warn(dbc->dev, "tx error %d detected\n", comp_code); - status = -comp_code; - break; -+ case COMP_STALL_ERROR: -+ dev_warn(dbc->dev, "Stall error at bulk TRB %llx, remaining %zu, ep deq %llx\n", -+ event->trans_event.buffer, remain_length, ep_ctx->deq); -+ status = 0; -+ dep->halted = 1; -+ -+ /* -+ * xHC DbC may trigger a STALL bulk xfer event when host sends a -+ * ClearFeature(ENDPOINT_HALT) request even if there wasn't an -+ * active bulk transfer. -+ * -+ * Don't give back this transfer request as hardware will later -+ * start processing TRBs starting from this 'STALLED' TRB, -+ * causing TRBs and requests to be out of sync. -+ * -+ * If STALL event shows some bytes were transferred then assume -+ * it's an actual transfer issue and give back the request. -+ * In this case mark the TRB as No-Op to avoid hw from using the -+ * TRB again. -+ */ -+ -+ if ((ep_ctx->deq & ~TRB_CYCLE) == event->trans_event.buffer) { -+ dev_dbg(dbc->dev, "Ep stopped on Stalled TRB\n"); -+ if (remain_length == req->length) { -+ dev_dbg(dbc->dev, "Spurious stall event, keep req\n"); -+ req->status = -COMP_STALL_ERROR; -+ req->actual = 0; -+ return; -+ } -+ dev_dbg(dbc->dev, "Give back stalled req, but turn TRB to No-op\n"); -+ trb_to_noop(req->trb); -+ } -+ break; -+ - default: - dev_err(dbc->dev, "unknown tx error %d\n", comp_code); - status = -comp_code; - break; - } - -- /* Match the pending request: */ -- list_for_each_entry(r, &dep->list_pending, list_pending) { -- if (r->trb_dma == event->trans_event.buffer) { -- req = r; -- break; -- } -- } -- -- if (!req) { -- dev_warn(dbc->dev, "no matched request\n"); -- return; -- } -- -- trace_xhci_dbc_handle_transfer(ring, &req->trb->generic); -- - ring->num_trbs_free++; - req->actual = req->length - remain_length; - xhci_dbc_giveback(req, status); -@@ -750,7 +809,6 @@ static void inc_evt_deq(struct xhci_ring - static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) - { - dma_addr_t deq; -- struct dbc_ep *dep; - union xhci_trb *evt; - u32 ctrl, portsc; - bool update_erdp = false; -@@ -802,43 +860,17 @@ static enum evtreturn xhci_dbc_do_handle - return EVT_DISC; - } - -- /* Handle endpoint stall event: */ -+ /* Check and handle changes in endpoint halt status */ - ctrl = readl(&dbc->regs->control); -- if ((ctrl & DBC_CTRL_HALT_IN_TR) || -- (ctrl & DBC_CTRL_HALT_OUT_TR)) { -- dev_info(dbc->dev, "DbC Endpoint stall\n"); -- dbc->state = DS_STALLED; -- -- if (ctrl & DBC_CTRL_HALT_IN_TR) { -- dep = get_in_ep(dbc); -- xhci_dbc_flush_endpoint_requests(dep); -- } -- -- if (ctrl & DBC_CTRL_HALT_OUT_TR) { -- dep = get_out_ep(dbc); -- xhci_dbc_flush_endpoint_requests(dep); -- } -- -- return EVT_DONE; -- } -+ handle_ep_halt_changes(dbc, get_in_ep(dbc), ctrl & DBC_CTRL_HALT_IN_TR); -+ handle_ep_halt_changes(dbc, get_out_ep(dbc), ctrl & DBC_CTRL_HALT_OUT_TR); - - /* Clear DbC run change bit: */ - if (ctrl & DBC_CTRL_DBC_RUN_CHANGE) { - writel(ctrl, &dbc->regs->control); - ctrl = readl(&dbc->regs->control); - } -- - break; -- case DS_STALLED: -- ctrl = readl(&dbc->regs->control); -- if (!(ctrl & DBC_CTRL_HALT_IN_TR) && -- !(ctrl & DBC_CTRL_HALT_OUT_TR) && -- (ctrl & DBC_CTRL_DBC_RUN)) { -- dbc->state = DS_CONFIGURED; -- break; -- } -- -- return EVT_DONE; - default: - dev_err(dbc->dev, "Unknown DbC state %d\n", dbc->state); - break; ---- a/drivers/usb/host/xhci-dbgcap.h -+++ b/drivers/usb/host/xhci-dbgcap.h -@@ -81,7 +81,6 @@ enum dbc_state { - DS_ENABLED, - DS_CONNECTED, - DS_CONFIGURED, -- DS_STALLED, - }; - - struct dbc_ep { -@@ -89,6 +88,7 @@ struct dbc_ep { - struct list_head list_pending; - struct xhci_ring *ring; - unsigned int direction:1; -+ unsigned int halted:1; - }; - - #define DBC_QUEUE_SIZE 16 -- 2.47.3