The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 0/2] DWC3 link tunneling state reporting
@ 2026-05-05  8:55 Konrad Dybcio
  2026-05-05  8:55 ` [PATCH 1/2] usb: host: xhci: Allow non-Intel usb_link_tunnel_mode reporting Konrad Dybcio
  2026-05-05  8:55 ` [PATCH 2/2] usb: dwc3: Notify XHCI core of tunneled status Konrad Dybcio
  0 siblings, 2 replies; 16+ messages in thread
From: Konrad Dybcio @ 2026-05-05  8:55 UTC (permalink / raw)
  To: Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman
  Cc: linux-usb, linux-kernel, usb4-upstream, Raghavendra Thoorpu,
	Mika Westerberg, Konrad Dybcio

Currently, retrieving the tunneled/native state of a running port is
only possible on Intel XHCI hosts. This series extends that to CIO-
capable DWC31 controllers (see [1]).

Note that this patchset only results in the correct udev->tunnel_mode
value being assigned. Creating the device links (which requires this
information) between the USB4 router and the USB3 controller does not
currently take place on DT-based platforms, but that will be amended
in a follow-up patchset.

Tested on a Qualcomm X1E80100 CRD board, with a (currently) out-of-tree
set of drivers.

[1] I'm not entirely sure about the DWC version range (particularly
    wrt DWC32 and newer), so I limited it to a reasonable subset. I'll
    happily amend that.

Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
Konrad Dybcio (2):
      usb: host: xhci: Allow non-Intel usb_link_tunnel_mode reporting
      usb: dwc3: Notify XHCI core of tunneled status

 drivers/usb/dwc3/core.c      | 12 ++++++++++++
 drivers/usb/dwc3/core.h      | 18 ++++++++++++++++++
 drivers/usb/dwc3/host.c      | 12 ++++++++++++
 drivers/usb/host/xhci-hub.c  |  4 ++--
 drivers/usb/host/xhci-plat.c |  2 ++
 drivers/usb/host/xhci-plat.h |  1 +
 drivers/usb/host/xhci.c      |  6 +++++-
 drivers/usb/host/xhci.h      |  5 ++++-
 8 files changed, 56 insertions(+), 4 deletions(-)
---
base-commit: b9303e6bff706758c167af686b5315ad00233bf8
change-id: 20260504-topic-dwc3_tunneling_state-50588c0e1ae3

Best regards,
--  
Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/2] usb: host: xhci: Allow non-Intel usb_link_tunnel_mode reporting
  2026-05-05  8:55 [PATCH 0/2] DWC3 link tunneling state reporting Konrad Dybcio
@ 2026-05-05  8:55 ` Konrad Dybcio
  2026-05-05 12:14   ` Mika Westerberg
  2026-05-05  8:55 ` [PATCH 2/2] usb: dwc3: Notify XHCI core of tunneled status Konrad Dybcio
  1 sibling, 1 reply; 16+ messages in thread
From: Konrad Dybcio @ 2026-05-05  8:55 UTC (permalink / raw)
  To: Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman
  Cc: linux-usb, linux-kernel, usb4-upstream, Raghavendra Thoorpu,
	Mika Westerberg, Konrad Dybcio

From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>

The Thunderbolt framework relies on the USB core to create device links
for tunneled ports, so that the USB3 controller is only kept
runtime-resumed for the duration of the tunneling.

Currently, retrieving that information is only possibe on Intel XHCI
hosts, through a vendor-specific capability. Extend xhci-plat to allow
plumbing a custom one.

Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
 drivers/usb/host/xhci-hub.c  | 4 ++--
 drivers/usb/host/xhci-plat.c | 2 ++
 drivers/usb/host/xhci-plat.h | 1 +
 drivers/usb/host/xhci.c      | 6 +++++-
 drivers/usb/host/xhci.h      | 5 ++++-
 5 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index bacd0ddd0d09..09e5da912066 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -750,7 +750,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
 }
 
 /**
- * xhci_port_is_tunneled() - Check if USB3 connection is tunneled over USB4
+ * xhci_port_tunnel_mode() - Check if USB3 connection is tunneled over USB4
  * @xhci: xhci host controller
  * @port: USB3 port to be checked.
  *
@@ -764,7 +764,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
  * detecting USB3 over USB4 tunnels. USB_LINK_NATIVE or USB_LINK_TUNNELED
  * otherwise.
  */
-enum usb_link_tunnel_mode xhci_port_is_tunneled(struct xhci_hcd *xhci,
+enum usb_link_tunnel_mode xhci_port_tunnel_mode(struct xhci_hcd *xhci,
 						struct xhci_port *port)
 {
 	struct usb_hcd *hcd;
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 074d9c731639..dbaca694baa2 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -244,6 +244,8 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
 		priv = hcd_to_xhci_priv(hcd);
 		/* Just copy data for now */
 		*priv = *priv_match;
+
+		xhci->tunnel_mode = priv->tunnel_mode;
 	}
 
 	device_set_wakeup_capable(&pdev->dev, true);
diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h
index 00751d851831..c5042766a486 100644
--- a/drivers/usb/host/xhci-plat.h
+++ b/drivers/usb/host/xhci-plat.h
@@ -22,6 +22,7 @@ struct xhci_plat_priv {
 	int (*suspend_quirk)(struct usb_hcd *);
 	int (*resume_quirk)(struct usb_hcd *);
 	int (*post_resume_quirk)(struct usb_hcd *);
+	enum usb_link_tunnel_mode (*tunnel_mode)(struct usb_hcd *hcd, int portnum);
 };
 
 #define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index a54f5b57f205..90a6751b5c69 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4754,7 +4754,11 @@ static int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
 	if (hcd->speed >= HCD_USB3 && !udev->parent->parent) {
 		port = xhci->usb3_rhub.ports[udev->portnum - 1];
 
-		udev->tunnel_mode = xhci_port_is_tunneled(xhci, port);
+		if (xhci->tunnel_mode)
+			udev->tunnel_mode = xhci->tunnel_mode(hcd, port->hcd_portnum);
+		else
+			udev->tunnel_mode = xhci_port_tunnel_mode(xhci, port);
+
 		if (udev->tunnel_mode == USB_LINK_UNKNOWN)
 			dev_dbg(&udev->dev, "link tunnel state unknown\n");
 		else if (udev->tunnel_mode == USB_LINK_TUNNELED)
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index aeecd301f207..59cc5797d5d2 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1672,6 +1672,9 @@ struct xhci_hcd {
 	struct list_head	regset_list;
 
 	void			*dbc;
+
+	enum usb_link_tunnel_mode (*tunnel_mode)(struct usb_hcd *hcd, int portnum);
+
 	/* platform-specific data -- must come last */
 	unsigned long		priv[] __aligned(sizeof(s64));
 };
@@ -1977,7 +1980,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
 int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
 int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1);
 struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd);
-enum usb_link_tunnel_mode xhci_port_is_tunneled(struct xhci_hcd *xhci,
+enum usb_link_tunnel_mode xhci_port_tunnel_mode(struct xhci_hcd *xhci,
 						struct xhci_port *port);
 void xhci_hc_died(struct xhci_hcd *xhci);
 

-- 
2.54.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/2] usb: dwc3: Notify XHCI core of tunneled status
  2026-05-05  8:55 [PATCH 0/2] DWC3 link tunneling state reporting Konrad Dybcio
  2026-05-05  8:55 ` [PATCH 1/2] usb: host: xhci: Allow non-Intel usb_link_tunnel_mode reporting Konrad Dybcio
@ 2026-05-05  8:55 ` Konrad Dybcio
  2026-05-06 23:40   ` Thinh Nguyen
  1 sibling, 1 reply; 16+ messages in thread
From: Konrad Dybcio @ 2026-05-05  8:55 UTC (permalink / raw)
  To: Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman
  Cc: linux-usb, linux-kernel, usb4-upstream, Raghavendra Thoorpu,
	Mika Westerberg, Konrad Dybcio

From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>

The Thunderbolt framework relies on the USB core to create device links
for tunneled ports, so that the USB3 controller is only kept
runtime-resumed for the duration of the tunneling. This depends on
first knowing whether a connection is tunneled or native.

Add the logic to handle that for DWC3 controllers.

Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
 drivers/usb/dwc3/core.c | 12 ++++++++++++
 drivers/usb/dwc3/core.h | 18 ++++++++++++++++++
 drivers/usb/dwc3/host.c | 12 ++++++++++++
 3 files changed, 42 insertions(+)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 65213896de99..7cec4911e278 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -162,6 +162,18 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy)
 }
 EXPORT_SYMBOL_GPL(dwc3_set_prtcap);
 
