summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2019-08-26 18:19:33 +0300
committerMika Westerberg <mika.westerberg@linux.intel.com>2019-11-02 12:13:31 +0300
commit0d46c08d1ed4f7bb283c7315824f2bfe2c5e0fa9 (patch)
treea25fc8d476d9366ed724567d0f423445452defeb
parent91c0c12080d0f40ee7275485221b06b4e1e289e1 (diff)
downloadlinux-0d46c08d1ed4f7bb283c7315824f2bfe2c5e0fa9.tar.bz2
thunderbolt: Add default linking between lane adapters if not provided by DROM
We currently read how sibling lane adapter ports relate each other from DROM (Device ROM). If the two lane adapter ports go through the same physical connector these lanes can then be bonded together. However, some cases DROM does not provide this information or it is missing completely (host routers typically do not have DROM). In this case we have hard-coded the relationship. Expand this to work with both legacy devices where lane adapter ports 1 and 2, and 3 and 4 are always linked together, and with USB4 devices where lane adapter 1 is always following lane adapter 0 or is disabled completely (see USB4 section 5.2.1 for more information). Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
-rw-r--r--drivers/thunderbolt/eeprom.c11
-rw-r--r--drivers/thunderbolt/switch.c32
2 files changed, 32 insertions, 11 deletions
diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
index ee5196479854..8dd7de0cc826 100644
--- a/drivers/thunderbolt/eeprom.c
+++ b/drivers/thunderbolt/eeprom.c
@@ -514,17 +514,6 @@ int tb_drom_read(struct tb_switch *sw)
* no entries). Hardcode the configuration here.
*/
tb_drom_read_uid_only(sw, &sw->uid);
-
- sw->ports[1].link_nr = 0;
- sw->ports[2].link_nr = 1;
- sw->ports[1].dual_link_port = &sw->ports[2];
- sw->ports[2].dual_link_port = &sw->ports[1];
-
- sw->ports[3].link_nr = 0;
- sw->ports[4].link_nr = 1;
- sw->ports[3].dual_link_port = &sw->ports[4];
- sw->ports[4].dual_link_port = &sw->ports[3];
-
return 0;
}
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 12a63f86820e..205045caabdc 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -1936,6 +1936,36 @@ static int tb_switch_add_dma_port(struct tb_switch *sw)
return -ESHUTDOWN;
}
+static void tb_switch_default_link_ports(struct tb_switch *sw)
+{
+ int i;
+
+ for (i = 1; i <= sw->config.max_port_number; i += 2) {
+ struct tb_port *port = &sw->ports[i];
+ struct tb_port *subordinate;
+
+ if (!tb_port_is_null(port))
+ continue;
+
+ /* Check for the subordinate port */
+ if (i == sw->config.max_port_number ||
+ !tb_port_is_null(&sw->ports[i + 1]))
+ continue;
+
+ /* Link them if not already done so (by DROM) */
+ subordinate = &sw->ports[i + 1];
+ if (!port->dual_link_port && !subordinate->dual_link_port) {
+ port->link_nr = 0;
+ port->dual_link_port = subordinate;
+ subordinate->link_nr = 1;
+ subordinate->dual_link_port = port;
+
+ tb_sw_dbg(sw, "linked ports %d <-> %d\n",
+ port->port, subordinate->port);
+ }
+ }
+}
+
static bool tb_switch_lane_bonding_possible(struct tb_switch *sw)
{
const struct tb_port *up = tb_upstream_port(sw);
@@ -2109,6 +2139,8 @@ int tb_switch_add(struct tb_switch *sw)
}
}
+ tb_switch_default_link_ports(sw);
+
ret = tb_switch_update_link_attributes(sw);
if (ret)
return ret;