Re: [PATCH v2 2/4] usb: xhci: Honor PORTSC.TM if valid

Mathias Nyman <[email protected]> Fri, 31 Jul 2026 13:51:34 +0300
Newsgroups org.kernel.vger.linux-usb,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On 7/15/26 15:29, Konrad Dybcio wrote:
> From: Konrad Dybcio <[email protected]>
> 
> Currently, the only way for the USB core to determine whether the link
> is native or tunneled is via an Intel vendor-specific Extended
> Capability.
> 
> The XHCI specification v1.2 and newer expose a common ext_cap,
> indicating whether BIT(2) of PORTSC can be interpreted as the tunneling
> status.
> 
> Make use of that and fall back to the existing Intel-specific path if
> the ext_cap is absent.
> 
> Signed-off-by: Konrad Dybcio <[email protected]>
> ---
>   drivers/usb/host/xhci-ext-caps.h |  3 +++
>   drivers/usb/host/xhci-hub.c      | 19 ++++++++++++++++---
>   drivers/usb/host/xhci-port.h     |  3 ++-
>   3 files changed, 21 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h
> index 22e53a750e2a..af7d624cd38e 100644
> --- a/drivers/usb/host/xhci-ext-caps.h
> +++ b/drivers/usb/host/xhci-ext-caps.h
> @@ -66,6 +66,9 @@
>   #define XHCI_HLC               (1 << 19)
>   #define XHCI_BLC               (1 << 20)
>   
> +/* USB3 tunneling support capability - section 7.11 */
> +#define XHCI_USB3_TUNNELING_SUPPORTED	BIT(16)
> +
>   /* Intel SPR shadow capability */
>   #define XHCI_INTEL_SPR_ESS_PORT_OFFSET  0x8ac4	/* SuperSpeed port control */
>   #define XHCI_INTEL_SPR_TUNEN	BIT(4)		/* Tunnel mode enabled */
> diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
> index b0264bd8577a..402e98ab95ee 100644
> --- a/drivers/usb/host/xhci-hub.c
> +++ b/drivers/usb/host/xhci-hub.c
> @@ -766,17 +766,30 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
>   enum usb_link_tunnel_mode xhci_port_is_tunneled(struct xhci_hcd *xhci,
>   						struct xhci_port *port)
>   {
> +	void __iomem *base = &xhci->cap_regs->hc_capbase;
>   	struct usb_hcd *hcd;
> -	void __iomem *base;
>   	u32 offset;
> +	u32 val;
>   
> -	/* Don't try and probe this capability for non-Intel hosts */
> +	/* Prefer the XHCI v1.2 ext_cap if advertised */
> +	offset = xhci_find_next_ext_cap(base, 0, XHCI_EXT_CAPS_USB3_TUNNELING);
> +	if (offset) {
> +		if (!(readl(base + offset) & XHCI_USB3_TUNNELING_SUPPORTED))
> +			return USB_LINK_NATIVE;
> +

The extcap 18 value won't change.
We can read it once in xhci_gen_setup()/xhci_setup_port_arrays() and cache it.

here we would just check:

if  (xhci->portsc_tunnel_reporting) {
	..read portsc and return, as you do below


> +		val = xhci_portsc_readl(port);
> +		if (val & PORT_TM)
> +			return USB_LINK_TUNNELED;
> +
> +		return USB_LINK_NATIVE;
> +	}
> +

Thanks
Mathias