+enum usb_link_tunnel_mode dwc3_link_tunnel_mode(struct dwc3 *dwc, u8 port)
+{
+	/* Prior versions had no CIO support */
+	if (!DWC3_VER_IS_WITHIN(DWC31, 191A, ANY))
+		return USB_LINK_NATIVE;
+
+	if (dwc3_readl(dwc, DWC3_CIOCTRL(port)) & DWC3_CIOCTRL_CIO_EN)
+		return USB_LINK_TUNNELED;
+
+	return USB_LINK_NATIVE;
+}
+
 static void __dwc3_set_mode(struct work_struct *work)
 {
 	struct dwc3 *dwc = work_to_dwc(work);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index e0dee9d28740..9594829de6c7 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -179,6 +179,11 @@
 #define DWC3_OEVTEN		0xcc0C
 #define DWC3_OSTS		0xcc10
 
+/* CIO regs */
+#define DWC3_CIO_BASE(n)	(0xcd20 + ((n) * 0x30))
+#define DWC3_CIOCTRL(n)		(DWC3_CIO_BASE(n) + 0x00)
+#define DWC3_CIOCTRL_CIO_EN	BIT(0)
+
 #define DWC3_LLUCTL(n)		(0xd024 + ((n) * 0x80))
 
 /* Bit fields */
@@ -1309,6 +1314,7 @@ struct dwc3 {
 #define DWC31_REVISION_170A	0x3137302a
 #define DWC31_REVISION_180A	0x3138302a
 #define DWC31_REVISION_190A	0x3139302a
+#define DWC31_REVISION_191A	0x3139312a
 #define DWC31_REVISION_200A	0x3230302a
 
 #define DWC32_REVISION_ANY	0x0
@@ -1653,11 +1659,23 @@ static inline void dwc3_pre_run_stop(struct dwc3 *dwc, bool is_on)
 #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
 int dwc3_host_init(struct dwc3 *dwc);
 void dwc3_host_exit(struct dwc3 *dwc);
+
+/**
+ * dwc3_link_tunnel_mode - Check whether the link is tunneled over TBT/USB4
+ * @dwc: Pointer to DWC3 controller context
+ * @port: 0-based port index
+ *
+ * Returns: USB_LINK_TUNNELED if tunneled, USB_LINK_NATIVE if not, or
+ *          when the controller does not have USB4 capabilities.
+ */
+enum usb_link_tunnel_mode dwc3_link_tunnel_mode(struct dwc3 *dwc, u8 port);
 #else
 static inline int dwc3_host_init(struct dwc3 *dwc)
 { return 0; }
 static inline void dwc3_host_exit(struct dwc3 *dwc)
 { }
+static inline enum usb_link_tunnel_mode dwc3_link_tunnel_mode(struct dwc3 *dwc, u8 port)
+{ return USB_LINK_UNKNOWN; }
 #endif
 
 #if IS_ENABLED(CONFIG_USB_DWC3_GADGET) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index 96b588bd08cd..eb03b079696e 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -77,8 +77,20 @@ static void dwc3_xhci_plat_start(struct usb_hcd *hcd)
 	dwc3_enable_susphy(dwc, true);
 }
 
+static enum usb_link_tunnel_mode dwc3_xhci_tunnel_mode(struct usb_hcd *hcd, int portnum)
+{
+	struct platform_device *pdev;
+	struct dwc3 *dwc;
+
+	pdev = to_platform_device(hcd->self.controller);
+	dwc = dev_get_drvdata(pdev->dev.parent);
+
+	return dwc3_link_tunnel_mode(dwc, portnum);
+}
+
 static const struct xhci_plat_priv dwc3_xhci_plat_quirk = {
 	.plat_start = dwc3_xhci_plat_start,
+	.tunnel_mode = dwc3_xhci_tunnel_mode,
 };
 
 static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc,

-- 
2.54.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/2] usb: host: xhci: Allow non-Intel usb_link_tunnel_mode reporting
  2026-05-05  8:55 ` [PATCH 1/2] usb: host: xhci: Allow non-Intel usb_link_tunnel_mode reporting Konrad Dybcio
@ 2026-05-05 12:14   ` Mika Westerberg
  2026-05-07 10:40     ` Konrad Dybcio
  0 siblings, 1 reply; 16+ messages in thread
From: Mika Westerberg @ 2026-05-05 12:14 UTC (permalink / raw)
  To: Konrad Dybcio
  Cc: Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman, linux-usb,
	linux-kernel, usb4-upstream, Raghavendra Thoorpu, Konrad Dybcio

Hi,

On Tue, May 05, 2026 at 10:55:04AM +0200, Konrad Dybcio wrote:
> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> 
> The Thunderbolt framework relies on the USB core to create device links
> for tunneled ports, so that the USB3 controller is only kept
> runtime-resumed for the duration of the tunneling.
> 
> Currently, retrieving that information is only possibe on Intel XHCI
> hosts, through a vendor-specific capability. Extend xhci-plat to allow
> plumbing a custom one.
> 
> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> ---
>  drivers/usb/host/xhci-hub.c  | 4 ++--
>  drivers/usb/host/xhci-plat.c | 2 ++
>  drivers/usb/host/xhci-plat.h | 1 +
>  drivers/usb/host/xhci.c      | 6 +++++-
>  drivers/usb/host/xhci.h      | 5 ++++-
>  5 files changed, 14 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
> index bacd0ddd0d09..09e5da912066 100644
> --- a/drivers/usb/host/xhci-hub.c
> +++ b/drivers/usb/host/xhci-hub.c
> @@ -750,7 +750,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
>  }
>  
>  /**
> - * xhci_port_is_tunneled() - Check if USB3 connection is tunneled over USB4
> + * xhci_port_tunnel_mode() - Check if USB3 connection is tunneled over USB4
>   * @xhci: xhci host controller
>   * @port: USB3 port to be checked.
>   *
> @@ -764,7 +764,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
>   * detecting USB3 over USB4 tunnels. USB_LINK_NATIVE or USB_LINK_TUNNELED
>   * otherwise.
>   */
> -enum usb_link_tunnel_mode xhci_port_is_tunneled(struct xhci_hcd *xhci,
> +enum usb_link_tunnel_mode xhci_port_tunnel_mode(struct xhci_hcd *xhci,
>  						struct xhci_port *port)

I'm wondering if this could be:

bool xhci_port_is_tunneled()

becase if I understand correctly that's the only information we need e.g is
it going over tunnel or not.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] usb: dwc3: Notify XHCI core of tunneled status
  2026-05-05  8:55 ` [PATCH 2/2] usb: dwc3: Notify XHCI core of tunneled status Konrad Dybcio
@ 2026-05-06 23:40   ` Thinh Nguyen
  2026-05-07 10:34     ` Konrad Dybcio
  0 siblings, 1 reply; 16+ messages in thread
From: Thinh Nguyen @ 2026-05-06 23:40 UTC (permalink / raw)
  To: Konrad Dybcio
  Cc: Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	usb4-upstream@oss.qualcomm.com, Raghavendra Thoorpu,
	Mika Westerberg, Konrad Dybcio

