diff mbox series

[RFC,07/22] thunderbolt: Add default linking between ports if not provided by DROM

Message ID 20191001113830.13028-8-mika.westerberg@linux.intel.com (mailing list archive)
State Superseded
Headers show
Series thunderbolt: Add support for USB4 | expand

Commit Message

Mika Westerberg Oct. 1, 2019, 11:38 a.m. UTC
Some cases the DROM information is not correct or is simply missing.
This prevents establishing lane bonding even if it would be possible
otherwise. To make this work better provide default linking between
ports if DROM has not provided that information.

This works with legacy devices where ports 1 and 2, and 3 and 4 are
linked together and also with USB4.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/thunderbolt/eeprom.c | 11 -----------
 drivers/thunderbolt/switch.c | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 11 deletions(-)

Comments

Greg Kroah-Hartman Oct. 1, 2019, 12:39 p.m. UTC | #1
On Tue, Oct 01, 2019 at 02:38:15PM +0300, Mika Westerberg wrote:
> Some cases the DROM information is not correct or is simply missing.

What is "DROM"?

> This prevents establishing lane bonding even if it would be possible
> otherwise. To make this work better provide default linking between
> ports if DROM has not provided that information.
> 
> This works with legacy devices where ports 1 and 2, and 3 and 4 are
> linked together and also with USB4.

"linked together" as in "bonded"?  Or something else?  Names are getting
confusing here :(

thanks,

greg k-h
Mika Westerberg Oct. 1, 2019, 1:14 p.m. UTC | #2
On Tue, Oct 01, 2019 at 02:39:11PM +0200, Greg Kroah-Hartman wrote:
> On Tue, Oct 01, 2019 at 02:38:15PM +0300, Mika Westerberg wrote:
> > Some cases the DROM information is not correct or is simply missing.
> 
> What is "DROM"?

It is "Device ROM". Essentially per-device information. I will spell it
out in next version.

> > This prevents establishing lane bonding even if it would be possible
> > otherwise. To make this work better provide default linking between
> > ports if DROM has not provided that information.
> > 
> > This works with legacy devices where ports 1 and 2, and 3 and 4 are
> > linked together and also with USB4.
> 
> "linked together" as in "bonded"?  Or something else?  Names are getting
> confusing here :(

Here linked together means the both port in dual link so ports 1, 2 and
ports 3 and 4. There are always two pairs of ports (lanes) that go out
of physical connector. Here we just link them in software. I'll try to
clarify this in the next version.
diff mbox series

Patch

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 2b00ea7a979a..f7547287be68 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -1904,6 +1904,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);
@@ -2071,6 +2101,8 @@  int tb_switch_add(struct tb_switch *sw)
 				return ret;
 		}
 
+		tb_switch_default_link_ports(sw);
+
 		ret = tb_switch_update_link_attributes(sw);
 		if (ret)
 			return ret;