From: Mika Westerberg <mika.westerberg@linux.intel.com>
To: linux-usb@vger.kernel.org
Cc: Yehezkel Bernat <YehezkelShB@gmail.com>,
Lukas Wunner <lukas@wunner.de>,
Andreas Noever <andreas.noever@gmail.com>,
Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>,
Pooja Katiyar <pooja.katiyar@intel.com>,
Rene Sapiens <rene.sapiens@linux.intel.com>,
Gil Fine <gil.fine@linux.intel.com>,
Mika Westerberg <mika.westerberg@linux.intel.com>
Subject: [PATCH 5/8] thunderbolt: Verify PCIe adapter in detect state before tunnel setup
Date: Tue, 12 May 2026 14:29:52 +0200 [thread overview]
Message-ID: <20260512122955.271688-6-mika.westerberg@linux.intel.com> (raw)
In-Reply-To: <20260512122955.271688-1-mika.westerberg@linux.intel.com>
From: Gil Fine <gil.fine@linux.intel.com>
The USB4 Connection Manager guide suggests that a PCIe downstream and
PCIe upstream adapters of the USB4 router is in the Detect state before
setting up a PCIe tunnel.
Add this check by verifying the LTSSM field in ADP_PCIE_CS_0 before
tunnel setup.
Signed-off-by: Gil Fine <gil.fine@linux.intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/thunderbolt/tb.h | 1 +
drivers/thunderbolt/tb_regs.h | 15 +++++++++++++++
drivers/thunderbolt/tunnel.c | 35 +++++++++++++++++++++++++++++++++++
drivers/thunderbolt/usb4.c | 24 ++++++++++++++++++++++++
4 files changed, 75 insertions(+)
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index 229b9e7961fb..d86919474fdb 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -1481,6 +1481,7 @@ int usb4_dp_port_allocate_bandwidth(struct tb_port *port, int bw);
int usb4_dp_port_requested_bandwidth(struct tb_port *port);
int usb4_pci_port_set_ext_encapsulation(struct tb_port *port, bool enable);
+int usb4_pci_port_ltssm_state(struct tb_port *port);
static inline bool tb_is_usb4_port_device(const struct device *dev)
{
diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h
index c0bf136236e6..75131fcfe044 100644
--- a/drivers/thunderbolt/tb_regs.h
+++ b/drivers/thunderbolt/tb_regs.h
@@ -473,10 +473,25 @@ struct tb_regs_port_header {
/* PCIe adapter registers */
#define ADP_PCIE_CS_0 0x00
+#define ADP_PCIE_CS_0_LTSSM_MASK GENMASK(28, 25)
#define ADP_PCIE_CS_0_PE BIT(31)
#define ADP_PCIE_CS_1 0x01
#define ADP_PCIE_CS_1_EE BIT(0)
+enum tb_pcie_ltssm_state {
+ USB4_PCIE_LTSSM_DETECT,
+ USB4_PCIE_LTSSM_POLLING,
+ USB4_PCIE_LTSSM_CONFIG,
+ USB4_PCIE_LTSSM_CONFIG_IDLE,
+ USB4_PCIE_LTSSM_RECOVERY,
+ USB4_PCIE_LTSSM_RECOVERY_IDLE,
+ USB4_PCIE_LTSSM_L0,
+ USB4_PCIE_LTSSM_L1,
+ USB4_PCIE_LTSSM_L2,
+ USB4_PCIE_LTSSM_DISABLED,
+ USB4_PCIE_LTSSM_HOT_RESET,
+};
+
/* USB adapter registers */
#define ADP_USB3_CS_0 0x00
#define ADP_USB3_CS_0_V BIT(30)
diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c
index f38f7753b6e4..b7f32305f14a 100644
--- a/drivers/thunderbolt/tunnel.c
+++ b/drivers/thunderbolt/tunnel.c
@@ -290,6 +290,40 @@ static inline void tb_tunnel_changed(struct tb_tunnel *tunnel)
tunnel->src_port, tunnel->dst_port);
}
+static int tb_pci_port_ltssm_state_detect(struct tb_port *port)
+{
+ ktime_t timeout = ktime_add_ms(ktime_get(), 500);
+
+ do {
+ int ret;
+
+ ret = usb4_pci_port_ltssm_state(port);
+ if (ret < 0)
+ return ret;
+ if (ret == USB4_PCIE_LTSSM_DETECT)
+ return 0;
+
+ fsleep(50);
+ } while (ktime_before(ktime_get(), timeout));
+
+ return -ETIMEDOUT;
+}
+
+static int tb_pci_pre_activate(struct tb_tunnel *tunnel)
+{
+ struct tb_port *down = tunnel->src_port;
+ struct tb_port *up = tunnel->dst_port;
+ int ret;
+
+ ret = tb_switch_is_usb4(down->sw) ?
+ tb_pci_port_ltssm_state_detect(down) : 0;
+ if (ret)
+ return ret;
+
+ return tb_switch_is_usb4(up->sw) ?
+ tb_pci_port_ltssm_state_detect(up) : 0;
+}
+
static int tb_pci_set_ext_encapsulation(struct tb_tunnel *tunnel, bool enable)
{
struct tb_port *port = tb_upstream_port(tunnel->dst_port->sw);
@@ -505,6 +539,7 @@ struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up,
if (!tunnel)
return NULL;
+ tunnel->pre_activate = tb_pci_pre_activate;
tunnel->activate = tb_pci_activate;
tunnel->src_port = down;
tunnel->dst_port = up;
diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c
index 9e810b2ae0b5..6f76bcaefa49 100644
--- a/drivers/thunderbolt/usb4.c
+++ b/drivers/thunderbolt/usb4.c
@@ -3145,3 +3145,27 @@ int usb4_pci_port_set_ext_encapsulation(struct tb_port *port, bool enable)
return tb_port_write(port, &val, TB_CFG_PORT,
port->cap_adap + ADP_PCIE_CS_1, 1);
}
+
+/**
+ * usb4_pci_port_ltssm_state() - Read PCIe adapter LTSSM state
+ * @port: PCIe adapter
+ *
+ * Return:
+ * * LTSSM state of @port.
+ * * Negative errno - On failure.
+ */
+int usb4_pci_port_ltssm_state(struct tb_port *port)
+{
+ u32 val;
+ int ret;
+
+ if (!tb_port_is_pcie_down(port) && !tb_port_is_pcie_up(port))
+ return -EINVAL;
+
+ ret = tb_port_read(port, &val, TB_CFG_PORT,
+ port->cap_adap + ADP_PCIE_CS_0, 1);
+ if (ret)
+ return ret;
+
+ return FIELD_GET(ADP_PCIE_CS_0_LTSSM_MASK, val);
+}
--
2.50.1
next prev parent reply other threads:[~2026-05-12 12:30 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-12 12:29 [PATCH 0/8] thunderbolt: Make the driver follow CM guide more closely Mika Westerberg
2026-05-12 12:29 ` [PATCH 1/8] thunderbolt: Improve multi-display DisplayPort tunnel allocation Mika Westerberg
2026-05-12 12:29 ` [PATCH 2/8] thunderbolt: Don't access path config space on Lane 1 adapters in tb_switch_reset_host() Mika Westerberg
2026-05-12 12:29 ` [PATCH 3/8] thunderbolt: Fix lane bonding log when bonding not possible Mika Westerberg
2026-05-12 12:29 ` [PATCH 4/8] thunderbolt: Activate path hops from source to destination Mika Westerberg
2026-05-12 12:29 ` Mika Westerberg [this message]
2026-05-12 12:29 ` [PATCH 6/8] thunderbolt: Verify Router Ready bit is set after router enumeration Mika Westerberg
2026-05-12 12:29 ` [PATCH 7/8] thunderbolt: Increase timeout for Configuration Ready bit Mika Westerberg
2026-05-12 12:29 ` [PATCH 8/8] thunderbolt: Increase Notification Timeout to 255 ms for USB4 routers Mika Westerberg
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=20260512122955.271688-6-mika.westerberg@linux.intel.com \
--to=mika.westerberg@linux.intel.com \
--cc=YehezkelShB@gmail.com \
--cc=alan.borzeszkowski@linux.intel.com \
--cc=andreas.noever@gmail.com \
--cc=gil.fine@linux.intel.com \
--cc=linux-usb@vger.kernel.org \
--cc=lukas@wunner.de \
--cc=pooja.katiyar@intel.com \
--cc=rene.sapiens@linux.intel.com \
/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