On Tue, May 05, 2026, Konrad Dybcio wrote:
> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> 
> The Thunderbolt framework relies on the USB core to create device links
> for tunneled ports, so that the USB3 controller is only kept
> runtime-resumed for the duration of the tunneling. This depends on
> first knowing whether a connection is tunneled or native.
> 
> Add the logic to handle that for DWC3 controllers.
> 
> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> ---
>  drivers/usb/dwc3/core.c | 12 ++++++++++++
>  drivers/usb/dwc3/core.h | 18 ++++++++++++++++++
>  drivers/usb/dwc3/host.c | 12 ++++++++++++
>  3 files changed, 42 insertions(+)
> 
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 65213896de99..7cec4911e278 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -162,6 +162,18 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy)
>  }
>  EXPORT_SYMBOL_GPL(dwc3_set_prtcap);
>  
> +enum usb_link_tunnel_mode dwc3_link_tunnel_mode(struct dwc3 *dwc, u8 port)
> +{
> +	/* Prior versions had no CIO support */
> +	if (!DWC3_VER_IS_WITHIN(DWC31, 191A, ANY))
> +		return USB_LINK_NATIVE;
> +
> +	if (dwc3_readl(dwc, DWC3_CIOCTRL(port)) & DWC3_CIOCTRL_CIO_EN)

The CIO register block only exists if DWC1_USB31_EN_CIO is set (and
DWC_USB31_EN_USB2_ONLY is not set). In most cases, this register block
will be reserved, register read of reserved block should be 0. But we
can't guarantee that it will always be the case.

> +		return USB_LINK_TUNNELED;
> +
> +	return USB_LINK_NATIVE;
> +}
> +
>  static void __dwc3_set_mode(struct work_struct *work)
>  {
>  	struct dwc3 *dwc = work_to_dwc(work);
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index e0dee9d28740..9594829de6c7 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -179,6 +179,11 @@
>  #define DWC3_OEVTEN		0xcc0C
>  #define DWC3_OSTS		0xcc10
>  
> +/* CIO regs */
> +#define DWC3_CIO_BASE(n)	(0xcd20 + ((n) * 0x30))
> +#define DWC3_CIOCTRL(n)		(DWC3_CIO_BASE(n) + 0x00)
> +#define DWC3_CIOCTRL_CIO_EN	BIT(0)
> +
>  #define DWC3_LLUCTL(n)		(0xd024 + ((n) * 0x80))
>  
>  /* Bit fields */
> @@ -1309,6 +1314,7 @@ struct dwc3 {
>  #define DWC31_REVISION_170A	0x3137302a
>  #define DWC31_REVISION_180A	0x3138302a
>  #define DWC31_REVISION_190A	0x3139302a
> +#define DWC31_REVISION_191A	0x3139312a
>  #define DWC31_REVISION_200A	0x3230302a
>  
>  #define DWC32_REVISION_ANY	0x0
> @@ -1653,11 +1659,23 @@ static inline void dwc3_pre_run_stop(struct dwc3 *dwc, bool is_on)
>  #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
>  int dwc3_host_init(struct dwc3 *dwc);
>  void dwc3_host_exit(struct dwc3 *dwc);
> +
> +/**
> + * dwc3_link_tunnel_mode - Check whether the link is tunneled over TBT/USB4
> + * @dwc: Pointer to DWC3 controller context
> + * @port: 0-based port index
> + *
> + * Returns: USB_LINK_TUNNELED if tunneled, USB_LINK_NATIVE if not, or
> + *          when the controller does not have USB4 capabilities.
> + */
> +enum usb_link_tunnel_mode dwc3_link_tunnel_mode(struct dwc3 *dwc, u8 port);
>  #else
>  static inline int dwc3_host_init(struct dwc3 *dwc)
>  { return 0; }
>  static inline void dwc3_host_exit(struct dwc3 *dwc)
>  { }
> +static inline enum usb_link_tunnel_mode dwc3_link_tunnel_mode(struct dwc3 *dwc, u8 port)
> +{ return USB_LINK_UNKNOWN; }
>  #endif
>  
>  #if IS_ENABLED(CONFIG_USB_DWC3_GADGET) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
> diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
> index 96b588bd08cd..eb03b079696e 100644
> --- a/drivers/usb/dwc3/host.c
> +++ b/drivers/usb/dwc3/host.c
> @@ -77,8 +77,20 @@ static void dwc3_xhci_plat_start(struct usb_hcd *hcd)
>  	dwc3_enable_susphy(dwc, true);
>  }
>  
> +static enum usb_link_tunnel_mode dwc3_xhci_tunnel_mode(struct usb_hcd *hcd, int portnum)
> +{
> +	struct platform_device *pdev;
> +	struct dwc3 *dwc;
> +
> +	pdev = to_platform_device(hcd->self.controller);
> +	dwc = dev_get_drvdata(pdev->dev.parent);
> +
> +	return dwc3_link_tunnel_mode(dwc, portnum);
> +}
> +
>  static const struct xhci_plat_priv dwc3_xhci_plat_quirk = {
>  	.plat_start = dwc3_xhci_plat_start,
> +	.tunnel_mode = dwc3_xhci_tunnel_mode,
>  };
>  
>  static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc,
> 
> -- 
> 2.54.0
> 

We shouldn't need to be doing this. This should be checked from the
xHCI driver. Check xHCI spec for PORTSC.TM and USB3 tunneling support
capability (section 7.11).

See xhci spec r2.0:
https://www.intel.com/content/www/us/en/content-details/868296/extensible-host-controller-interface-for-universal-serial-bus-xhci-requirements-specification-r2-0.html

BR,
Thinh

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] usb: dwc3: Notify XHCI core of tunneled status
  2026-05-06 23:40   ` Thinh Nguyen
@ 2026-05-07 10:34     ` Konrad Dybcio
  2026-05-07 17:46       ` Jack Pham
  0 siblings, 1 reply; 16+ messages in thread
From: Konrad Dybcio @ 2026-05-07 10:34 UTC (permalink / raw)
  To: Thinh Nguyen, Konrad Dybcio
  Cc: Greg Kroah-Hartman, Mathias Nyman, linux-usb@vger.kernel.org,
	linux-kernel@vger.kernel.org, usb4-upstream@oss.qualcomm.com,
	Raghavendra Thoorpu, Mika Westerberg

On 5/7/26 1:40 AM, Thinh Nguyen wrote:
> On Tue, May 05, 2026, Konrad Dybcio wrote:
>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>
>> The Thunderbolt framework relies on the USB core to create device links
>> for tunneled ports, so that the USB3 controller is only kept
>> runtime-resumed for the duration of the tunneling. This depends on
>> first knowing whether a connection is tunneled or native.
>>
>> Add the logic to handle that for DWC3 controllers.
>>
>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>> ---
>>  drivers/usb/dwc3/core.c | 12 ++++++++++++
>>  drivers/usb/dwc3/core.h | 18 ++++++++++++++++++
>>  drivers/usb/dwc3/host.c | 12 ++++++++++++
>>  3 files changed, 42 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index 65213896de99..7cec4911e278 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -162,6 +162,18 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy)
>>  }
>>  EXPORT_SYMBOL_GPL(dwc3_set_prtcap);
>>  
>> +enum usb_link_tunnel_mode dwc3_link_tunnel_mode(struct dwc3 *dwc, u8 port)
>> +{
>> +	/* Prior versions had no CIO support */
>> +	if (!DWC3_VER_IS_WITHIN(DWC31, 191A, ANY))
>> +		return USB_LINK_NATIVE;
>> +
>> +	if (dwc3_readl(dwc, DWC3_CIOCTRL(port)) & DWC3_CIOCTRL_CIO_EN)
> 
> The CIO register block only exists if DWC1_USB31_EN_CIO is set (and
> DWC_USB31_EN_USB2_ONLY is not set). In most cases, this register block
> will be reserved, register read of reserved block should be 0. But we
> can't guarantee that it will always be the case.

That's inconvenient because..

[...]

> We shouldn't need to be doing this. This should be checked from the
> xHCI driver. Check xHCI spec for PORTSC.TM and USB3 tunneling support
> capability (section 7.11).

..I'm seeing only caps 0/1/2 (and 10 on some but not all) advertised
(I ran a for-loop checking offsets 0..=255)

How should we proceed?

Konrad

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/2] usb: host: xhci: Allow non-Intel usb_link_tunnel_mode reporting
  2026-05-05 12:14   ` Mika Westerberg
@ 2026-05-07 10:40     ` Konrad Dybcio
  2026-05-07 12:48       ` Mathias Nyman
  0 siblings, 1 reply; 16+ messages in thread
From: Konrad Dybcio @ 2026-05-07 10:40 UTC (permalink / raw)
  To: Mika Westerberg, Konrad Dybcio
  Cc: Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman, linux-usb,
	linux-kernel, usb4-upstream, Raghavendra Thoorpu

