]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.16.4/thunderbolt-handle-connecting-device-in-place-of-host-properly.patch
fix up queue-5.15/mm-fix-race-between-__split_huge_pmd_locked-and-gup-.patch
[thirdparty/kernel/stable-queue.git] / releases / 4.16.4 / thunderbolt-handle-connecting-device-in-place-of-host-properly.patch
1 From 79fae987518a3aa6c3c7b2e3ad5fe1e4080c12bc Mon Sep 17 00:00:00 2001
2 From: Mika Westerberg <mika.westerberg@linux.intel.com>
3 Date: Fri, 9 Feb 2018 17:29:38 +0300
4 Subject: thunderbolt: Handle connecting device in place of host properly
5
6 From: Mika Westerberg <mika.westerberg@linux.intel.com>
7
8 commit 79fae987518a3aa6c3c7b2e3ad5fe1e4080c12bc upstream.
9
10 If the system is suspended and user disconnects cable to another host
11 and connects it to a Thunderbolt device instead we get a warning from
12 driver core about adding duplicate sysfs attribute and adding the new
13 device fails.
14
15 Handle this properly so that we first remove the existing XDomain
16 connection before adding new devices.
17
18 Fixes: d1ff70241a27 ("thunderbolt: Add support for XDomain discovery protocol")
19 Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
20 Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
21 Cc: stable@vger.kernel.org
22 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
23
24 ---
25 drivers/thunderbolt/icm.c | 26 +++++++++++++++++---------
26 1 file changed, 17 insertions(+), 9 deletions(-)
27
28 --- a/drivers/thunderbolt/icm.c
29 +++ b/drivers/thunderbolt/icm.c
30 @@ -383,6 +383,15 @@ static void remove_switch(struct tb_swit
31 tb_switch_remove(sw);
32 }
33
34 +static void remove_xdomain(struct tb_xdomain *xd)
35 +{
36 + struct tb_switch *sw;
37 +
38 + sw = tb_to_switch(xd->dev.parent);
39 + tb_port_at(xd->route, sw)->xdomain = NULL;
40 + tb_xdomain_remove(xd);
41 +}
42 +
43 static void
44 icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr)
45 {
46 @@ -391,6 +400,7 @@ icm_fr_device_connected(struct tb *tb, c
47 struct tb_switch *sw, *parent_sw;
48 struct icm *icm = tb_priv(tb);
49 bool authorized = false;
50 + struct tb_xdomain *xd;
51 u8 link, depth;
52 u64 route;
53 int ret;
54 @@ -467,6 +477,13 @@ icm_fr_device_connected(struct tb *tb, c
55 tb_switch_put(sw);
56 }
57
58 + /* Remove existing XDomain connection if found */
59 + xd = tb_xdomain_find_by_link_depth(tb, link, depth);
60 + if (xd) {
61 + remove_xdomain(xd);
62 + tb_xdomain_put(xd);
63 + }
64 +
65 parent_sw = tb_switch_find_by_link_depth(tb, link, depth - 1);
66 if (!parent_sw) {
67 tb_err(tb, "failed to find parent switch for %u.%u\n",
68 @@ -529,15 +546,6 @@ icm_fr_device_disconnected(struct tb *tb
69 tb_switch_put(sw);
70 }
71
72 -static void remove_xdomain(struct tb_xdomain *xd)
73 -{
74 - struct tb_switch *sw;
75 -
76 - sw = tb_to_switch(xd->dev.parent);
77 - tb_port_at(xd->route, sw)->xdomain = NULL;
78 - tb_xdomain_remove(xd);
79 -}
80 -
81 static void
82 icm_fr_xdomain_connected(struct tb *tb, const struct icm_pkg_header *hdr)
83 {