mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Michal Pecio <michal.pecio@gmail.com>
To: Dane Linssen <linssendane@gmail.com>
Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org,
	Mathias Nyman <mathias.nyman@intel.com>,
	Alan Stern <stern@rowland.harvard.edu>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Andrew Lunn <andrew+netdev@lunn.ch>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	linux-kernel@vger.kernel.org, Hayes Wang <hayeswang@realtek.com>,
	Chih Kai Hsu <hsu.chih.kai@realtek.com>,
	nic_swsd@realtek.com
Subject: Re: r8152: RX stops until rebind after -EPROTO on the bulk-in endpoint
Date: Mon, 2 Nov 2026 13:51:25 +0100	[thread overview]
Message-ID: <20261102135125.121f8de9.michal.pecio@gmail.com> (raw)
In-Reply-To: <CAM6_QD9NDbVESP5peiNhfU5B_7UmvKVLqNz_85A_GABwDhabiw@mail.gmail.com>

[Adding another Realtek contact I found in r8152.c]

Hi,

I found a way to artificially produce something similar, though not
mid-operation, so there is no partly completed transfer in flight.

This patch works for the simplified case, you could try if it helps
with your issues too.

It adds usb_clear_halt() and logs its return status just in case.

The commented code is my artificial trigger. To test:

  ifconfig up
  # receive a few packets
  ifconfig down
  ethtool
  ifconfig up
  # receive another packet
  # dmesg shows "transfer errors" and "usb_clear_halt(pipe_in): 0"

The rest is xHCI changes to delay execution of URBs queued in advance
until the pipe is cleared. This keeps them from failing and may actually
be necessary under heavy RX, because a concurrently processed URB could
cause usb_clear_halt() to leave the pipe desynchronized again.

In principle drivers should unlink URBs before calling that, but xHCI
is tolerant in this case. And HCDs aren't really supposed to continue
URB execution after a halt, so that was arguably a bug anyway.

The xHCI part is written a bit "oddly" to avoid conflicts with changes
between 7.2 and 7.3 (EP_DROP_PENDING).

Regards,
Michal

---
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index f61686433031..e59af0e2ca1d 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -7044,9 +7044,15 @@ static void rtl_work_func_t(struct work_struct *work)
 	    netif_carrier_ok(tp->netdev))
 		tasklet_schedule(&tp->tx_tl);
 
-	if (test_and_clear_bit(RX_EPROTO, &tp->flags) &&
-	    !list_empty(&tp->rx_done))
-		napi_schedule(&tp->napi);
+	if (test_and_clear_bit(RX_EPROTO, &tp->flags)) {
+		/* On USB3 the pipe won't work until we clear halt */
+		if (tp->udev->speed >= USB_SPEED_SUPER)
+			dev_info(&tp->intf->dev, "usb_clear_halt(pipe_in): %d\n",
+					usb_clear_halt(tp->udev, tp->pipe_in));
+
+		if (!list_empty(&tp->rx_done))
+			napi_schedule(&tp->napi);
+	}
 
 	mutex_unlock(&tp->control);
 
@@ -8935,6 +8941,9 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,
 
 	mutex_lock(&tp->control);
 
+	//dev_err(&tp->intf->dev, "breaking RX\n");
+	//usb_reset_endpoint(tp->udev, 0x81);
+
 	mii_ethtool_get_link_ksettings(&tp->mii, cmd);
 
 	linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b634f1089bb1..25910c40ee74 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -556,6 +556,8 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
 	struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
 	unsigned int ep_state = ep->ep_state;
 
