thunderbolt: Fix wake configurations after device unplug
authorGil Fine <gil.fine@linux.intel.com>
Fri, 1 Mar 2024 13:22:53 +0000 (15:22 +0200)
committerMika Westerberg <mika.westerberg@linux.intel.com>
Wed, 10 Apr 2024 07:49:58 +0000 (10:49 +0300)
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>
drivers/thunderbolt/switch.c

index 6ffc4e81ffed78bedaac182b5a77742390c6cd74..4edfd6e34e31938030da19b5c0c7680ade2571e8 100644 (file)
@@ -3180,22 +3180,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 void tb_switch_credits_init(struct tb_switch *sw)