aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-4.19/950-0749-net-bcmgenet-Workaround-for-Pi-4B-network-issue.patch
blob: 7cb26f10d3a1dfadba07cc4a88d7f89fa86d0d9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
From 29109f495f5842f4e9a09ffb54ae3e13298fff07 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Fri, 2 Aug 2019 22:25:27 +0100
Subject: [PATCH 749/773] net: bcmgenet: Workaround for Pi 4B network issue

Some combinations of Pi 4Bs and Ethernet switches don't reliably get a
DCHP-assigned IP address, leaving the unit with a self=assigned 169.254
address.

Forcing renegotiation has been found to be an effective workaround, so
add an automatic renegotiation after the link comes up for the first
time; enable it with genet.force_reneg=y - by default it is disabled.

See: https://github.com/raspberrypi/linux/issues/3108

Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
 .../net/ethernet/broadcom/genet/bcmgenet.c    | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -72,6 +72,10 @@
 #define GENET_RDMA_REG_OFF	(priv->hw_params->rdma_offset + \
 				TOTAL_DESC * DMA_DESC_SIZE)
 
+static bool force_reneg = false;
+module_param(force_reneg, bool, 0444);
+MODULE_PARM_DESC(force_reneg, "Force a renegotiation after the initial link-up");
+
 static inline void bcmgenet_writel(u32 value, void __iomem *offset)
 {
 	/* MIPS chips strapped for BE will automagically configure the
@@ -2610,6 +2614,7 @@ static void bcmgenet_irq_task(struct wor
 	unsigned int status;
 	struct bcmgenet_priv *priv = container_of(
 			work, struct bcmgenet_priv, bcmgenet_irq_work);
+	static int first_link = 1;
 
 	netif_dbg(priv, intr, priv->dev, "%s\n", __func__);
 
@@ -2622,6 +2627,23 @@ static void bcmgenet_irq_task(struct wor
 	if (status & UMAC_IRQ_LINK_EVENT) {
 		priv->dev->phydev->link = !!(status & UMAC_IRQ_LINK_UP);
 		phy_mac_interrupt(priv->dev->phydev);
+
+		if (priv->dev->phydev->link && first_link) {
+			first_link = 0;
+			/*
+			 * HACK: Some Pi4Bs, when paired with some switches,
+			 * come up in a strange state where they are unable to
+			 * transmit, causing them to fail to get an IP address.
+			 * Although the failure mechanism is not yet understood,
+			 * forcing renegotiation at this point has been shown
+			 * to be effective in avoiding the problem.
+			 */
+			if (force_reneg) {
+				dev_info(&priv->pdev->dev,
+					 "Forcing renegotiation\n");
+				genphy_restart_aneg(priv->dev->phydev);
+			}
+		}
 	}
 }