aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/thunderbolt/lc.c6
-rw-r--r--drivers/thunderbolt/switch.c55
-rw-r--r--drivers/thunderbolt/tb.c5
-rw-r--r--drivers/thunderbolt/tb.h2
-rw-r--r--drivers/thunderbolt/usb4.c6
5 files changed, 49 insertions, 25 deletions
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;
@@ -2315,6 +2307,48 @@ void tb_switch_lane_bonding_disable(struct tb_switch *sw)
}
/**
+ * 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);
}