diff --git a/drivers/thunderbolt/lc.c b/drivers/thunderbolt/lc.c index 19be627d090f..b2f62ba0421d 100644 --- a/drivers/thunderbolt/lc.c +++ b/drivers/thunderbolt/lc.c @@ -94,9 +94,6 @@ int tb_lc_configure_link(struct tb_switch *sw) struct tb_port *up, *down; int ret; - if (!tb_route(sw) || tb_switch_is_icm(sw)) - return 0; - up = tb_upstream_port(sw); down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent)); @@ -124,9 +121,6 @@ void tb_lc_unconfigure_link(struct tb_switch *sw) { struct tb_port *up, *down; - if (sw->is_unplugged || !tb_route(sw) || tb_switch_is_icm(sw)) - return; - up = tb_upstream_port(sw); down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent)); diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 02f981ee88e9..5d99d69107eb 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -2011,10 +2011,6 @@ int tb_switch_configure(struct tb_switch *sw) return ret; ret = usb4_switch_setup(sw); - if (ret) - return ret; - - ret = usb4_switch_configure_link(sw); } else { if (sw->config.vendor_id != PCI_VENDOR_ID_INTEL) tb_sw_warn(sw, "unknown switch vendor id %#x\n", @@ -2028,10 +2024,6 @@ int tb_switch_configure(struct tb_switch *sw) /* Enumerate the switch */ ret = tb_sw_write(sw, (u32 *)&sw->config + 1, TB_CFG_SWITCH, ROUTER_CS_1, 3); - if (ret) - return ret; - - ret = tb_lc_configure_link(sw); } if (ret) return ret; @@ -2314,6 +2306,48 @@ void tb_switch_lane_bonding_disable(struct tb_switch *sw) tb_sw_dbg(sw, "lane bonding disabled\n"); } +/** + * tb_switch_configure_link() - Set link configured + * @sw: Switch whose link is configured + * + * Sets the link upstream from @sw configured (from both ends) so that + * it will not be disconnected when the domain exits sleep. Can be + * called for any switch. + * + * It is recommended that this is called after lane bonding is enabled. + * + * Returns %0 on success and negative errno in case of error. + */ +int tb_switch_configure_link(struct tb_switch *sw) +{ + if (!tb_route(sw) || tb_switch_is_icm(sw)) + return 0; + + if (tb_switch_is_usb4(sw)) + return usb4_switch_configure_link(sw); + return tb_lc_configure_link(sw); +} + +/** + * tb_switch_unconfigure_link() - Unconfigure link + * @sw: Switch whose link is unconfigured + * + * Sets the link unconfigured so the @sw will be disconnected if the + * domain exists sleep. + */ +void tb_switch_unconfigure_link(struct tb_switch *sw) +{ + if (sw->is_unplugged) + return; + if (!tb_route(sw) || tb_switch_is_icm(sw)) + return; + + if (tb_switch_is_usb4(sw)) + usb4_switch_unconfigure_link(sw); + else + tb_lc_unconfigure_link(sw); +} + /** * tb_switch_add() - Add a switch to the domain * @sw: Switch to add @@ -2448,11 +2482,6 @@ void tb_switch_remove(struct tb_switch *sw) if (!sw->is_unplugged) tb_plug_events_active(sw, false); - if (tb_switch_is_usb4(sw)) - usb4_switch_unconfigure_link(sw); - else - tb_lc_unconfigure_link(sw); - tb_switch_nvm_remove(sw); if (tb_route(sw)) diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index c35d5fec48f4..54a4daf0b1b4 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -593,6 +593,8 @@ static void tb_scan_port(struct tb_port *port) /* Enable lane bonding if supported */ tb_switch_lane_bonding_enable(sw); + /* Set the link configured */ + tb_switch_configure_link(sw); if (tb_enable_tmu(sw)) tb_sw_warn(sw, "failed to enable TMU\n"); @@ -681,6 +683,7 @@ static void tb_free_unplugged_children(struct tb_switch *sw) if (port->remote->sw->is_unplugged) { tb_retimer_remove_all(port); tb_remove_dp_resources(port->remote->sw); + tb_switch_unconfigure_link(port->remote->sw); tb_switch_lane_bonding_disable(port->remote->sw); tb_switch_remove(port->remote->sw); port->remote = NULL; @@ -1076,6 +1079,7 @@ static void tb_handle_hotplug(struct work_struct *work) tb_free_invalid_tunnels(tb); tb_remove_dp_resources(port->remote->sw); tb_switch_tmu_disable(port->remote->sw); + tb_switch_unconfigure_link(port->remote->sw); tb_switch_lane_bonding_disable(port->remote->sw); tb_switch_remove(port->remote->sw); port->remote = NULL; @@ -1269,6 +1273,7 @@ static void tb_restore_children(struct tb_switch *sw) continue; tb_switch_lane_bonding_enable(port->remote->sw); + tb_switch_configure_link(port->remote->sw); tb_restore_children(port->remote->sw); } diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index b16d290690f3..4f7f3b44af00 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -767,6 +767,8 @@ static inline bool tb_switch_is_icm(const struct tb_switch *sw) int tb_switch_lane_bonding_enable(struct tb_switch *sw); void tb_switch_lane_bonding_disable(struct tb_switch *sw); +int tb_switch_configure_link(struct tb_switch *sw); +void tb_switch_unconfigure_link(struct tb_switch *sw); bool tb_switch_query_dp_resource(struct tb_switch *sw, struct tb_port *in); int tb_switch_alloc_dp_resource(struct tb_switch *sw, struct tb_port *in); diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index 2b8355e6b65f..dd601a6db23c 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -368,9 +368,6 @@ int usb4_switch_configure_link(struct tb_switch *sw) { struct tb_port *up; - if (!tb_route(sw)) - return 0; - up = tb_upstream_port(sw); return usb4_set_port_configured(up, true); } @@ -385,9 +382,6 @@ void usb4_switch_unconfigure_link(struct tb_switch *sw) { struct tb_port *up; - if (sw->is_unplugged || !tb_route(sw)) - return; - up = tb_upstream_port(sw); usb4_set_port_configured(up, false); }