Linux kernel -stable discussions
 help / color / mirror / Atom feed
From: Gil Fine <gil.fine@linux.intel.com>
To: mika.westerberg@linux.intel.com
Cc: gil.fine@intel.com, gil.fine@linux.intel.com, stable@vger.kernel.org
Subject: [PATCH v2 3/3] thunderbolt: Fix credits reservation logic for DisplayPort tunnels
Date: Thu, 17 Sep 2026 01:57:55 +0300	[thread overview]
Message-ID: <20260916225755.45127-3-gil.fine@linux.intel.com> (raw)
In-Reply-To: <20260916225755.45127-1-gil.fine@linux.intel.com>

Currently we reserve lane adapter credits for as many DisplayPort
streams as the leftover credits allow, after USB3, PCIe and the DMA
reserve (which only covers one full DMA tunnel plus a minimal second
one). This is wasteful in practice as no known host router exposes more
than three DP IN adapters.

As multiple DMA tunnels become more common (as is topology below), these
unused DisplayPort credits can be used for additional DMA tunnels.

Take for example the following topology, where the links from the hub to
Host2, Host3, and Host4 are inter-domain links carrying DMA tunnels:

          --- Domain 1 ---
          [Host1: USB4 v1]
                 |
                 |
         [Hub:   USB4 v2]
         /       |        \
        /        |         \
   --Domain2-- --Domain3-- --Domain4--
       |         |            |
   [Host2]     [Host3]      [Host4]
   USB4v1      USB4v1       USB4v1

On the USB4 v2 hub upstream facing lane adapter with credits:
Total 160, control path = 2, USB3 = 20, PCIe = 76, 7 credits per
DisplayPort stream, DMA = 14 + 1, reserving the full six possible
DisplayPort streams is calculated as:
(160 - 2 - 20 - 76 - 14 - 1) / 7 = 47 / 7 = 6 => Six DisplayPort
streams.

This leaves only 20 credits for DMA - one full tunnel (14) plus a
reduced-throughput one (6), which is not optimal.

Fix this by limiting the reservation to TB_DP_RESERVED_STREAMS (3), or
the number of DP IN adapters above the lane adapter, whichever is lower.
Beyond these reserved DisplayPort streams, remaining credits for
DisplayPort and DMA tunnels are allocated on a first-come, first-served
basis.

With the reservation now limited to three streams instead of six, 21
credits are freed, giving DMA 41 credits, enough for three DMA tunnels
(14 + 14 + 13).

Fixes: 6ed541c53edc ("thunderbolt: Allocate credits according to router preferences")
Cc: stable@vger.kernel.org
Signed-off-by: Gil Fine <gil.fine@linux.intel.com>
Assisted-by: LLM
---
 drivers/thunderbolt/tunnel.c | 41 +++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c
index 0625b1ff3820..f7e9d58de2f7 100644
--- a/drivers/thunderbolt/tunnel.c
+++ b/drivers/thunderbolt/tunnel.c
@@ -85,6 +85,9 @@
 /* Minimum number of credits for DMA path */
 #define TB_MIN_DMA_CREDITS		1
 
+/* Number of DP tunnels we reserve credits for in advance */
+#define TB_DP_RESERVED_STREAMS		3
+
 #define TB_DMA_PRIORITY			5
 #define TB_DMA_WEIGHT			1
 
@@ -156,6 +159,22 @@ static inline unsigned int tb_usable_credits(const struct tb_port *port)
 	return port->total_credits - port->ctl_credits;
 }
 
+static unsigned int tb_dp_in_count(struct tb_switch *sw)
+{
+	unsigned int count = 0;
+
+	while (sw) {
+		const struct tb_port *p;
+
+		tb_switch_for_each_port(sw, p)
+			if (tb_port_is_dpin(p))
+				count++;
+		sw = tb_switch_parent(sw);
+	}
+
+	return count;
+}
+
 /**
  * tb_available_credits() - Available credits for PCIe and DMA
  * @port: Lane adapter to check
@@ -167,9 +186,9 @@ static inline unsigned int tb_usable_credits(const struct tb_port *port)
 static unsigned int tb_available_credits(const struct tb_port *port,
 					 size_t *max_dp_streams)
 {
-	const struct tb_switch *sw = port->sw;
+	struct tb_switch *sw = port->sw;
 	int credits, usb3, pcie, spare;
-	size_t ndp;
+	size_t ndp, reserved;
 
 	usb3 = tb_acpi_may_tunnel_usb3() ? sw->max_usb3_genx_credits : 0;
 	pcie = tb_acpi_may_tunnel_pcie() ? sw->max_pcie_credits : 0;
@@ -197,7 +216,23 @@ static unsigned int tb_available_credits(const struct tb_port *port,
 	} else {
 		ndp = 0;
 	}
-	credits -= ndp * (sw->min_dp_aux_credits + sw->min_dp_main_credits);
+
+	reserved = min(TB_DP_RESERVED_STREAMS, ndp);
+
+	/*
+	 * The only real use case is a downstream directed DP tunnel, so reserve
+	 * AUX + main video on the upstream facing adapter and only AUX on the
+	 * downstream facing one. Don't reserve more than the number of DP IN
+	 * adapters above the current lane adapter.
+	 */
+	if (tb_is_upstream_port(port)) {
+		reserved = min(reserved, tb_dp_in_count(tb_switch_parent(sw)));
+		credits -= reserved *
+			   (sw->min_dp_aux_credits + sw->min_dp_main_credits);
+	} else {
+		reserved = min(reserved, tb_dp_in_count(sw));
+		credits -= reserved * sw->min_dp_aux_credits;
+	}
 	credits -= usb3;
 
 	if (max_dp_streams)
-- 
2.43.0


      parent reply	other threads:[~2026-09-16 22:52 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-16 22:57 [PATCH v2 1/3] thunderbolt: Do not set up a DisplayPort tunnel when credits are insufficient Gil Fine
2026-09-16 22:57 ` [PATCH v2 2/3] thunderbolt: Fix DMA credit limit to use host router value Gil Fine
2026-09-17  6:19   ` Mika Westerberg
2026-09-16 22:57 ` Gil Fine [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260916225755.45127-3-gil.fine@linux.intel.com \
    --to=gil.fine@linux.intel.com \
    --cc=gil.fine@intel.com \
    --cc=mika.westerberg@linux.intel.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox