From 79fae987518a3aa6c3c7b2e3ad5fe1e4080c12bc Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 9 Feb 2018 17:29:38 +0300 Subject: thunderbolt: Handle connecting device in place of host properly If the system is suspended and user disconnects cable to another host and connects it to a Thunderbolt device instead we get a warning from driver core about adding duplicate sysfs attribute and adding the new device fails. Handle this properly so that we first remove the existing XDomain connection before adding new devices. Fixes: d1ff70241a27 ("thunderbolt: Add support for XDomain discovery protocol") Signed-off-by: Mika Westerberg Reviewed-by: Andy Shevchenko Cc: stable@vger.kernel.org --- drivers/thunderbolt/icm.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'drivers/thunderbolt') diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c index ab02d13f40b7..182226023acb 100644 --- a/drivers/thunderbolt/icm.c +++ b/drivers/thunderbolt/icm.c @@ -383,6 +383,15 @@ static void remove_switch(struct tb_switch *sw) tb_switch_remove(sw); } +static void remove_xdomain(struct tb_xdomain *xd) +{ + struct tb_switch *sw; + + sw = tb_to_switch(xd->dev.parent); + tb_port_at(xd->route, sw)->xdomain = NULL; + tb_xdomain_remove(xd); +} + static void icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) { @@ -391,6 +400,7 @@ icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) struct tb_switch *sw, *parent_sw; struct icm *icm = tb_priv(tb); bool authorized = false; + struct tb_xdomain *xd; u8 link, depth; u64 route; int ret; @@ -467,6 +477,13 @@ icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) tb_switch_put(sw); } + /* Remove existing XDomain connection if found */ + xd = tb_xdomain_find_by_link_depth(tb, link, depth); + if (xd) { + remove_xdomain(xd); + tb_xdomain_put(xd); + } + parent_sw = tb_switch_find_by_link_depth(tb, link, depth - 1); if (!parent_sw) { tb_err(tb, "failed to find parent switch for %u.%u\n", @@ -529,15 +546,6 @@ icm_fr_device_disconnected(struct tb *tb, const struct icm_pkg_header *hdr) tb_switch_put(sw); } -static void remove_xdomain(struct tb_xdomain *xd) -{ - struct tb_switch *sw; - - sw = tb_to_switch(xd->dev.parent); - tb_port_at(xd->route, sw)->xdomain = NULL; - tb_xdomain_remove(xd); -} - static void icm_fr_xdomain_connected(struct tb *tb, const struct icm_pkg_header *hdr) { -- cgit v1.2.3