+	if (ep_state & EP_WAIT_CLEAR)
+		return;
 	/* Don't ring the doorbell for this endpoint if there are pending
 	 * cancellations because we don't want to interrupt processing.
 	 * We don't want to restart any stream rings if there's a set dequeue
@@ -2563,8 +2567,15 @@ static void process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
 	case COMP_USB_TRANSACTION_ERROR:
 		if (xhci->quirks & XHCI_NO_SOFT_RETRY ||
 		    (ep->err_count++ > MAX_SOFT_RETRY) ||
-		    le32_to_cpu(slot_ctx->tt_info) & TT_SLOT)
+		    le32_to_cpu(slot_ctx->tt_info) & TT_SLOT) {
+			/* halted endpoint */
+			if (td->urb->dev->speed >= USB_SPEED_SUPER) {
+				dev_info(&td->urb->dev->dev, "waiting for ep 0x%X clear halt\n",
+						td->urb->ep->desc.bEndpointAddress);
+				ep->ep_state |= EP_WAIT_CLEAR;
+			}
 			break;
+		}
 
 		td->status = 0;
 
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 6d997e07cb84..277911ebf65c 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1855,6 +1855,8 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 		xhci_dbg(xhci, "Invalidating TDs instantly on slot %d ep %d in state 0x%x\n",
 				urb->dev->slot_id, ep_index, ep->ep_state);
 		xhci_process_cancelled_tds(xhci, ep);
+	} else if (ep->ep_state & EP_WAIT_CLEAR) {
+		xhci_process_cancelled_tds(xhci, ep);
 	} else {
 		/* Otherwise, queue a new Stop Endpoint command */
 		command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
@@ -3403,7 +3405,7 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
 	/* Bail out if toggle is already being cleared by a endpoint reset */
 	spin_lock_irqsave(&xhci->lock, flags);
 	if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) {
-		ep->ep_state &= ~EP_HARD_CLEAR_TOGGLE;
+		ep->ep_state &= ~(EP_HARD_CLEAR_TOGGLE | EP_WAIT_CLEAR);
 		spin_unlock_irqrestore(&xhci->lock, flags);
 		return;
 	}
@@ -3495,7 +3497,7 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
 	xhci_free_command(xhci, stop_cmd);
 	spin_lock_irqsave(&xhci->lock, flags);
 	if (ep->ep_state & EP_SOFT_CLEAR_TOGGLE)
-		ep->ep_state &= ~EP_SOFT_CLEAR_TOGGLE;
+		ep->ep_state &= ~(EP_SOFT_CLEAR_TOGGLE | EP_WAIT_CLEAR);
 	spin_unlock_irqrestore(&xhci->lock, flags);
 }
 
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 379374a67c64..34ace464e155 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -670,6 +670,7 @@ struct xhci_virt_ep {
 	struct xhci_ring		*new_ring;
 	unsigned int			err_count;
 	unsigned int			ep_state;
+#define EP_WAIT_CLEAR		BIT(12)
 #define SET_DEQ_PENDING		BIT(0)
 #define EP_HALTED		BIT(1)	/* For stall handling */
 #define EP_STOP_CMD_PENDING	BIT(2)	/* For URB cancellation */


  reply	other threads:[~2026-11-02 12:51 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CAM6_QD_PoTdwdM7DvzzgHRs-G5EvQu-c5oNGve=GuKV4wFYAvQ@mail.gmail.com>
2026-09-27 22:01 ` Dane Linssen
2026-09-28 10:03   ` Michal Pecio
2026-09-28 12:48     ` Dane Linssen
2026-10-02  8:43       ` Michal Pecio
2026-10-09 12:23         ` Dane Linssen
2026-10-13 21:25           ` Michal Pecio
2026-10-28 21:15             ` Dane Linssen
2026-11-02 12:51               ` Michal Pecio [this message]
2026-11-02 16:18                 ` Dane Linssen
2026-09-28  1:33 ` Andrew Lunn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261102135125.121f8de9.michal.pecio@gmail.com \
    --to=michal.pecio@gmail.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=hayeswang@realtek.com \
    --cc=hsu.chih.kai@realtek.com \
    --cc=kuba@kernel.org \
    --cc=linssendane@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=mathias.nyman@intel.com \
    --cc=netdev@vger.kernel.org \
    --cc=nic_swsd@realtek.com \
    --cc=pabeni@redhat.com \
    --cc=stern@rowland.harvard.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®