On 5/5/26 2:14 PM, Mika Westerberg wrote:
> Hi,
> 
> On Tue, May 05, 2026 at 10:55:04AM +0200, Konrad Dybcio wrote:
>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>
>> The Thunderbolt framework relies on the USB core to create device links
>> for tunneled ports, so that the USB3 controller is only kept
>> runtime-resumed for the duration of the tunneling.
>>
>> Currently, retrieving that information is only possibe on Intel XHCI
>> hosts, through a vendor-specific capability. Extend xhci-plat to allow
>> plumbing a custom one.
>>
>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>> ---
>>  drivers/usb/host/xhci-hub.c  | 4 ++--
>>  drivers/usb/host/xhci-plat.c | 2 ++
>>  drivers/usb/host/xhci-plat.h | 1 +
>>  drivers/usb/host/xhci.c      | 6 +++++-
>>  drivers/usb/host/xhci.h      | 5 ++++-
>>  5 files changed, 14 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
>> index bacd0ddd0d09..09e5da912066 100644
>> --- a/drivers/usb/host/xhci-hub.c
>> +++ b/drivers/usb/host/xhci-hub.c
>> @@ -750,7 +750,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
>>  }
>>  
>>  /**
>> - * xhci_port_is_tunneled() - Check if USB3 connection is tunneled over USB4
>> + * xhci_port_tunnel_mode() - Check if USB3 connection is tunneled over USB4
>>   * @xhci: xhci host controller
>>   * @port: USB3 port to be checked.
>>   *
>> @@ -764,7 +764,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
>>   * detecting USB3 over USB4 tunnels. USB_LINK_NATIVE or USB_LINK_TUNNELED
>>   * otherwise.
>>   */
>> -enum usb_link_tunnel_mode xhci_port_is_tunneled(struct xhci_hcd *xhci,
>> +enum usb_link_tunnel_mode xhci_port_tunnel_mode(struct xhci_hcd *xhci,
>>  						struct xhci_port *port)
> 
> I'm wondering if this could be:
> 
> bool xhci_port_is_tunneled()
> 
> becase if I understand correctly that's the only information we need e.g is
> it going over tunnel or not.

It was originally introduced as a tristate enum in:

f46a6e165197 ("usb: Add tunnel_mode parameter to usb device structure")

but the usefulness of USB_LINK_UNKNOWN is limited to a dev_dbg() print..
I don't really have strong opinions either way

Konrad

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/2] usb: host: xhci: Allow non-Intel usb_link_tunnel_mode reporting
  2026-05-07 10:40     ` Konrad Dybcio
@ 2026-05-07 12:48       ` Mathias Nyman
  2026-05-07 12:53         ` Konrad Dybcio
  0 siblings, 1 reply; 16+ messages in thread
From: Mathias Nyman @ 2026-05-07 12:48 UTC (permalink / raw)
  To: Konrad Dybcio, Mika Westerberg, Konrad Dybcio
  Cc: Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman, linux-usb,
	linux-kernel, usb4-upstream, Raghavendra Thoorpu

On 5/7/26 13:40, Konrad Dybcio wrote:
> On 5/5/26 2:14 PM, Mika Westerberg wrote:
>> Hi,
>>
>> On Tue, May 05, 2026 at 10:55:04AM +0200, Konrad Dybcio wrote:
>>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>
>>> The Thunderbolt framework relies on the USB core to create device links
>>> for tunneled ports, so that the USB3 controller is only kept
>>> runtime-resumed for the duration of the tunneling.
>>>
>>> Currently, retrieving that information is only possibe on Intel XHCI
>>> hosts, through a vendor-specific capability. Extend xhci-plat to allow
>>> plumbing a custom one.
>>>
>>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>> ---
>>>   drivers/usb/host/xhci-hub.c  | 4 ++--
>>>   drivers/usb/host/xhci-plat.c | 2 ++
>>>   drivers/usb/host/xhci-plat.h | 1 +
>>>   drivers/usb/host/xhci.c      | 6 +++++-
>>>   drivers/usb/host/xhci.h      | 5 ++++-
>>>   5 files changed, 14 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
>>> index bacd0ddd0d09..09e5da912066 100644
>>> --- a/drivers/usb/host/xhci-hub.c
>>> +++ b/drivers/usb/host/xhci-hub.c
>>> @@ -750,7 +750,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
>>>   }
>>>   
>>>   /**
>>> - * xhci_port_is_tunneled() - Check if USB3 connection is tunneled over USB4
>>> + * xhci_port_tunnel_mode() - Check if USB3 connection is tunneled over USB4
>>>    * @xhci: xhci host controller
>>>    * @port: USB3 port to be checked.
>>>    *
>>> @@ -764,7 +764,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
>>>    * detecting USB3 over USB4 tunnels. USB_LINK_NATIVE or USB_LINK_TUNNELED
>>>    * otherwise.
>>>    */
>>> -enum usb_link_tunnel_mode xhci_port_is_tunneled(struct xhci_hcd *xhci,
>>> +enum usb_link_tunnel_mode xhci_port_tunnel_mode(struct xhci_hcd *xhci,
>>>   						struct xhci_port *port)
>>
>> I'm wondering if this could be:
>>
>> bool xhci_port_is_tunneled()
>>
>> becase if I understand correctly that's the only information we need e.g is
>> it going over tunnel or not.
> 
> It was originally introduced as a tristate enum in:
> 
> f46a6e165197 ("usb: Add tunnel_mode parameter to usb device structure")
> 
> but the usefulness of USB_LINK_UNKNOWN is limited to a dev_dbg() print..
> I don't really have strong opinions either way
> 

Tunnel detection can be tried other ways if state is USB_LINK_UNKNOWN.

For example usb-acpi.c will try to create a tunnel if all the ACPI entries exists
that indicate a tunnel, but the current xHC doesn't support tunnel detection.

usb_acpi_find_companion_for_device(struct usb_device *udev)
{
	...

	/* Tunneled USB3 devices depend on USB4 Host Interface, set device link to it */
	if (udev->speed >= USB_SPEED_SUPER &&
		udev->tunnel_mode != USB_LINK_NATIVE)
		usb_acpi_add_usb4_devlink(udev);
}

-Mathias






^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/2] usb: host: xhci: Allow non-Intel usb_link_tunnel_mode reporting
  2026-05-07 12:48       ` Mathias Nyman
@ 2026-05-07 12:53         ` Konrad Dybcio
  2026-05-07 13:11           ` Mika Westerberg
  0 siblings, 1 reply; 16+ messages in thread
From: Konrad Dybcio @ 2026-05-07 12:53 UTC (permalink / raw)
  To: Mathias Nyman, Mika Westerberg, Konrad Dybcio
  Cc: Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman, linux-usb,
	linux-kernel, usb4-upstream, Raghavendra Thoorpu

On 5/7/26 2:48 PM, Mathias Nyman wrote:
> On 5/7/26 13:40, Konrad Dybcio wrote:
>> On 5/5/26 2:14 PM, Mika Westerberg wrote:
>>> Hi,
>>>
>>> On Tue, May 05, 2026 at 10:55:04AM +0200, Konrad Dybcio wrote:
>>>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>>
>>>> The Thunderbolt framework relies on the USB core to create device links
>>>> for tunneled ports, so that the USB3 controller is only kept
>>>> runtime-resumed for the duration of the tunneling.
>>>>
>>>> Currently, retrieving that information is only possibe on Intel XHCI
>>>> hosts, through a vendor-specific capability. Extend xhci-plat to allow
>>>> plumbing a custom one.
>>>>
>>>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>> ---
>>>>   drivers/usb/host/xhci-hub.c  | 4 ++--
>>>>   drivers/usb/host/xhci-plat.c | 2 ++
>>>>   drivers/usb/host/xhci-plat.h | 1 +
>>>>   drivers/usb/host/xhci.c      | 6 +++++-
>>>>   drivers/usb/host/xhci.h      | 5 ++++-
>>>>   5 files changed, 14 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
>>>> index bacd0ddd0d09..09e5da912066 100644
>>>> --- a/drivers/usb/host/xhci-hub.c
>>>> +++ b/drivers/usb/host/xhci-hub.c
>>>> @@ -750,7 +750,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
>>>>   }
>>>>     /**
>>>> - * xhci_port_is_tunneled() - Check if USB3 connection is tunneled over USB4
>>>> + * xhci_port_tunnel_mode() - Check if USB3 connection is tunneled over USB4
>>>>    * @xhci: xhci host controller
>>>>    * @port: USB3 port to be checked.
>>>>    *
>>>> @@ -764,7 +764,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
>>>>    * detecting USB3 over USB4 tunnels. USB_LINK_NATIVE or USB_LINK_TUNNELED
>>>>    * otherwise.
>>>>    */
>>>> -enum usb_link_tunnel_mode xhci_port_is_tunneled(struct xhci_hcd *xhci,
>>>> +enum usb_link_tunnel_mode xhci_port_tunnel_mode(struct xhci_hcd *xhci,
>>>>                           struct xhci_port *port)
>>>
>>> I'm wondering if this could be:
>>>
>>> bool xhci_port_is_tunneled()
>>>
>>> becase if I understand correctly that's the only information we need e.g is
>>> it going over tunnel or not.
>>
>> It was originally introduced as a tristate enum in:
>>
>> f46a6e165197 ("usb: Add tunnel_mode parameter to usb device structure")
>>
>> but the usefulness of USB_LINK_UNKNOWN is limited to a dev_dbg() print..
>> I don't really have strong opinions either way
>>
> 
> Tunnel detection can be tried other ways if state is USB_LINK_UNKNOWN.
> 
> For example usb-acpi.c will try to create a tunnel if all the ACPI entries exists
> that indicate a tunnel, but the current xHC doesn't support tunnel detection.

Fair, I didn't consider that!

Konrad

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/2] usb: host: xhci: Allow non-Intel usb_link_tunnel_mode reporting
  2026-05-07 12:53         ` Konrad Dybcio
@ 2026-05-07 13:11           ` Mika Westerberg
  0 siblings, 0 replies; 16+ messages in thread
From: Mika Westerberg @ 2026-05-07 13:11 UTC (permalink / raw)
  To: Konrad Dybcio
  Cc: Mathias Nyman, Konrad Dybcio, Thinh Nguyen, Greg Kroah-Hartman,
	Mathias Nyman, linux-usb, linux-kernel, usb4-upstream,
	Raghavendra Thoorpu

