Software that has run before the USB4 CM in Linux runs may have disabled hotplug events for a given lane adapter.
Other CMs such as that one distributed with Windows 11 will enable hotplug events. Do the same thing in the Linux CM which fixes hotplug events on "AMD Pink Sardine".
Cc: stable@vger.kernel.org Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- v2->v3: * Guard with tb_switch_is_icm to avoid risk to Intel FW CM case v1->v2: * s/usb4_enable_hotplug/usb4_port_hotplug_enable/ * Clarify intended users in documentation comment * Only call for lane adapters * Add stable tag
Note: v2 it was suggested to move this to tb_switch_configure, but port->config is not yet read at that time. This should be the right time to call it, so this version of the patch just guards against the code running on Intel's controllers that have a FW CM.
drivers/thunderbolt/switch.c | 4 ++++ drivers/thunderbolt/tb.h | 1 + drivers/thunderbolt/tb_regs.h | 1 + drivers/thunderbolt/usb4.c | 23 +++++++++++++++++++++++ 4 files changed, 29 insertions(+)
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 77d7f07ca075..3213239d12c8 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -778,6 +778,10 @@ static int tb_init_port(struct tb_port *port)
if (!tb_port_read(port, &hop, TB_CFG_HOPS, 0, 2)) port->ctl_credits = hop.initial_credits; + + res = usb4_port_hotplug_enable(port); + if (res) + return res; } if (!port->ctl_credits) port->ctl_credits = 2; diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 5db76de40cc1..332159f984fc 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -1174,6 +1174,7 @@ int usb4_switch_add_ports(struct tb_switch *sw); void usb4_switch_remove_ports(struct tb_switch *sw);
int usb4_port_unlock(struct tb_port *port); +int usb4_port_hotplug_enable(struct tb_port *port); int usb4_port_configure(struct tb_port *port); void usb4_port_unconfigure(struct tb_port *port); int usb4_port_configure_xdomain(struct tb_port *port); diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h index 166054110388..bbe38b2d9057 100644 --- a/drivers/thunderbolt/tb_regs.h +++ b/drivers/thunderbolt/tb_regs.h @@ -308,6 +308,7 @@ struct tb_regs_port_header { #define ADP_CS_5 0x05 #define ADP_CS_5_LCA_MASK GENMASK(28, 22) #define ADP_CS_5_LCA_SHIFT 22 +#define ADP_CS_5_DHP BIT(31)
/* TMU adapter registers */ #define TMU_ADP_CS_3 0x03 diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index 3a2e7126db9d..98f3afa03036 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -1046,6 +1046,29 @@ int usb4_port_unlock(struct tb_port *port) return tb_port_write(port, &val, TB_CFG_PORT, ADP_CS_4, 1); }
+/** + * usb4_port_hotplug_enable() - Enables hotplug for a port + * @port: USB4 port to operate on + * + * Enables hot plug events on a given port. This is only intended + * to be used on lane, DP-IN, and DP-OUT adapters. + */ +int usb4_port_hotplug_enable(struct tb_port *port) +{ + int ret; + u32 val; + + if (tb_switch_is_icm(port->sw)) + return 0; + + ret = tb_port_read(port, &val, TB_CFG_PORT, ADP_CS_5, 1); + if (ret) + return ret; + + val &= ~ADP_CS_5_DHP; + return tb_port_write(port, &val, TB_CFG_PORT, ADP_CS_5, 1); +} + static int usb4_port_set_configured(struct tb_port *port, bool configured) { int ret;
Hi Mario,
On Fri, Sep 23, 2022 at 01:39:44PM -0500, Mario Limonciello wrote:
Software that has run before the USB4 CM in Linux runs may have disabled hotplug events for a given lane adapter.
Other CMs such as that one distributed with Windows 11 will enable hotplug events. Do the same thing in the Linux CM which fixes hotplug events on "AMD Pink Sardine".
Cc: stable@vger.kernel.org Signed-off-by: Mario Limonciello mario.limonciello@amd.com
v2->v3:
- Guard with tb_switch_is_icm to avoid risk to Intel FW CM case
v1->v2:
- s/usb4_enable_hotplug/usb4_port_hotplug_enable/
- Clarify intended users in documentation comment
- Only call for lane adapters
- Add stable tag
Note: v2 it was suggested to move this to tb_switch_configure, but port->config is not yet read at that time. This should be the right time to call it, so this version of the patch just guards against the code running on Intel's controllers that have a FW CM.
Can we put it in a separate function that is called from tb_switch_add()? I explained in the previous reply (to v2) that the tb_init_port() is pretty much just reading stuff and therefore I would not like to add there anything that does writing.
While at it, the USB4 v2 spec (not yet public but can be found from the working group site) adds a CM requirement that forbids writing lane 1 adapter configuration registers so in addition to that please check port->cap_usb4 there so we know we deal with the lane 0 adapter only (as ->cap_usb4 is only set for the lane 0 adapters).
So something like this:
static void tb_switch_port_hotplug_enable(struct tb_switch *sw) { if (tb_switch_is_icm(sw)) return;
tb_switch_for_each_port(sw, port) { if (!port->cap_usb4) continue;
// here enable the hotplug } }
int tb_switch_add(struct tb_switch *sw) { ... // init ports and stuff happens here
tb_switch_default_link_ports(sw); tb_switch_port_hotplug_enable(sw); }
(we should probably create a new macro tb_switch_for_each_usb4_port() that just enumerates all USB4 ports).
linux-stable-mirror@lists.linaro.org