]>
Commit | Line | Data |
---|---|---|
a9af9959 GKH |
1 | From c38fa07dc69f0b9e6f43ecab96dc7861a70c827c Mon Sep 17 00:00:00 2001 |
2 | From: Gil Fine <gil.fine@linux.intel.com> | |
3 | Date: Fri, 1 Mar 2024 15:22:53 +0200 | |
4 | Subject: thunderbolt: Fix wake configurations after device unplug | |
5 | ||
6 | From: Gil Fine <gil.fine@linux.intel.com> | |
7 | ||
8 | commit c38fa07dc69f0b9e6f43ecab96dc7861a70c827c upstream. | |
9 | ||
10 | Currently we don't configure correctly the wake events after unplug of device | |
11 | router. What can happen is that the downstream ports of host router will be | |
12 | configured to wake on: USB4-wake and wake-on-disconnect, but not on | |
13 | wake-on-connect. This may cause the later plugged device not to wake the | |
14 | domain and fail in enumeration. Fix this by clearing downstream port's "USB4 | |
15 | Port is Configured" bit, after unplug of a device router. | |
16 | ||
17 | Signed-off-by: Gil Fine <gil.fine@linux.intel.com> | |
18 | Cc: stable@vger.kernel.org | |
19 | Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> | |
20 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
21 | --- | |
22 | drivers/thunderbolt/switch.c | 21 ++++++++++++++------- | |
23 | 1 file changed, 14 insertions(+), 7 deletions(-) | |
24 | ||
25 | --- a/drivers/thunderbolt/switch.c | |
26 | +++ b/drivers/thunderbolt/switch.c | |
baf248c1 | 27 | @@ -2949,22 +2949,29 @@ void tb_switch_unconfigure_link(struct t |
a9af9959 GKH |
28 | { |
29 | struct tb_port *up, *down; | |
30 | ||
31 | - if (sw->is_unplugged) | |
32 | - return; | |
33 | if (!tb_route(sw) || tb_switch_is_icm(sw)) | |
34 | return; | |
35 | ||
36 | + /* | |
37 | + * Unconfigure downstream port so that wake-on-connect can be | |
38 | + * configured after router unplug. No need to unconfigure upstream port | |
39 | + * since its router is unplugged. | |
40 | + */ | |
41 | up = tb_upstream_port(sw); | |
42 | - if (tb_switch_is_usb4(up->sw)) | |
43 | - usb4_port_unconfigure(up); | |
44 | - else | |
45 | - tb_lc_unconfigure_port(up); | |
46 | - | |
47 | down = up->remote; | |
48 | if (tb_switch_is_usb4(down->sw)) | |
49 | usb4_port_unconfigure(down); | |
50 | else | |
51 | tb_lc_unconfigure_port(down); | |
52 | + | |
53 | + if (sw->is_unplugged) | |
54 | + return; | |
55 | + | |
56 | + up = tb_upstream_port(sw); | |
57 | + if (tb_switch_is_usb4(up->sw)) | |
58 | + usb4_port_unconfigure(up); | |
59 | + else | |
60 | + tb_lc_unconfigure_port(up); | |
61 | } | |
62 | ||
63 | static void tb_switch_credits_init(struct tb_switch *sw) |