On Thu, May 07, 2026 at 02:53:22PM +0200, Konrad Dybcio wrote:
> On 5/7/26 2:48 PM, Mathias Nyman wrote:
> > On 5/7/26 13:40, Konrad Dybcio wrote:
> >> On 5/5/26 2:14 PM, Mika Westerberg wrote:
> >>> Hi,
> >>>
> >>> On Tue, May 05, 2026 at 10:55:04AM +0200, Konrad Dybcio wrote:
> >>>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> >>>>
> >>>> The Thunderbolt framework relies on the USB core to create device links
> >>>> for tunneled ports, so that the USB3 controller is only kept
> >>>> runtime-resumed for the duration of the tunneling.
> >>>>
> >>>> Currently, retrieving that information is only possibe on Intel XHCI
> >>>> hosts, through a vendor-specific capability. Extend xhci-plat to allow
> >>>> plumbing a custom one.
> >>>>
> >>>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> >>>> ---
> >>>>   drivers/usb/host/xhci-hub.c  | 4 ++--
> >>>>   drivers/usb/host/xhci-plat.c | 2 ++
> >>>>   drivers/usb/host/xhci-plat.h | 1 +
> >>>>   drivers/usb/host/xhci.c      | 6 +++++-
> >>>>   drivers/usb/host/xhci.h      | 5 ++++-
> >>>>   5 files changed, 14 insertions(+), 4 deletions(-)
> >>>>
> >>>> diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
> >>>> index bacd0ddd0d09..09e5da912066 100644
> >>>> --- a/drivers/usb/host/xhci-hub.c
> >>>> +++ b/drivers/usb/host/xhci-hub.c
> >>>> @@ -750,7 +750,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
> >>>>   }
> >>>>     /**
> >>>> - * xhci_port_is_tunneled() - Check if USB3 connection is tunneled over USB4
> >>>> + * xhci_port_tunnel_mode() - Check if USB3 connection is tunneled over USB4
> >>>>    * @xhci: xhci host controller
> >>>>    * @port: USB3 port to be checked.
> >>>>    *
> >>>> @@ -764,7 +764,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
> >>>>    * detecting USB3 over USB4 tunnels. USB_LINK_NATIVE or USB_LINK_TUNNELED
> >>>>    * otherwise.
> >>>>    */
> >>>> -enum usb_link_tunnel_mode xhci_port_is_tunneled(struct xhci_hcd *xhci,
> >>>> +enum usb_link_tunnel_mode xhci_port_tunnel_mode(struct xhci_hcd *xhci,
> >>>>                           struct xhci_port *port)
> >>>
> >>> I'm wondering if this could be:
> >>>
> >>> bool xhci_port_is_tunneled()
> >>>
> >>> becase if I understand correctly that's the only information we need e.g is
> >>> it going over tunnel or not.
> >>
> >> It was originally introduced as a tristate enum in:
> >>
> >> f46a6e165197 ("usb: Add tunnel_mode parameter to usb device structure")
> >>
> >> but the usefulness of USB_LINK_UNKNOWN is limited to a dev_dbg() print..
> >> I don't really have strong opinions either way
> >>
> > 
> > Tunnel detection can be tried other ways if state is USB_LINK_UNKNOWN.
> > 
> > For example usb-acpi.c will try to create a tunnel if all the ACPI entries exists
> > that indicate a tunnel, but the current xHC doesn't support tunnel detection.
> 
> Fair, I didn't consider that!

Yeah, I missed it too. Thanks Mathias for explaining.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] usb: dwc3: Notify XHCI core of tunneled status
  2026-05-07 10:34     ` Konrad Dybcio
@ 2026-05-07 17:46       ` Jack Pham
  2026-05-07 22:46         ` Thinh Nguyen
  0 siblings, 1 reply; 16+ messages in thread
From: Jack Pham @ 2026-05-07 17:46 UTC (permalink / raw)
  To: Konrad Dybcio, Thinh Nguyen
  Cc: Konrad Dybcio, Greg Kroah-Hartman, Mathias Nyman,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	usb4-upstream@oss.qualcomm.com, Raghavendra Thoorpu,
	Mika Westerberg

On Thu, May 07, 2026 at 12:34:50PM +0200, Konrad Dybcio wrote:
> On 5/7/26 1:40 AM, Thinh Nguyen wrote:
> > On Tue, May 05, 2026, Konrad Dybcio wrote:
> >> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> >>
> >> The Thunderbolt framework relies on the USB core to create device links
> >> for tunneled ports, so that the USB3 controller is only kept
> >> runtime-resumed for the duration of the tunneling. This depends on
> >> first knowing whether a connection is tunneled or native.
> >>
> >> Add the logic to handle that for DWC3 controllers.
> >>
> >> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> >> ---
> >>  drivers/usb/dwc3/core.c | 12 ++++++++++++
> >>  drivers/usb/dwc3/core.h | 18 ++++++++++++++++++
> >>  drivers/usb/dwc3/host.c | 12 ++++++++++++
> >>  3 files changed, 42 insertions(+)
> >>
> >> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> >> index 65213896de99..7cec4911e278 100644
> >> --- a/drivers/usb/dwc3/core.c
> >> +++ b/drivers/usb/dwc3/core.c
> >> @@ -162,6 +162,18 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy)
> >>  }
> >>  EXPORT_SYMBOL_GPL(dwc3_set_prtcap);
> >>  
> >> +enum usb_link_tunnel_mode dwc3_link_tunnel_mode(struct dwc3 *dwc, u8 port)
> >> +{
> >> +	/* Prior versions had no CIO support */
> >> +	if (!DWC3_VER_IS_WITHIN(DWC31, 191A, ANY))
> >> +		return USB_LINK_NATIVE;
> >> +
> >> +	if (dwc3_readl(dwc, DWC3_CIOCTRL(port)) & DWC3_CIOCTRL_CIO_EN)
> > 
> > The CIO register block only exists if DWC1_USB31_EN_CIO is set (and
> > DWC_USB31_EN_USB2_ONLY is not set). In most cases, this register block
> > will be reserved, register read of reserved block should be 0. But we
> > can't guarantee that it will always be the case.
> 
> That's inconvenient because..
> 
> [...]
> 
> > We shouldn't need to be doing this. This should be checked from the
> > xHCI driver. Check xHCI spec for PORTSC.TM and USB3 tunneling support
> > capability (section 7.11).
> 
> ..I'm seeing only caps 0/1/2 (and 10 on some but not all) advertised
> (I ran a for-loop checking offsets 0..=255)

Right.  That section in xHCI spec was only added in the 1.2b revision.
However the DWC31 IP versions that current Qualcomm USB4-capable SoCs
are using are 2.00a (and a customized version of 1.91a) which are only
compliant to xHCI 1.1 so this capability is not there, even though the
CIO register block exists.  So short of having the proper XHCI bit, this
is the next best, non-SoC specific alternative we've found that can
allow XHCI driver to identify when it is operating in tunnel mode.

Jack

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] usb: dwc3: Notify XHCI core of tunneled status
  2026-05-07 17:46       ` Jack Pham
@ 2026-05-07 22:46         ` Thinh Nguyen
  2026-05-08 12:04           ` Konrad Dybcio
  0 siblings, 1 reply; 16+ messages in thread
From: Thinh Nguyen @ 2026-05-07 22:46 UTC (permalink / raw)
  To: Konrad Dybcio, Jack Pham
  Cc: Thinh Nguyen, Konrad Dybcio, Greg Kroah-Hartman, Mathias Nyman,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	usb4-upstream@oss.qualcomm.com, Raghavendra Thoorpu,
	Mika Westerberg

