summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGil Fine <gil.fine@linux.intel.com>2024-03-01 16:22:53 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-05-02 17:23:38 +0300
commit5a7e30d9be7ab708d5617763d7e4fdd86e2dec88 (patch)
treebbf61eb430f0017c6d6b24bbb48d16fbca48a5c3
parente6245ed82248ab1fd85d88ddb793b52dda90f609 (diff)
downloadlinux-5a7e30d9be7ab708d5617763d7e4fdd86e2dec88.tar.xz
thunderbolt: Fix wake configurations after device unplug
commit c38fa07dc69f0b9e6f43ecab96dc7861a70c827c upstream. Currently we don't configure correctly the wake events after unplug of device router. What can happen is that the downstream ports of host router will be configured to wake on: USB4-wake and wake-on-disconnect, but not on wake-on-connect. This may cause the later plugged device not to wake the domain and fail in enumeration. Fix this by clearing downstream port's "USB4 Port is Configured" bit, after unplug of a device router. Signed-off-by: Gil Fine <gil.fine@linux.intel.com> Cc: stable@vger.kernel.org Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/thunderbolt/switch.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index bbada6c25c04..b13a944eb462 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -2402,22 +2402,29 @@ void tb_switch_unconfigure_link(struct tb_switch *sw)
{
struct tb_port *up, *down;
- if (sw->is_unplugged)
- return;
if (!tb_route(sw) || tb_switch_is_icm(sw))
return;
+ /*
+ * Unconfigure downstream port so that wake-on-connect can be
+ * configured after router unplug. No need to unconfigure upstream port
+ * since its router is unplugged.
+ */
up = tb_upstream_port(sw);
- if (tb_switch_is_usb4(up->sw))
- usb4_port_unconfigure(up);
- else
- tb_lc_unconfigure_port(up);
-
down = up->remote;
if (tb_switch_is_usb4(down->sw))
usb4_port_unconfigure(down);
else
tb_lc_unconfigure_port(down);
+
+ if (sw->is_unplugged)
+ return;
+
+ up = tb_upstream_port(sw);
+ if (tb_switch_is_usb4(up->sw))
+ usb4_port_unconfigure(up);
+ else
+ tb_lc_unconfigure_port(up);
}
static int tb_switch_port_hotplug_enable(struct tb_switch *sw)