[PATCH 18/19] usb: isp1760: wait for the TT clear in endpoint_disable
From: Greg Kroah-Hartman
Date: Tue Oct 27 2026 - 11:08:14 EST
From: Josef Bacik <josef@xxxxxxxxxxxxxx>
The driver sets qh->tt_buffer_dirty and calls usb_hub_clear_tt_buffer()
when a transfer to a full or low speed device fails or is unlinked while
it is running. The hub driver stores urb->ep in its list and
hub_tt_work() hands it back to isp1760_clear_tt_buffer_complete() after
the CLEAR_TT_BUFFER request to the hub.
Nothing keeps the endpoint until then. isp1760_endpoint_disable() frees
the QH at once. If the device is unplugged, the unlink of a running URB
queues such a request, and usb_disconnect() goes on to free the
usb_device and its configurations, which hold the struct
usb_host_endpoint. The callback then reads ep->hcpriv from freed memory
and, if it is not NULL, writes to whatever it points to. A change of the
configuration or altsetting only frees the QH, under a callback which
has loaded ep->hcpriv without the lock.
The HCD has to wait, like ehci_endpoint_disable(),
xhci_endpoint_disable() and fotg210_endpoint_disable() do. hub_tt_work()
calls the callback for every entry, also if the request failed, and
hub_quiesce() flushes the work, so the wait ends.
Fixes: 74ad60292bf0 ("usb/isp1760: Clear TT buffer on interrupted low & full speed transfers")
Cc: stable <stable@xxxxxxxxxx>
Cc: Rui Miguel Silva <rui.silva@xxxxxxxxxx>
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
drivers/usb/isp1760/isp1760-hcd.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/usb/isp1760/isp1760-hcd.c b/drivers/usb/isp1760/isp1760-hcd.c
index 6c52c6f59d69..3cbf5fe3ed34 100644
--- a/drivers/usb/isp1760/isp1760-hcd.c
+++ b/drivers/usb/isp1760/isp1760-hcd.c
@@ -2071,12 +2071,23 @@ static void isp1760_endpoint_disable(struct usb_hcd *hcd,
struct isp1760_qh *qh, *qh_iter;
int i;
+rescan:
spin_lock_irqsave(&priv->lock, spinflags);
qh = ep->hcpriv;
if (!qh)
goto out;
+ /*
+ * The hub driver still has a pointer to the endpoint. Wait until it
+ * has called isp1760_clear_tt_buffer_complete().
+ */
+ if (qh->tt_buffer_dirty) {
+ spin_unlock_irqrestore(&priv->lock, spinflags);
+ schedule_timeout_uninterruptible(1);
+ goto rescan;
+ }
+
WARN_ON(!list_empty(&qh->qtd_list));
for (i = 0; i < QH_END; i++)
--
2.56.0