From 138825e93dbf389e9a336e128051d3f4e4a76d58 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 3 Dec 2024 09:23:55 +0100 Subject: [PATCH] 6.1-stable patches added patches: usb-xhci-fix-td-invalidation-under-pending-set-tr-dequeue.patch --- queue-6.1/series | 2 +- ...idation-under-pending-set-tr-dequeue.patch | 102 ++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 queue-6.1/usb-xhci-fix-td-invalidation-under-pending-set-tr-dequeue.patch diff --git a/queue-6.1/series b/queue-6.1/series index b911033e2b0..a73ec07170b 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -390,5 +390,5 @@ locking-lockdep-avoid-creating-new-name-string-literals-in-lockdep_set_subclass. pinctrl-qcom-spmi-fix-debugfs-drive-strength.patch dt-bindings-iio-dac-ad3552r-fix-maximum-spi-speed.patch exfat-fix-uninit-value-in-__exfat_get_dentry_set.patch -xhci-don-t-perform-soft-retry-for-etron-xhci-host.patch bluetooth-fix-type-of-len-in-rfcomm_sock_getsockopt-_old.patch +usb-xhci-fix-td-invalidation-under-pending-set-tr-dequeue.patch diff --git a/queue-6.1/usb-xhci-fix-td-invalidation-under-pending-set-tr-dequeue.patch b/queue-6.1/usb-xhci-fix-td-invalidation-under-pending-set-tr-dequeue.patch new file mode 100644 index 00000000000..dc454dee60a --- /dev/null +++ b/queue-6.1/usb-xhci-fix-td-invalidation-under-pending-set-tr-dequeue.patch @@ -0,0 +1,102 @@ +From 484c3bab2d5dfa13ff659a51a06e9a393141eefc Mon Sep 17 00:00:00 2001 +From: Michal Pecio +Date: Wed, 6 Nov 2024 12:14:58 +0200 +Subject: usb: xhci: Fix TD invalidation under pending Set TR Dequeue + +From: Michal Pecio + +commit 484c3bab2d5dfa13ff659a51a06e9a393141eefc upstream. + +xhci_invalidate_cancelled_tds() may not work correctly if the hardware +is modifying endpoint or stream contexts at the same time by executing +a Set TR Dequeue command. And even if it worked, it would be unable to +queue Set TR Dequeue for the next stream, failing to clear xHC cache. + +On stream endpoints, a chain of Set TR Dequeue commands may take some +time to execute and we may want to cancel more TDs during this time. +Currently this leads to Stop Endpoint completion handler calling this +function without testing for SET_DEQ_PENDING, which will trigger the +aforementioned problems when it happens. + +On all endpoints, a halt condition causes Reset Endpoint to be queued +and an error status given to the class driver, which may unlink more +URBs in response. Stop Endpoint is queued and its handler may execute +concurrently with Set TR Dequeue queued by Reset Endpoint handler. + +(Reset Endpoint handler calls this function too, but there seems to +be no possibility of it running concurrently with Set TR Dequeue). + +Fix xhci_invalidate_cancelled_tds() to work correctly under a pending +Set TR Dequeue. Bail out of the function when SET_DEQ_PENDING is set, +then make the completion handler call the function again and also call +xhci_giveback_invalidated_tds(), which needs to be called next. + +This seems to fix another potential bug, where the handler would call +xhci_invalidate_cancelled_tds(), which may clear some deferred TDs if +a sanity check fails, and the TDs wouldn't be given back promptly. + +Said sanity check seems to be wrong and prone to false positives when +the endpoint halts, but fixing it is beyond the scope of this change, +besides ensuring that cleared TDs are given back properly. + +Fixes: 5ceac4402f5d ("xhci: Handle TD clearing for multiple streams case") +CC: stable@vger.kernel.org +Signed-off-by: Michal Pecio +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20241106101459.775897-33-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci-ring.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -954,6 +954,13 @@ static int xhci_invalidate_cancelled_tds + unsigned int slot_id = ep->vdev->slot_id; + int err; + ++ /* ++ * This is not going to work if the hardware is changing its dequeue ++ * pointers as we look at them. Completion handler will call us later. ++ */ ++ if (ep->ep_state & SET_DEQ_PENDING) ++ return 0; ++ + xhci = ep->xhci; + + list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) { +@@ -1324,7 +1331,6 @@ static void xhci_handle_cmd_set_deq(stru + struct xhci_ep_ctx *ep_ctx; + struct xhci_slot_ctx *slot_ctx; + struct xhci_td *td, *tmp_td; +- bool deferred = false; + + ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3])); + stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2])); +@@ -1425,8 +1431,6 @@ static void xhci_handle_cmd_set_deq(stru + xhci_dbg(ep->xhci, "%s: Giveback cancelled URB %p TD\n", + __func__, td->urb); + xhci_td_cleanup(ep->xhci, td, ep_ring, td->status); +- } else if (td->cancel_status == TD_CLEARING_CACHE_DEFERRED) { +- deferred = true; + } else { + xhci_dbg(ep->xhci, "%s: Keep cancelled URB %p TD as cancel_status is %d\n", + __func__, td->urb, td->cancel_status); +@@ -1437,11 +1441,15 @@ cleanup: + ep->queued_deq_seg = NULL; + ep->queued_deq_ptr = NULL; + +- if (deferred) { +- /* We have more streams to clear */ ++ /* Check for deferred or newly cancelled TDs */ ++ if (!list_empty(&ep->cancelled_td_list)) { + xhci_dbg(ep->xhci, "%s: Pending TDs to clear, continuing with invalidation\n", + __func__); + xhci_invalidate_cancelled_tds(ep); ++ /* Try to restart the endpoint if all is done */ ++ ring_doorbell_for_active_rings(xhci, slot_id, ep_index); ++ /* Start giving back any TDs invalidated above */ ++ xhci_giveback_invalidated_tds(ep); + } else { + /* Restart any rings with pending URBs */ + xhci_dbg(ep->xhci, "%s: All TDs cleared, ring doorbell\n", __func__); -- 2.47.3