On Thu, May 07, 2026, Jack Pham wrote:
> On Thu, May 07, 2026 at 12:34:50PM +0200, Konrad Dybcio wrote:
> > On 5/7/26 1:40 AM, Thinh Nguyen wrote:
> > > On Tue, May 05, 2026, Konrad Dybcio wrote:
> > >> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> > >>
> > >> The Thunderbolt framework relies on the USB core to create device links
> > >> for tunneled ports, so that the USB3 controller is only kept
> > >> runtime-resumed for the duration of the tunneling. This depends on
> > >> first knowing whether a connection is tunneled or native.
> > >>
> > >> Add the logic to handle that for DWC3 controllers.
> > >>
> > >> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> > >> ---
> > >>  drivers/usb/dwc3/core.c | 12 ++++++++++++
> > >>  drivers/usb/dwc3/core.h | 18 ++++++++++++++++++
> > >>  drivers/usb/dwc3/host.c | 12 ++++++++++++
> > >>  3 files changed, 42 insertions(+)
> > >>
> > >> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> > >> index 65213896de99..7cec4911e278 100644
> > >> --- a/drivers/usb/dwc3/core.c
> > >> +++ b/drivers/usb/dwc3/core.c
> > >> @@ -162,6 +162,18 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy)
> > >>  }
> > >>  EXPORT_SYMBOL_GPL(dwc3_set_prtcap);
> > >>  
> > >> +enum usb_link_tunnel_mode dwc3_link_tunnel_mode(struct dwc3 *dwc, u8 port)
> > >> +{
> > >> +	/* Prior versions had no CIO support */
> > >> +	if (!DWC3_VER_IS_WITHIN(DWC31, 191A, ANY))
> > >> +		return USB_LINK_NATIVE;
> > >> +
> > >> +	if (dwc3_readl(dwc, DWC3_CIOCTRL(port)) & DWC3_CIOCTRL_CIO_EN)
> > > 
> > > The CIO register block only exists if DWC1_USB31_EN_CIO is set (and
> > > DWC_USB31_EN_USB2_ONLY is not set). In most cases, this register block
> > > will be reserved, register read of reserved block should be 0. But we
> > > can't guarantee that it will always be the case.
> > 
> > That's inconvenient because..
> > 
> > [...]
> > 
> > > We shouldn't need to be doing this. This should be checked from the
> > > xHCI driver. Check xHCI spec for PORTSC.TM and USB3 tunneling support
> > > capability (section 7.11).
> > 
> > ..I'm seeing only caps 0/1/2 (and 10 on some but not all) advertised
> > (I ran a for-loop checking offsets 0..=255)
> 
> Right.  That section in xHCI spec was only added in the 1.2b revision.
> However the DWC31 IP versions that current Qualcomm USB4-capable SoCs
> are using are 2.00a (and a customized version of 1.91a) which are only
> compliant to xHCI 1.1 so this capability is not there, even though the
> CIO register block exists.  So short of having the proper XHCI bit, this
> is the next best, non-SoC specific alternative we've found that can
> allow XHCI driver to identify when it is operating in tunnel mode.
> 

I see. If you're using 2.00a, then we can't use the xHCI's capability
register and PORTSC.TM.

Can we match the compatible string to check for CIO capability and have
this passed from your glue driver before accessing the CIO registers?

BR,
Thinh

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] usb: dwc3: Notify XHCI core of tunneled status
  2026-05-07 22:46         ` Thinh Nguyen
@ 2026-05-08 12:04           ` Konrad Dybcio
  2026-05-08 23:31             ` Thinh Nguyen
  0 siblings, 1 reply; 16+ messages in thread
From: Konrad Dybcio @ 2026-05-08 12:04 UTC (permalink / raw)
  To: Thinh Nguyen, Jack Pham
  Cc: Konrad Dybcio, Greg Kroah-Hartman, Mathias Nyman,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	usb4-upstream@oss.qualcomm.com, Raghavendra Thoorpu,
	Mika Westerberg

On 5/8/26 12:46 AM, Thinh Nguyen wrote:
> On Thu, May 07, 2026, Jack Pham wrote:
>> On Thu, May 07, 2026 at 12:34:50PM +0200, Konrad Dybcio wrote:
>>> On 5/7/26 1:40 AM, Thinh Nguyen wrote:
>>>> On Tue, May 05, 2026, Konrad Dybcio wrote:
>>>>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>>>
>>>>> The Thunderbolt framework relies on the USB core to create device links
>>>>> for tunneled ports, so that the USB3 controller is only kept
>>>>> runtime-resumed for the duration of the tunneling. This depends on
>>>>> first knowing whether a connection is tunneled or native.
>>>>>
>>>>> Add the logic to handle that for DWC3 controllers.
>>>>>
>>>>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>>> ---
>>>>>  drivers/usb/dwc3/core.c | 12 ++++++++++++
>>>>>  drivers/usb/dwc3/core.h | 18 ++++++++++++++++++
>>>>>  drivers/usb/dwc3/host.c | 12 ++++++++++++
>>>>>  3 files changed, 42 insertions(+)
>>>>>
>>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>>> index 65213896de99..7cec4911e278 100644
>>>>> --- a/drivers/usb/dwc3/core.c
>>>>> +++ b/drivers/usb/dwc3/core.c
>>>>> @@ -162,6 +162,18 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy)
>>>>>  }
>>>>>  EXPORT_SYMBOL_GPL(dwc3_set_prtcap);
>>>>>  
>>>>> +enum usb_link_tunnel_mode dwc3_link_tunnel_mode(struct dwc3 *dwc, u8 port)
>>>>> +{
>>>>> +	/* Prior versions had no CIO support */
>>>>> +	if (!DWC3_VER_IS_WITHIN(DWC31, 191A, ANY))
>>>>> +		return USB_LINK_NATIVE;
>>>>> +
>>>>> +	if (dwc3_readl(dwc, DWC3_CIOCTRL(port)) & DWC3_CIOCTRL_CIO_EN)
>>>>
>>>> The CIO register block only exists if DWC1_USB31_EN_CIO is set (and
>>>> DWC_USB31_EN_USB2_ONLY is not set). In most cases, this register block
>>>> will be reserved, register read of reserved block should be 0. But we
>>>> can't guarantee that it will always be the case.
>>>
>>> That's inconvenient because..
>>>
>>> [...]
>>>
>>>> We shouldn't need to be doing this. This should be checked from the
>>>> xHCI driver. Check xHCI spec for PORTSC.TM and USB3 tunneling support
>>>> capability (section 7.11).
>>>
>>> ..I'm seeing only caps 0/1/2 (and 10 on some but not all) advertised
>>> (I ran a for-loop checking offsets 0..=255)
>>
>> Right.  That section in xHCI spec was only added in the 1.2b revision.
>> However the DWC31 IP versions that current Qualcomm USB4-capable SoCs
>> are using are 2.00a (and a customized version of 1.91a) which are only
>> compliant to xHCI 1.1 so this capability is not there, even though the
>> CIO register block exists.  So short of having the proper XHCI bit, this
>> is the next best, non-SoC specific alternative we've found that can
>> allow XHCI driver to identify when it is operating in tunnel mode.
>>
> 
> I see. If you're using 2.00a, then we can't use the xHCI's capability
> register and PORTSC.TM.
> 
> Can we match the compatible string to check for CIO capability and have
> this passed from your glue driver before accessing the CIO registers?

Hm, we currently use a shared compatible string for the USB3+4 (1.91a-xxx)
and USB2 (3.30a) hosts on the USB4-capable platforms..

Another idea would be to bail out if

!device_property_present(dev, "usb4-host-interface")

which would place the burden of making sure the DT makes sense on the
programmer (which is OK in my view)

Konrad

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] usb: dwc3: Notify XHCI core of tunneled status
  2026-05-08 12:04           ` Konrad Dybcio
@ 2026-05-08 23:31             ` Thinh Nguyen
  2026-05-11  9:06               ` Konrad Dybcio
  0 siblings, 1 reply; 16+ messages in thread
From: Thinh Nguyen @ 2026-05-08 23:31 UTC (permalink / raw)
  To: Konrad Dybcio
  Cc: Thinh Nguyen, Jack Pham, Konrad Dybcio, Greg Kroah-Hartman,
	Mathias Nyman, linux-usb@vger.kernel.org,
	linux-kernel@vger.kernel.org, usb4-upstream@oss.qualcomm.com,
	Raghavendra Thoorpu, Mika Westerberg

