From: Mohammad Rahimi <rahimi.mhmmd@gmail.com>
To: mika.westerberg@linux.intel.com
Cc: andreas.noever@gmail.com, michael.jamet@intel.com,
YehezkelShB@gmail.com, linux-usb@vger.kernel.org,
linux-kernel@vger.kernel.org,
Mohammad Rahimi <rahimi.mhmmd@gmail.com>
Subject: [PATCH v4] thunderbolt: Disable Gen 4 Recovery on Asymmetric Transitions
Date: Fri, 31 Jan 2025 01:41:27 +0000 [thread overview]
Message-ID: <20250131014406.28645-4-rahimi.mhmmd@gmail.com> (raw)
In-Reply-To: <20250131014406.28645-1-rahimi.mhmmd@gmail.com>
Updates the Connection Manager to disable the Gen 4 Link Recovery
flow before transitioning from a Symmetric Link to an Asymmetric
Link, as specified in recent changes to the USB4 v2 specification.
According to the "USB4 2.0 ENGINEERING CHANGE NOTICE FORM"
published in September 2024, the rationale for this change is:
"Since the default value of the Target Asymmetric Link might be
different than Symmetric Link and Gen 4 Link Recovery flow checks
this field to make sure it matched the actual Negotiated Link Width,
we’re removing the condition for a Disconnect in the Gen 4 Link
Recovery flow when Target Asymmetric Link doesn’t match the actual
Link width and adding a Connection Manager note to Disable Gen 4 Link
Recovery flow before doing Asymmetric Transitions."
Signed-off-by: Mohammad Rahimi <rahimi.mhmmd@gmail.com>
---
drivers/thunderbolt/tb.c | 18 ++++++--
drivers/thunderbolt/tb.h | 3 ++
drivers/thunderbolt/tb_regs.h | 1 +
drivers/thunderbolt/usb4.c | 77 +++++++++++++++++++++++++++++++++++
4 files changed, 96 insertions(+), 3 deletions(-)
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index a7c6919fbf97..a3ccfb398797 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -1013,6 +1013,7 @@ static int tb_configure_asym(struct tb *tb, struct tb_port *src_port,
struct tb_port *dst_port, int requested_up,
int requested_down)
{
+ bool link_recovery_up = false, link_recovery_down = false;
bool clx = false, clx_disabled = false, downstream;
struct tb_switch *sw;
struct tb_port *up;
@@ -1075,15 +1076,19 @@ static int tb_configure_asym(struct tb *tb, struct tb_port *src_port,
continue;
/*
- * Disable CL states before doing any transitions. We
- * delayed it until now that we know there is a real
- * transition taking place.
+ * Disable CL states and Link Recovery before doing any
+ * transitions. We delayed it until now that we know
+ * there is a real transition taking place.
*/
if (!clx_disabled) {
clx = tb_disable_clx(sw);
clx_disabled = true;
}
+ /* Ignore non-critical errors of disabling Link Recovery */
+ link_recovery_up = (usb4_port_link_recovery_disable(up) > 0);
+ link_recovery_down = (usb4_port_link_recovery_disable(down) > 0);
+
tb_sw_dbg(up->sw, "configuring asymmetric link\n");
/*
@@ -1091,6 +1096,13 @@ static int tb_configure_asym(struct tb *tb, struct tb_port *src_port,
* transtion the link into asymmetric now.
*/
ret = tb_switch_set_link_width(up->sw, width_up);
+
+ /* Re-enable Link Recovery if they were previously enabled */
+ if (link_recovery_up)
+ usb4_port_link_recovery_enable(up);
+ if (link_recovery_down)
+ usb4_port_link_recovery_enable(down);
+
if (ret) {
tb_sw_warn(up->sw, "failed to set link width\n");
break;
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index ddbf0cd78377..d37d778082fc 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -1332,6 +1332,9 @@ int usb4_port_router_online(struct tb_port *port);
int usb4_port_enumerate_retimers(struct tb_port *port);
bool usb4_port_clx_supported(struct tb_port *port);
+int usb4_port_link_recovery_enable(struct tb_port *port);
+int usb4_port_link_recovery_disable(struct tb_port *port);
+
bool usb4_port_asym_supported(struct tb_port *port);
int usb4_port_asym_set_link_width(struct tb_port *port, enum tb_link_width width);
int usb4_port_asym_start(struct tb_port *port);
diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h
index 4e43b47f9f11..085139e1a958 100644
--- a/drivers/thunderbolt/tb_regs.h
+++ b/drivers/thunderbolt/tb_regs.h
@@ -398,6 +398,7 @@ struct tb_regs_port_header {
#define PORT_CS_19_WOD BIT(17)
#define PORT_CS_19_WOU4 BIT(18)
#define PORT_CS_19_START_ASYM BIT(24)
+#define PORT_CS_19_ELR BIT(31)
/* Display Port adapter registers */
#define ADP_DP_CS_0 0x00
diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c
index e51d01671d8e..450e3920f20c 100644
--- a/drivers/thunderbolt/usb4.c
+++ b/drivers/thunderbolt/usb4.c
@@ -10,6 +10,7 @@
#include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/units.h>
+#include <linux/string_helpers.h>
#include "sb_regs.h"
#include "tb.h"
@@ -1518,6 +1519,82 @@ bool usb4_port_clx_supported(struct tb_port *port)
return !!(val & PORT_CS_18_CPS);
}
+static int __usb4_port_link_recovery_enable(struct tb_port *port, bool enable)
+{
+ bool was_enable;
+ int ret;
+ u32 val;
+
+ if (!port->cap_usb4)
+ return -EINVAL;
+
+ ret = tb_port_read(port, &val, TB_CFG_PORT,
+ port->cap_usb4 + PORT_CS_19, 1);
+ if (ret)
+ return ret;
+
+ was_enable = !!(val & PORT_CS_19_ELR);
+
+ if (enable)
+ val |= PORT_CS_19_ELR;
+ else
+ val &= ~PORT_CS_19_ELR;
+
+ ret = tb_port_write(port, &val, TB_CFG_PORT,
+ port->cap_usb4 + PORT_CS_19, 1);
+ if (ret)
+ return ret;
+
+ tb_port_dbg(port, "link recovery %s\n", str_enabled_disabled(enable));
+ return was_enable ? 1 : 0;
+}
+
+/**
+ * usb4_port_link_recovery_enable() - Enable the Link Recovery
+ * @port: USB4 port
+ *
+ * Enables the Link Recovery for @port.
+ *
+ * Returns:
+ * * %-EINVAL - Capability not present.
+ * * %-ENODEV - Switch unplugged.
+ * * %-ETIMEDOUT - Config space access timed out.
+ * * %0 - Successfully enabled.
+ * * %1 - Already enabled.
+ */
+int usb4_port_link_recovery_enable(struct tb_port *port)
+{
+ int ret = __usb4_port_link_recovery_enable(port, true);
+
+ if (ret < 0)
+ tb_port_warn(port, "failed to enable link recovery\n");
+
+ return ret;
+}
+
+/**
+ * usb4_port_link_recovery_disable() - Disable the Link Recovery
+ * @port: USB4 port
+ *
+ * Disables the Link Recovery for @port.
+ *
+ * Returns:
+ * * %-EINVAL - Capability not present.
+ * * %-ENODEV - Switch unplugged.
+ * * %-ETIMEDOUT - Config space access timed out.
+ * * %0 - Already disabled.
+ * * %1 - Successfully disabled.
+ */
+int usb4_port_link_recovery_disable(struct tb_port *port)
+{
+ int ret = __usb4_port_link_recovery_enable(port, false);
+
+ if (ret < 0)
+ tb_port_warn(port, "failed to disable link recovery\n");
+
+ return ret;
+}
+
/**
* usb4_port_asym_supported() - If the port supports asymmetric link
* @port: USB4 port
--
2.45.2
next prev parent reply other threads:[~2025-01-31 1:45 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-31 1:41 [PATCH v4 Cover Letter] thunderbolt: Disable Gen 4 Recovery on Asymmetric Transitions Mohammad Rahimi
2025-01-31 1:41 ` Mohammad Rahimi [this message]
2025-02-03 8:42 ` [PATCH v4] " Mika Westerberg
2025-02-03 12:25 ` Mohammad Rahimi
2025-02-03 12:39 ` Mika Westerberg
2025-02-03 12:43 ` Mohammad Rahimi
2025-02-03 12:59 ` Mika Westerberg
2025-02-04 11:16 ` Mika Westerberg
2025-02-04 11:39 ` Mika Westerberg
2025-02-04 2:35 ` Mohammad Rahimi
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=20250131014406.28645-4-rahimi.mhmmd@gmail.com \
--to=rahimi.mhmmd@gmail.com \
--cc=YehezkelShB@gmail.com \
--cc=andreas.noever@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=michael.jamet@intel.com \
--cc=mika.westerberg@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