[03/17] thunderbolt: Make tb_path_alloc() work with tree topologies

Message ID 20200615142645.56209-4-mika.westerberg@linux.intel.com
State New
Headers show
Series
  • Untitled series #39591
Related show

Commit Message

Mika Westerberg June 15, 2020, 2:26 p.m.
With USB4, topologies are not limited to daisy-chains anymore so when
calculating how many hops are between two ports we need to walk the
whole path instead.

Add helper function tb_for_each_port_on_path() that can be used to walk
over each port on a path and make tb_path_alloc() to use it.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/thunderbolt/path.c | 12 ++++++------
 drivers/thunderbolt/tb.h   | 12 ++++++++++++
 2 files changed, 18 insertions(+), 6 deletions(-)

Patch

diff --git a/drivers/thunderbolt/path.c b/drivers/thunderbolt/path.c
index ad58559ea88e..77abb1fa80c0 100644
--- a/drivers/thunderbolt/path.c
+++ b/drivers/thunderbolt/path.c
@@ -239,12 +239,12 @@  struct tb_path *tb_path_alloc(struct tb *tb, struct tb_port *src, int src_hopid,
 	if (!path)
 		return NULL;
 
-	/*
-	 * Number of hops on a path is the distance between the two
-	 * switches plus the source adapter port.
-	 */
-	num_hops = abs(tb_route_length(tb_route(src->sw)) -
-		       tb_route_length(tb_route(dst->sw))) + 1;
+	i = 0;
+	tb_for_each_port_on_path(src, dst, in_port)
+		i++;
+
+	/* Each hop takes two ports */
+	num_hops = i / 2;
 
 	path->hops = kcalloc(num_hops, sizeof(*path->hops), GFP_KERNEL);
 	if (!path->hops) {
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index 2eb2bcd3cca3..6916168e2c76 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -741,6 +741,18 @@  void tb_port_release_out_hopid(struct tb_port *port, int hopid);
 struct tb_port *tb_next_port_on_path(struct tb_port *start, struct tb_port *end,
 				     struct tb_port *prev);
 
+/**
+ * tb_for_each_port_on_path() - Iterate over each port on path
+ * @src: Source port
+ * @dst: Destination port
+ * @p: Port used as iterator
+ *
+ * Walks over each port on path from @src to @dst.
+ */
+#define tb_for_each_port_on_path(src, dst, p)				\
+	for ((p) = tb_next_port_on_path((src), (dst), NULL); (p);	\
+	     (p) = tb_next_port_on_path((src), (dst), (p)))
+
 int tb_switch_find_vse_cap(struct tb_switch *sw, enum tb_switch_vse_cap vsec);
 int tb_switch_find_cap(struct tb_switch *sw, enum tb_switch_cap cap);
 int tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap);