backport thunderbolt-net fixes
A user of ours reported an issue with p2p thunderbolt-net w.r.t. IPv6
and failure to reestablish the connection after a reboot of a peer
node, in the forum [0] and the relayed it upstream, so lets
cherry-pick those two patches to our 6.2. Especially the IPv6 one
seems straight forward, and the other one makes it actually spec
conform and should only improve things.
[0]: https://forum.proxmox.com/threads/133104/
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
(cherry picked from commit ddba52024f)
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
			
			
This commit is contained in:
		
							parent
							
								
									31a20e1eb0
								
							
						
					
					
						commit
						0d7e7de56f
					
				@ -0,0 +1,42 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Mika Westerberg <mika.westerberg@linux.intel.com>
 | 
			
		||||
Date: Wed, 13 Sep 2023 08:26:47 +0300
 | 
			
		||||
Subject: [PATCH] net: thunderbolt: Fix TCPv6 GSO checksum calculation
 | 
			
		||||
 | 
			
		||||
Alex reported that running ssh over IPv6 does not work with
 | 
			
		||||
Thunderbolt/USB4 networking driver. The reason for that is that driver
 | 
			
		||||
should call skb_is_gso() before calling skb_is_gso_v6(), and it should
 | 
			
		||||
not return false after calculates the checksum successfully. This probably
 | 
			
		||||
was a copy paste error from the original driver where it was done properly.
 | 
			
		||||
 | 
			
		||||
Reported-by: Alex Balcanquall <alex@alexbal.com>
 | 
			
		||||
Fixes: e69b6c02b4c3 ("net: Add support for networking over Thunderbolt cable")
 | 
			
		||||
Cc: stable@vger.kernel.org
 | 
			
		||||
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
 | 
			
		||||
Reviewed-by: Eric Dumazet <edumazet@google.com>
 | 
			
		||||
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
 | 
			
		||||
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
 | 
			
		||||
Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
			
		||||
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/thunderbolt.c | 3 +--
 | 
			
		||||
 1 file changed, 1 insertion(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt.c
 | 
			
		||||
index 990484776f2d..0c554a7a5ce4 100644
 | 
			
		||||
--- a/drivers/net/thunderbolt.c
 | 
			
		||||
+++ b/drivers/net/thunderbolt.c
 | 
			
		||||
@@ -1005,12 +1005,11 @@ static bool tbnet_xmit_csum_and_map(struct tbnet *net, struct sk_buff *skb,
 | 
			
		||||
 		*tucso = ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
 | 
			
		||||
 					    ip_hdr(skb)->daddr, 0,
 | 
			
		||||
 					    ip_hdr(skb)->protocol, 0);
 | 
			
		||||
-	} else if (skb_is_gso_v6(skb)) {
 | 
			
		||||
+	} else if (skb_is_gso(skb) && skb_is_gso_v6(skb)) {
 | 
			
		||||
 		tucso = dest + ((void *)&(tcp_hdr(skb)->check) - data);
 | 
			
		||||
 		*tucso = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
 | 
			
		||||
 					  &ipv6_hdr(skb)->daddr, 0,
 | 
			
		||||
 					  IPPROTO_TCP, 0);
 | 
			
		||||
-		return false;
 | 
			
		||||
 	} else if (protocol == htons(ETH_P_IPV6)) {
 | 
			
		||||
 		tucso = dest + skb_checksum_start_offset(skb) + skb->csum_offset;
 | 
			
		||||
 		*tucso = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
 | 
			
		||||
@ -0,0 +1,134 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Mika Westerberg <mika.westerberg@linux.intel.com>
 | 
			
		||||
Date: Thu, 7 Sep 2023 16:02:30 +0300
 | 
			
		||||
Subject: [PATCH] thunderbolt: Restart XDomain discovery handshake after
 | 
			
		||||
 failure
 | 
			
		||||
 | 
			
		||||
Alex reported that after rebooting the other host the peer-to-peer link
 | 
			
		||||
does not come up anymore. The reason for this is that the host that was
 | 
			
		||||
not rebooted tries to send the UUID request only 10 times according to
 | 
			
		||||
the USB4 Inter-Domain spec and gives up if it does not get reply. Then
 | 
			
		||||
when the other side is actually ready it cannot get the link established
 | 
			
		||||
anymore. The USB4 Inter-Domain spec requires that the discovery protocol
 | 
			
		||||
is restarted in that case so implement this now.
 | 
			
		||||
 | 
			
		||||
Reported-by: Alex Balcanquall <alex@alexbal.com>
 | 
			
		||||
Fixes: 8e1de7042596 ("thunderbolt: Add support for XDomain lane bonding")
 | 
			
		||||
Cc: stable@vger.kernel.org
 | 
			
		||||
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
 | 
			
		||||
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/thunderbolt/xdomain.c | 58 +++++++++++++++++++++++++----------
 | 
			
		||||
 1 file changed, 41 insertions(+), 17 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c
 | 
			
		||||
index 3c51e47dd86b..0b17a4d4e9b9 100644
 | 
			
		||||
--- a/drivers/thunderbolt/xdomain.c
 | 
			
		||||
+++ b/drivers/thunderbolt/xdomain.c
 | 
			
		||||
@@ -704,6 +704,27 @@ static void update_property_block(struct tb_xdomain *xd)
 | 
			
		||||
 	mutex_unlock(&xdomain_lock);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static void start_handshake(struct tb_xdomain *xd)
 | 
			
		||||
+{
 | 
			
		||||
+	xd->state = XDOMAIN_STATE_INIT;
 | 
			
		||||
+	queue_delayed_work(xd->tb->wq, &xd->state_work,
 | 
			
		||||
+			   msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+/* Can be called from state_work */
 | 
			
		||||
+static void __stop_handshake(struct tb_xdomain *xd)
 | 
			
		||||
+{
 | 
			
		||||
+	cancel_delayed_work_sync(&xd->properties_changed_work);
 | 
			
		||||
+	xd->properties_changed_retries = 0;
 | 
			
		||||
+	xd->state_retries = 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void stop_handshake(struct tb_xdomain *xd)
 | 
			
		||||
+{
 | 
			
		||||
+	cancel_delayed_work_sync(&xd->state_work);
 | 
			
		||||
+	__stop_handshake(xd);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void tb_xdp_handle_request(struct work_struct *work)
 | 
			
		||||
 {
 | 
			
		||||
 	struct xdomain_request_work *xw = container_of(work, typeof(*xw), work);
 | 
			
		||||
@@ -766,6 +787,15 @@ static void tb_xdp_handle_request(struct work_struct *work)
 | 
			
		||||
 	case UUID_REQUEST:
 | 
			
		||||
 		tb_dbg(tb, "%llx: received XDomain UUID request\n", route);
 | 
			
		||||
 		ret = tb_xdp_uuid_response(ctl, route, sequence, uuid);
 | 
			
		||||
+		/*
 | 
			
		||||
+		 * If we've stopped the discovery with an error such as
 | 
			
		||||
+		 * timing out, we will restart the handshake now that we
 | 
			
		||||
+		 * received UUID request from the remote host.
 | 
			
		||||
+		 */
 | 
			
		||||
+		if (!ret && xd && xd->state == XDOMAIN_STATE_ERROR) {
 | 
			
		||||
+			dev_dbg(&xd->dev, "restarting handshake\n");
 | 
			
		||||
+			start_handshake(xd);
 | 
			
		||||
+		}
 | 
			
		||||
 		break;
 | 
			
		||||
 
 | 
			
		||||
 	case LINK_STATE_STATUS_REQUEST:
 | 
			
		||||
@@ -1522,6 +1552,13 @@ static void tb_xdomain_queue_properties_changed(struct tb_xdomain *xd)
 | 
			
		||||
 			   msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static void tb_xdomain_failed(struct tb_xdomain *xd)
 | 
			
		||||
+{
 | 
			
		||||
+	xd->state = XDOMAIN_STATE_ERROR;
 | 
			
		||||
+	queue_delayed_work(xd->tb->wq, &xd->state_work,
 | 
			
		||||
+			   msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void tb_xdomain_state_work(struct work_struct *work)
 | 
			
		||||
 {
 | 
			
		||||
 	struct tb_xdomain *xd = container_of(work, typeof(*xd), state_work.work);
 | 
			
		||||
@@ -1548,7 +1585,7 @@ static void tb_xdomain_state_work(struct work_struct *work)
 | 
			
		||||
 		if (ret) {
 | 
			
		||||
 			if (ret == -EAGAIN)
 | 
			
		||||
 				goto retry_state;
 | 
			
		||||
-			xd->state = XDOMAIN_STATE_ERROR;
 | 
			
		||||
+			tb_xdomain_failed(xd);
 | 
			
		||||
 		} else {
 | 
			
		||||
 			tb_xdomain_queue_properties_changed(xd);
 | 
			
		||||
 			if (xd->bonding_possible)
 | 
			
		||||
@@ -1613,7 +1650,7 @@ static void tb_xdomain_state_work(struct work_struct *work)
 | 
			
		||||
 		if (ret) {
 | 
			
		||||
 			if (ret == -EAGAIN)
 | 
			
		||||
 				goto retry_state;
 | 
			
		||||
-			xd->state = XDOMAIN_STATE_ERROR;
 | 
			
		||||
+			tb_xdomain_failed(xd);
 | 
			
		||||
 		} else {
 | 
			
		||||
 			xd->state = XDOMAIN_STATE_ENUMERATED;
 | 
			
		||||
 		}
 | 
			
		||||
@@ -1624,6 +1661,8 @@ static void tb_xdomain_state_work(struct work_struct *work)
 | 
			
		||||
 		break;
 | 
			
		||||
 
 | 
			
		||||
 	case XDOMAIN_STATE_ERROR:
 | 
			
		||||
+		dev_dbg(&xd->dev, "discovery failed, stopping handshake\n");
 | 
			
		||||
+		__stop_handshake(xd);
 | 
			
		||||
 		break;
 | 
			
		||||
 
 | 
			
		||||
 	default:
 | 
			
		||||
@@ -1793,21 +1832,6 @@ static void tb_xdomain_release(struct device *dev)
 | 
			
		||||
 	kfree(xd);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static void start_handshake(struct tb_xdomain *xd)
 | 
			
		||||
-{
 | 
			
		||||
-	xd->state = XDOMAIN_STATE_INIT;
 | 
			
		||||
-	queue_delayed_work(xd->tb->wq, &xd->state_work,
 | 
			
		||||
-			   msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
 | 
			
		||||
-}
 | 
			
		||||
-
 | 
			
		||||
-static void stop_handshake(struct tb_xdomain *xd)
 | 
			
		||||
-{
 | 
			
		||||
-	cancel_delayed_work_sync(&xd->properties_changed_work);
 | 
			
		||||
-	cancel_delayed_work_sync(&xd->state_work);
 | 
			
		||||
-	xd->properties_changed_retries = 0;
 | 
			
		||||
-	xd->state_retries = 0;
 | 
			
		||||
-}
 | 
			
		||||
-
 | 
			
		||||
 static int __maybe_unused tb_xdomain_suspend(struct device *dev)
 | 
			
		||||
 {
 | 
			
		||||
 	stop_handshake(tb_to_xdomain(dev));
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user