On Fri, May 08, 2026, Konrad Dybcio wrote:
> On 5/8/26 12:46 AM, Thinh Nguyen wrote:
> > On Thu, May 07, 2026, Jack Pham wrote:
> >> On Thu, May 07, 2026 at 12:34:50PM +0200, Konrad Dybcio wrote:
> >>> On 5/7/26 1:40 AM, Thinh Nguyen wrote:
> >>>> On Tue, May 05, 2026, Konrad Dybcio wrote:
> >>>>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> >>>>>
> >>>>> The Thunderbolt framework relies on the USB core to create device links
> >>>>> for tunneled ports, so that the USB3 controller is only kept
> >>>>> runtime-resumed for the duration of the tunneling. This depends on
> >>>>> first knowing whether a connection is tunneled or native.
> >>>>>
> >>>>> Add the logic to handle that for DWC3 controllers.
> >>>>>
> >>>>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> >>>>> ---
> >>>>>  drivers/usb/dwc3/core.c | 12 ++++++++++++
> >>>>>  drivers/usb/dwc3/core.h | 18 ++++++++++++++++++
> >>>>>  drivers/usb/dwc3/host.c | 12 ++++++++++++
> >>>>>  3 files changed, 42 insertions(+)
> >>>>>
> >>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> >>>>> index 65213896de99..7cec4911e278 100644
> >>>>> --- a/drivers/usb/dwc3/core.c
> >>>>> +++ b/drivers/usb/dwc3/core.c
> >>>>> @@ -162,6 +162,18 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy)
> >>>>>  }
> >>>>>  EXPORT_SYMBOL_GPL(dwc3_set_prtcap);
> >>>>>  
> >>>>> +enum usb_link_tunnel_mode dwc3_link_tunnel_mode(struct dwc3 *dwc, u8 port)
> >>>>> +{
> >>>>> +	/* Prior versions had no CIO support */
> >>>>> +	if (!DWC3_VER_IS_WITHIN(DWC31, 191A, ANY))
> >>>>> +		return USB_LINK_NATIVE;
> >>>>> +
> >>>>> +	if (dwc3_readl(dwc, DWC3_CIOCTRL(port)) & DWC3_CIOCTRL_CIO_EN)
> >>>>
> >>>> The CIO register block only exists if DWC1_USB31_EN_CIO is set (and
> >>>> DWC_USB31_EN_USB2_ONLY is not set). In most cases, this register block
> >>>> will be reserved, register read of reserved block should be 0. But we
> >>>> can't guarantee that it will always be the case.
> >>>
> >>> That's inconvenient because..
> >>>
> >>> [...]
> >>>
> >>>> We shouldn't need to be doing this. This should be checked from the
> >>>> xHCI driver. Check xHCI spec for PORTSC.TM and USB3 tunneling support
> >>>> capability (section 7.11).
> >>>
> >>> ..I'm seeing only caps 0/1/2 (and 10 on some but not all) advertised
> >>> (I ran a for-loop checking offsets 0..=255)
> >>
> >> Right.  That section in xHCI spec was only added in the 1.2b revision.
> >> However the DWC31 IP versions that current Qualcomm USB4-capable SoCs
> >> are using are 2.00a (and a customized version of 1.91a) which are only
> >> compliant to xHCI 1.1 so this capability is not there, even though the
> >> CIO register block exists.  So short of having the proper XHCI bit, this
> >> is the next best, non-SoC specific alternative we've found that can
> >> allow XHCI driver to identify when it is operating in tunnel mode.
> >>
> > 
> > I see. If you're using 2.00a, then we can't use the xHCI's capability
> > register and PORTSC.TM.
> > 
> > Can we match the compatible string to check for CIO capability and have
> > this passed from your glue driver before accessing the CIO registers?
> 
> Hm, we currently use a shared compatible string for the USB3+4 (1.91a-xxx)
> and USB2 (3.30a) hosts on the USB4-capable platforms..

Ok.

> 
> Another idea would be to bail out if
> 
> !device_property_present(dev, "usb4-host-interface")
> 
> which would place the burden of making sure the DT makes sense on the
> programmer (which is OK in my view)
> 

For the DWC3_CIOCTRL_CIO_EN to be set, it needs to be done by the type-c
driver after detecting alternate mode right? How is it being done now?
Can the udev->tunnel_mode be updated directly by your type-c driver
when it sets DWC3_CIOCTRL_CIO_EN?

BR,
Thinh

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] usb: dwc3: Notify XHCI core of tunneled status
  2026-05-08 23:31             ` Thinh Nguyen
@ 2026-05-11  9:06               ` Konrad Dybcio
  2026-05-11 18:44                 ` Sven Peter
  0 siblings, 1 reply; 16+ messages in thread
From: Konrad Dybcio @ 2026-05-11  9:06 UTC (permalink / raw)
  To: Thinh Nguyen, Sven Peter
  Cc: Jack Pham, Konrad Dybcio, Greg Kroah-Hartman, Mathias Nyman,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	usb4-upstream@oss.qualcomm.com, Raghavendra Thoorpu,
	Mika Westerberg

On 5/9/26 1:31 AM, Thinh Nguyen wrote:
> On Fri, May 08, 2026, Konrad Dybcio wrote:
>> On 5/8/26 12:46 AM, Thinh Nguyen wrote:
>>> On Thu, May 07, 2026, Jack Pham wrote:
>>>> On Thu, May 07, 2026 at 12:34:50PM +0200, Konrad Dybcio wrote:
>>>>> On 5/7/26 1:40 AM, Thinh Nguyen wrote:
>>>>>> On Tue, May 05, 2026, Konrad Dybcio wrote:
>>>>>>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>>>>>
>>>>>>> The Thunderbolt framework relies on the USB core to create device links
>>>>>>> for tunneled ports, so that the USB3 controller is only kept
>>>>>>> runtime-resumed for the duration of the tunneling. This depends on
>>>>>>> first knowing whether a connection is tunneled or native.
>>>>>>>
>>>>>>> Add the logic to handle that for DWC3 controllers.
>>>>>>>
>>>>>>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>>>>> ---
>>>>>>>  drivers/usb/dwc3/core.c | 12 ++++++++++++
>>>>>>>  drivers/usb/dwc3/core.h | 18 ++++++++++++++++++
>>>>>>>  drivers/usb/dwc3/host.c | 12 ++++++++++++
>>>>>>>  3 files changed, 42 insertions(+)
>>>>>>>
>>>>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>>>>> index 65213896de99..7cec4911e278 100644
>>>>>>> --- a/drivers/usb/dwc3/core.c
>>>>>>> +++ b/drivers/usb/dwc3/core.c
>>>>>>> @@ -162,6 +162,18 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy)
>>>>>>>  }
>>>>>>>  EXPORT_SYMBOL_GPL(dwc3_set_prtcap);
>>>>>>>  
>>>>>>> +enum usb_link_tunnel_mode dwc3_link_tunnel_mode(struct dwc3 *dwc, u8 port)
>>>>>>> +{
>>>>>>> +	/* Prior versions had no CIO support */
>>>>>>> +	if (!DWC3_VER_IS_WITHIN(DWC31, 191A, ANY))
>>>>>>> +		return USB_LINK_NATIVE;
>>>>>>> +
>>>>>>> +	if (dwc3_readl(dwc, DWC3_CIOCTRL(port)) & DWC3_CIOCTRL_CIO_EN)
>>>>>>
>>>>>> The CIO register block only exists if DWC1_USB31_EN_CIO is set (and
>>>>>> DWC_USB31_EN_USB2_ONLY is not set). In most cases, this register block
>>>>>> will be reserved, register read of reserved block should be 0. But we
>>>>>> can't guarantee that it will always be the case.
>>>>>
>>>>> That's inconvenient because..
>>>>>
>>>>> [...]
>>>>>
>>>>>> We shouldn't need to be doing this. This should be checked from the
>>>>>> xHCI driver. Check xHCI spec for PORTSC.TM and USB3 tunneling support
>>>>>> capability (section 7.11).
>>>>>
>>>>> ..I'm seeing only caps 0/1/2 (and 10 on some but not all) advertised
>>>>> (I ran a for-loop checking offsets 0..=255)
>>>>
>>>> Right.  That section in xHCI spec was only added in the 1.2b revision.
>>>> However the DWC31 IP versions that current Qualcomm USB4-capable SoCs
>>>> are using are 2.00a (and a customized version of 1.91a) which are only
>>>> compliant to xHCI 1.1 so this capability is not there, even though the
>>>> CIO register block exists.  So short of having the proper XHCI bit, this
>>>> is the next best, non-SoC specific alternative we've found that can
>>>> allow XHCI driver to identify when it is operating in tunnel mode.
>>>>
>>>
>>> I see. If you're using 2.00a, then we can't use the xHCI's capability
>>> register and PORTSC.TM.
>>>
>>> Can we match the compatible string to check for CIO capability and have
>>> this passed from your glue driver before accessing the CIO registers?
>>
>> Hm, we currently use a shared compatible string for the USB3+4 (1.91a-xxx)
>> and USB2 (3.30a) hosts on the USB4-capable platforms..
> 
> Ok.
> 
>>
>> Another idea would be to bail out if
>>
>> !device_property_present(dev, "usb4-host-interface")
>>
>> which would place the burden of making sure the DT makes sense on the
>> programmer (which is OK in my view)
>>
> 
> For the DWC3_CIOCTRL_CIO_EN to be set, it needs to be done by the type-c
> driver after detecting alternate mode right? How is it being done now?
> Can the udev->tunnel_mode be updated directly by your type-c driver
> when it sets DWC3_CIOCTRL_CIO_EN?

For us, it seems to be hardwired (not sure if actually, but definitely
effectively) to a separate register which is used to select the right
clock mux for the USB3 protocol adapter to work (which is to be set if
USB3 tunneling is going to be used)

Moreover, the register definition for our SoCs calls all fields of
CIOCTRL read-only, whereas the DWC programming guide says they're R/W -
possibly supporting my theory above

FWIW, our Type-C infra is as such:

1. thick firmware layer running on a MCU that performs mode&PD handshakes
2. drivers/soc/qcom/pmic_glink_altmode.c receives notifications of what
   the FW had negotiated with regards to mode
3. a relatively small subset of UCSI provides PD data (and some altmode
   data)
4. drivers/phy/qualcomm/phy-qcom-qmp-combo.c reprograms the PHY based
   on typec_mux events in native cases, or to USB4/TBT mode if the router
   driver requests it [that last part is not yet upstream]
5. [optionally] retimer drivers in between (most often Parade PS883x
   series via drivers/usb/typec/mux/ps883x.c), which act as an
   additional typec_mux/switch in the chain
6. [not upstream yet] USB4 router driver consumes some typec_mux
   parameters (orientation, cable and partner capabilities) and sends a
   command to another MCU to high-speed link establishment. It also sets
   the aforementioned magic register.

At a glance, 2. seems like a reasonably fitting place to set it, however:
* it does not have any sort of a handle to the typec_connector (it
only acts like a mux that sets another mux), and
* it may be going away in the future

so I'd much prefer to keep this logic somewhere near where this iteration
of the patch does - I think it'll be useful for more implementations, as
I'd imagine it'd be fairly commonplace to hardwire CIOCTRL_CIO_EN and
another part of the pipeline that must logically be online for USB4 to
be useful

+Sven, on ASi, is CIOCTRL_CIO_EN (dwc3base + (0xcd20 + ((port) * 0x30))
written to manually?

Konrad

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] usb: dwc3: Notify XHCI core of tunneled status
  2026-05-11  9:06               ` Konrad Dybcio
@ 2026-05-11 18:44                 ` Sven Peter
  0 siblings, 0 replies; 16+ messages in thread
From: Sven Peter @ 2026-05-11 18:44 UTC (permalink / raw)
  To: Konrad Dybcio
  Cc: Jack Pham, Konrad Dybcio, Greg Kroah-Hartman, Mathias Nyman,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	usb4-upstream@oss.qualcomm.com, Raghavendra Thoorpu,
	Mika Westerberg, Thinh Nguyen

Hi,

On 11.05.26 11:06, Konrad Dybcio wrote:
> On 5/9/26 1:31 AM, Thinh Nguyen wrote:
>> On Fri, May 08, 2026, Konrad Dybcio wrote:
>>> On 5/8/26 12:46 AM, Thinh Nguyen wrote:
>>>> On Thu, May 07, 2026, Jack Pham wrote:
>>>>> On Thu, May 07, 2026 at 12:34:50PM +0200, Konrad Dybcio wrote:
>>>>>> On 5/7/26 1:40 AM, Thinh Nguyen wrote:
>>>>>>> On Tue, May 05, 2026, Konrad Dybcio wrote:
>>>>>>>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>>>>>>
>>>>>>>> The Thunderbolt framework relies on the USB core to create device links
>>>>>>>> for tunneled ports, so that the USB3 controller is only kept
>>>>>>>> runtime-resumed for the duration of the tunneling. This depends on
>>>>>>>> first knowing whether a connection is tunneled or native.
>>>>>>>>
>>>>>>>> Add the logic to handle that for DWC3 controllers.
>>>>>>>>
>>>>>>>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>>>>>> ---
>>>>>>>>   drivers/usb/dwc3/core.c | 12 ++++++++++++
>>>>>>>>   drivers/usb/dwc3/core.h | 18 ++++++++++++++++++
>>>>>>>>   drivers/usb/dwc3/host.c | 12 ++++++++++++
>>>>>>>>   3 files changed, 42 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>>>>>> index 65213896de99..7cec4911e278 100644
>>>>>>>> --- a/drivers/usb/dwc3/core.c
>>>>>>>> +++ b/drivers/usb/dwc3/core.c
>>>>>>>> @@ -162,6 +162,18 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy)
>>>>>>>>   }
>>>>>>>>   EXPORT_SYMBOL_GPL(dwc3_set_prtcap);
>>>>>>>>   
>>>>>>>> +enum usb_link_tunnel_mode dwc3_link_tunnel_mode(struct dwc3 *dwc, u8 port)
>>>>>>>> +{
>>>>>>>> +	/* Prior versions had no CIO support */
>>>>>>>> +	if (!DWC3_VER_IS_WITHIN(DWC31, 191A, ANY))
>>>>>>>> +		return USB_LINK_NATIVE;
>>>>>>>> +
>>>>>>>> +	if (dwc3_readl(dwc, DWC3_CIOCTRL(port)) & DWC3_CIOCTRL_CIO_EN)
>>>>>>>
>>>>>>> The CIO register block only exists if DWC1_USB31_EN_CIO is set (and
>>>>>>> DWC_USB31_EN_USB2_ONLY is not set). In most cases, this register block
>>>>>>> will be reserved, register read of reserved block should be 0. But we
>>>>>>> can't guarantee that it will always be the case.
>>>>>>
>>>>>> That's inconvenient because..
>>>>>>
>>>>>> [...]
>>>>>>
>>>>>>> We shouldn't need to be doing this. This should be checked from the
>>>>>>> xHCI driver. Check xHCI spec for PORTSC.TM and USB3 tunneling support
>>>>>>> capability (section 7.11).
>>>>>>
>>>>>> ..I'm seeing only caps 0/1/2 (and 10 on some but not all) advertised
>>>>>> (I ran a for-loop checking offsets 0..=255)
>>>>>
>>>>> Right.  That section in xHCI spec was only added in the 1.2b revision.
>>>>> However the DWC31 IP versions that current Qualcomm USB4-capable SoCs
>>>>> are using are 2.00a (and a customized version of 1.91a) which are only
>>>>> compliant to xHCI 1.1 so this capability is not there, even though the
>>>>> CIO register block exists.  So short of having the proper XHCI bit, this
>>>>> is the next best, non-SoC specific alternative we've found that can
>>>>> allow XHCI driver to identify when it is operating in tunnel mode.
>>>>>
>>>>
>>>> I see. If you're using 2.00a, then we can't use the xHCI's capability
>>>> register and PORTSC.TM.
>>>>
>>>> Can we match the compatible string to check for CIO capability and have
>>>> this passed from your glue driver before accessing the CIO registers?
>>>
>>> Hm, we currently use a shared compatible string for the USB3+4 (1.91a-xxx)
>>> and USB2 (3.30a) hosts on the USB4-capable platforms..
>>
>> Ok.
>>
>>>
>>> Another idea would be to bail out if
>>>
>>> !device_property_present(dev, "usb4-host-interface")
>>>
>>> which would place the burden of making sure the DT makes sense on the
>>> programmer (which is OK in my view)
>>>
>>
>> For the DWC3_CIOCTRL_CIO_EN to be set, it needs to be done by the type-c
>> driver after detecting alternate mode right? How is it being done now?
>> Can the udev->tunnel_mode be updated directly by your type-c driver
>> when it sets DWC3_CIOCTRL_CIO_EN?
> 
> For us, it seems to be hardwired (not sure if actually, but definitely
> effectively) to a separate register which is used to select the right
> clock mux for the USB3 protocol adapter to work (which is to be set if
> USB3 tunneling is going to be used)

Same for Apple Silicon: We have to switch the PIPE interface and some 
unknown clock from USB3 to USB3-via-USB4 inside the Type-C PHY driver.
For Apple Silicon we use apple,tXXXX-dwc3 as the base compatible and 
then match on that with a dwc3 glue driver like Thinh suggested when I 
upstreamed usb3 support which calls into the Type-C PHY to do this at 
just the right moment.

> 
> Moreover, the register definition for our SoCs calls all fields of
> CIOCTRL read-only, whereas the DWC programming guide says they're R/W -
> possibly supporting my theory above
> 
> FWIW, our Type-C infra is as such:
> 
> 1. thick firmware layer running on a MCU that performs mode&PD handshakes
> 2. drivers/soc/qcom/pmic_glink_altmode.c receives notifications of what
>     the FW had negotiated with regards to mode
> 3. a relatively small subset of UCSI provides PD data (and some altmode
>     data)
This is similar to Apple Silicon.

> 4. drivers/phy/qualcomm/phy-qcom-qmp-combo.c reprograms the PHY based
>     on typec_mux events in native cases, or to USB4/TBT mode if the router
>     driver requests it [that last part is not yet upstream]
> 5. [optionally] retimer drivers in between (most often Parade PS883x
>     series via drivers/usb/typec/mux/ps883x.c), which act as an
>     additional typec_mux/switch in the chain
> 6. [not upstream yet] USB4 router driver consumes some typec_mux
>     parameters (orientation, cable and partner capabilities) and sends a
>     command to another MCU to high-speed link establishment. It also sets
>     the aforementioned magic register.

I'm not sure if mux is the correct framework here. On Apple Silicon we 
also need an out-of-band notification from the PD controller to the USB4 
NHI here but the NHI isn't a mux in the typec sense. And how do you 
ensure that 4 happens before 6 if you use the typec mux framework or 
does that not matter for your platform?
Currently I use [1] and [2] in my work-in-progress tree though I'm not 
quite happy with it yet.

> 
> At a glance, 2. seems like a reasonably fitting place to set it, however:
> * it does not have any sort of a handle to the typec_connector (it
> only acts like a mux that sets another mux), and
> * it may be going away in the future
> 
> so I'd much prefer to keep this logic somewhere near where this iteration
> of the patch does - I think it'll be useful for more implementations, as
> I'd imagine it'd be fairly commonplace to hardwire CIOCTRL_CIO_EN and
> another part of the pipeline that must logically be online for USB4 to
> be useful
> 
> +Sven, on ASi, is CIOCTRL_CIO_EN (dwc3base + (0xcd20 + ((port) * 0x30))
> written to manually?

I don't think so, but we need a manual out-of-band notification to both 
PCIe, tunneled DisplayPort and USB3 once the tunnel has been brought 
upside the NHI (i.e. long after the typec altmode is entered) and all 
this has to be represented in the device tree as well.
DWC3 on Apple platforms is very cursed and has to be fully offline while 
the Type-C switches modes and must only be brought up then once the 
tunnel inside the NHI has already been established.

My current WIP code uses a tbt_oob_notify for all that that I introduced 
and something like this in the dt to represent the connections:

/* USB4 */
&usb4_1_acio {
	ports {
		#address-cells = <1>;
		#size-cells = <0>;

		/* 1: USB4 port */
		port@1 {
			reg = <1>;
			usb4_1_acio_tbt: endpoint {
				remote-endpoint = <&typec1_con_tbt>;
			};
		};

		/* 2: unused(?) USB4 port */
		/* 3: PCIe, TBD */
		/* 4: USB3, TBD */
		/* 5: DP0, TBD */
		/* 6: DP1, TBD */
	};
};

Still not completely happy with that as well.
Does PCIe tunneling also need additional OOB notifications for you?


Sven



[1] 
https://github.com/AsahiLinux/linux/commit/b51ae0383e8f201aa0d2997d875f4b4993848b06
[2] 
https://github.com/AsahiLinux/linux/commit/827a9bfedbc78d7ad56c0c286382fe15d70d4f95


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2026-05-11 18:44 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-05  8:55 [PATCH 0/2] DWC3 link tunneling state reporting Konrad Dybcio
2026-05-05  8:55 ` [PATCH 1/2] usb: host: xhci: Allow non-Intel usb_link_tunnel_mode reporting Konrad Dybcio
2026-05-05 12:14   ` Mika Westerberg
2026-05-07 10:40     ` Konrad Dybcio
2026-05-07 12:48       ` Mathias Nyman
2026-05-07 12:53         ` Konrad Dybcio
2026-05-07 13:11           ` Mika Westerberg
2026-05-05  8:55 ` [PATCH 2/2] usb: dwc3: Notify XHCI core of tunneled status Konrad Dybcio
2026-05-06 23:40   ` Thinh Nguyen
2026-05-07 10:34     ` Konrad Dybcio
2026-05-07 17:46       ` Jack Pham
2026-05-07 22:46         ` Thinh Nguyen
2026-05-08 12:04           ` Konrad Dybcio
2026-05-08 23:31             ` Thinh Nguyen
2026-05-11  9:06               ` Konrad Dybcio
2026-05-11 18:44                 ` Sven Peter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox