[openwrt/openwrt] kernel: net: phy: mxl-gpy: replace downstream SGMII AN hack

LEDE Commits lede-commits at lists.infradead.org
Fri Jan 9 08:11:08 PST 2026


dangole pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/e5812c7a8c3c5e1cfc2971836f4f04c4038a91ed

commit e5812c7a8c3c5e1cfc2971836f4f04c4038a91ed
Author: Daniel Golle <daniel at makrotopia.org>
AuthorDate: Wed Jan 7 15:41:17 2026 +0000

    kernel: net: phy: mxl-gpy: replace downstream SGMII AN hack
    
    Replace downstream hack disabling SGMII in-band AN on the MediaTek platform
    with pending upstream patch announcing in-band AN capabilities and implementing
    configuring in-band AN in the PHY driver.
    
    Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
 ...-gpy-fix-link-properties-on-USXGMII-and-i.patch |  56 +++++++
 ...net-phy-mxl-gpy-add-support-for-MxL86211C.patch |  64 +++++++
 ...id-undefined-behavior-in-_led_polarity_se.patch |   2 +-
 ...-gpy-implement-SGMII-in-band-configuratio.patch | 185 +++++++++++++++++++++
 ...l-gpy-don-t-use-SGMII-AN-if-using-phylink.patch |  63 -------
 5 files changed, 306 insertions(+), 64 deletions(-)

diff --git a/target/linux/generic/backport-6.12/730-09-v6.18-net-phy-mxl-gpy-fix-link-properties-on-USXGMII-and-i.patch b/target/linux/generic/backport-6.12/730-09-v6.18-net-phy-mxl-gpy-fix-link-properties-on-USXGMII-and-i.patch
new file mode 100644
index 0000000000..6f3bbfcc0e
--- /dev/null
+++ b/target/linux/generic/backport-6.12/730-09-v6.18-net-phy-mxl-gpy-fix-link-properties-on-USXGMII-and-i.patch
@@ -0,0 +1,56 @@
+From 081156ce13f8fa4e97b5148dc54d8c0ddf02117b Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel at makrotopia.org>
+Date: Thu, 20 Nov 2025 15:02:19 +0000
+Subject: [PATCH] net: phy: mxl-gpy: fix link properties on USXGMII and
+ internal PHYs
+
+gpy_update_interface() returns early in case the PHY is internal or
+connected via USXGMII. In this case the gigabit master/slave property
+as well as MDI/MDI-X status also won't be read which seems wrong.
+Always read those properties by moving the logic to retrieve them to
+gpy_read_status().
+
+Fixes: fd8825cd8c6fc ("net: phy: mxl-gpy: Add PHY Auto/MDI/MDI-X set driver for GPY211 chips")
+Fixes: 311abcdddc00a ("net: phy: add support to get Master-Slave configuration")
+Suggested-by: "Russell King (Oracle)" <linux at armlinux.org.uk>
+Signed-off-by: Daniel Golle <daniel at makrotopia.org>
+Link: https://patch.msgid.link/71fccf3f56742116eb18cc070d2a9810479ea7f9.1763650701.git.daniel@makrotopia.org
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ drivers/net/phy/mxl-gpy.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/phy/mxl-gpy.c
++++ b/drivers/net/phy/mxl-gpy.c
+@@ -584,13 +584,7 @@ static int gpy_update_interface(struct p
+ 		break;
+ 	}
+ 
+-	if (phydev->speed == SPEED_2500 || phydev->speed == SPEED_1000) {
+-		ret = genphy_read_master_slave(phydev);
+-		if (ret < 0)
+-			return ret;
+-	}
+-
+-	return gpy_update_mdix(phydev);
++	return 0;
+ }
+ 
+ static int gpy_read_status(struct phy_device *phydev)
+@@ -645,6 +639,16 @@ static int gpy_read_status(struct phy_de
+ 		ret = gpy_update_interface(phydev);
+ 		if (ret < 0)
+ 			return ret;
++
++		if (phydev->speed == SPEED_2500 || phydev->speed == SPEED_1000) {
++			ret = genphy_read_master_slave(phydev);
++			if (ret < 0)
++				return ret;
++		}
++
++		ret = gpy_update_mdix(phydev);
++		if (ret < 0)
++			return ret;
+ 	}
+ 
+ 	return 0;
diff --git a/target/linux/generic/backport-6.12/730-10-v6.19-net-phy-mxl-gpy-add-support-for-MxL86211C.patch b/target/linux/generic/backport-6.12/730-10-v6.19-net-phy-mxl-gpy-add-support-for-MxL86211C.patch
new file mode 100644
index 0000000000..77073377c9
--- /dev/null
+++ b/target/linux/generic/backport-6.12/730-10-v6.19-net-phy-mxl-gpy-add-support-for-MxL86211C.patch
@@ -0,0 +1,64 @@
+From 9d844da693d6d0813714d9b5b7a58ac05c4cf7f0 Mon Sep 17 00:00:00 2001
+From: Chad Monroe <chad at monroe.io>
+Date: Sat, 22 Nov 2025 13:32:15 +0000
+Subject: [PATCH] net: phy: mxl-gpy: add support for MxL86211C
+
+MxL86211C is a smaller and more efficient version of the GPY211C.
+Add the PHY ID and phy_driver instance to the mxl-gpy driver.
+
+Signed-off-by: Chad Monroe <chad at monroe.io>
+Signed-off-by: Daniel Golle <daniel at makrotopia.org>
+Reviewed-by: Andrew Lunn <andrew at lunn.ch>
+Link: https://patch.msgid.link/cabf3559d6511bed6b8a925f540e3162efc20f6b.1763818120.git.daniel@makrotopia.org
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/phy/mxl-gpy.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+--- a/drivers/net/phy/mxl-gpy.c
++++ b/drivers/net/phy/mxl-gpy.c
+@@ -30,6 +30,7 @@
+ #define PHY_ID_GPY241B		0x67C9DE40
+ #define PHY_ID_GPY241BM		0x67C9DE80
+ #define PHY_ID_GPY245B		0x67C9DEC0
++#define PHY_ID_MXL86211C	0xC1335400
+ 
+ #define PHY_CTL1		0x13
+ #define PHY_CTL1_MDICD		BIT(3)
+@@ -1275,6 +1276,28 @@ static struct phy_driver gpy_drivers[] =
+ 		.get_wol	= gpy_get_wol,
+ 		.set_loopback	= gpy_loopback,
+ 	},
++	{
++		PHY_ID_MATCH_MODEL(PHY_ID_MXL86211C),
++		.name		= "Maxlinear Ethernet MxL86211C",
++		.get_features	= genphy_c45_pma_read_abilities,
++		.config_init	= gpy_config_init,
++		.probe		= gpy_probe,
++		.suspend	= genphy_suspend,
++		.resume		= genphy_resume,
++		.config_aneg	= gpy_config_aneg,
++		.aneg_done	= genphy_c45_aneg_done,
++		.read_status	= gpy_read_status,
++		.config_intr	= gpy_config_intr,
++		.handle_interrupt = gpy_handle_interrupt,
++		.set_wol	= gpy_set_wol,
++		.get_wol	= gpy_get_wol,
++		.set_loopback	= gpy_loopback,
++		.led_brightness_set = gpy_led_brightness_set,
++		.led_hw_is_supported = gpy_led_hw_is_supported,
++		.led_hw_control_get = gpy_led_hw_control_get,
++		.led_hw_control_set = gpy_led_hw_control_set,
++		.led_polarity_set = gpy_led_polarity_set,
++	},
+ };
+ module_phy_driver(gpy_drivers);
+ 
+@@ -1291,6 +1314,7 @@ static const struct mdio_device_id __may
+ 	{PHY_ID_MATCH_MODEL(PHY_ID_GPY241B)},
+ 	{PHY_ID_MATCH_MODEL(PHY_ID_GPY241BM)},
+ 	{PHY_ID_MATCH_MODEL(PHY_ID_GPY245B)},
++	{PHY_ID_MATCH_MODEL(PHY_ID_MXL86211C)},
+ 	{ }
+ };
+ MODULE_DEVICE_TABLE(mdio, gpy_tbl);
diff --git a/target/linux/generic/backport-6.12/735-v6.13-net-phy-avoid-undefined-behavior-in-_led_polarity_se.patch b/target/linux/generic/backport-6.12/735-v6.13-net-phy-avoid-undefined-behavior-in-_led_polarity_se.patch
index 7a1553ae28..48f531d709 100644
--- a/target/linux/generic/backport-6.12/735-v6.13-net-phy-avoid-undefined-behavior-in-_led_polarity_se.patch
+++ b/target/linux/generic/backport-6.12/735-v6.13-net-phy-avoid-undefined-behavior-in-_led_polarity_se.patch
@@ -53,7 +53,7 @@ Signed-off-by: Jakub Kicinski <kuba at kernel.org>
  static struct phy_driver xway_gphy[] = {
 --- a/drivers/net/phy/mxl-gpy.c
 +++ b/drivers/net/phy/mxl-gpy.c
-@@ -1014,7 +1014,7 @@ static int gpy_led_polarity_set(struct p
+@@ -1019,7 +1019,7 @@ static int gpy_led_polarity_set(struct p
  	if (force_active_high)
  		return phy_clear_bits(phydev, PHY_LED, PHY_LED_POLARITY(index));
  
diff --git a/target/linux/generic/pending-6.12/721-net-phy-mxl-gpy-implement-SGMII-in-band-configuratio.patch b/target/linux/generic/pending-6.12/721-net-phy-mxl-gpy-implement-SGMII-in-band-configuratio.patch
new file mode 100644
index 0000000000..8d4d2dc6cc
--- /dev/null
+++ b/target/linux/generic/pending-6.12/721-net-phy-mxl-gpy-implement-SGMII-in-band-configuratio.patch
@@ -0,0 +1,185 @@
+From aaf0094daf0d7a0e4599280341710c98ba1e9d35 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel at makrotopia.org>
+Date: Wed, 7 Jan 2026 13:48:16 +0000
+Subject: [PATCH] net: phy: mxl-gpy: implement SGMII in-band configuration
+
+SGMII in-band autonegotiation was previously kept untouched (and restored
+after switching back from 2500Base-X to SGMII). Now that the kernel offers
+a way to announce in-band capabilities and enable/disable in-band AN,
+implement the .inband_caps and .config_inband driver ops.
+This moves the responsibility to configure SGMII in-band AN from the PHY
+driver to phylink.
+
+Signed-off-by: Daniel Golle <daniel at makrotopia.org>
+---
+ drivers/net/phy/mxl-gpy.c | 61 ++++++++++++++++++++++++++++++---------
+ 1 file changed, 47 insertions(+), 14 deletions(-)
+
+--- a/drivers/net/phy/mxl-gpy.c
++++ b/drivers/net/phy/mxl-gpy.c
+@@ -568,20 +568,6 @@ static int gpy_update_interface(struct p
+ 	case SPEED_100:
+ 	case SPEED_10:
+ 		phydev->interface = PHY_INTERFACE_MODE_SGMII;
+-		if (gpy_sgmii_aneg_en(phydev))
+-			break;
+-		/* Enable and restart SGMII ANEG for 10/100/1000Mbps link speed
+-		 * if ANEG is disabled (in 2500-BaseX mode).
+-		 */
+-		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
+-				     VSPEC1_SGMII_ANEN_ANRS,
+-				     VSPEC1_SGMII_ANEN_ANRS);
+-		if (ret < 0) {
+-			phydev_err(phydev,
+-				   "Error: Enable of SGMII ANEG failed: %d\n",
+-				   ret);
+-			return ret;
+-		}
+ 		break;
+ 	}
+ 
+@@ -1022,6 +1008,27 @@ static int gpy_led_polarity_set(struct p
+ 	return -EINVAL;
+ }
+ 
++static unsigned int gpy_inband_caps(struct phy_device *phydev,
++				    phy_interface_t interface)
++{
++	switch (interface) {
++	case PHY_INTERFACE_MODE_SGMII:
++		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
++	case PHY_INTERFACE_MODE_2500BASEX:
++		return LINK_INBAND_DISABLE;
++	default:
++		return 0;
++	}
++}
++
++static int gpy_config_inband(struct phy_device *phydev, unsigned int modes)
++{
++	return phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
++			      VSPEC1_SGMII_ANEN_ANRS,
++			      (modes == LINK_INBAND_DISABLE) ? 0 :
++			      VSPEC1_SGMII_ANEN_ANRS);
++}
++
+ static struct phy_driver gpy_drivers[] = {
+ 	{
+ 		PHY_ID_MATCH_MODEL(PHY_ID_GPY2xx),
+@@ -1029,6 +1036,8 @@ static struct phy_driver gpy_drivers[] =
+ 		.get_features	= genphy_c45_pma_read_abilities,
+ 		.config_init	= gpy_config_init,
+ 		.probe		= gpy_probe,
++		.inband_caps	= gpy_inband_caps,
++		.config_inband	= gpy_config_inband,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
+ 		.config_aneg	= gpy_config_aneg,
+@@ -1052,6 +1061,8 @@ static struct phy_driver gpy_drivers[] =
+ 		.get_features	= genphy_c45_pma_read_abilities,
+ 		.config_init	= gpy_config_init,
+ 		.probe		= gpy_probe,
++		.inband_caps	= gpy_inband_caps,
++		.config_inband	= gpy_config_inband,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
+ 		.config_aneg	= gpy_config_aneg,
+@@ -1074,6 +1085,8 @@ static struct phy_driver gpy_drivers[] =
+ 		.get_features	= genphy_c45_pma_read_abilities,
+ 		.config_init	= gpy_config_init,
+ 		.probe		= gpy_probe,
++		.inband_caps	= gpy_inband_caps,
++		.config_inband	= gpy_config_inband,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
+ 		.config_aneg	= gpy_config_aneg,
+@@ -1097,6 +1110,8 @@ static struct phy_driver gpy_drivers[] =
+ 		.get_features	= genphy_c45_pma_read_abilities,
+ 		.config_init	= gpy21x_config_init,
+ 		.probe		= gpy_probe,
++		.inband_caps	= gpy_inband_caps,
++		.config_inband	= gpy_config_inband,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
+ 		.config_aneg	= gpy_config_aneg,
+@@ -1119,6 +1134,8 @@ static struct phy_driver gpy_drivers[] =
+ 		.get_features	= genphy_c45_pma_read_abilities,
+ 		.config_init	= gpy21x_config_init,
+ 		.probe		= gpy_probe,
++		.inband_caps	= gpy_inband_caps,
++		.config_inband	= gpy_config_inband,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
+ 		.config_aneg	= gpy_config_aneg,
+@@ -1141,6 +1158,8 @@ static struct phy_driver gpy_drivers[] =
+ 		.name		= "Maxlinear Ethernet GPY212B",
+ 		.get_features	= genphy_c45_pma_read_abilities,
+ 		.config_init	= gpy21x_config_init,
++		.inband_caps	= gpy_inband_caps,
++		.config_inband	= gpy_config_inband,
+ 		.probe		= gpy_probe,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
+@@ -1164,6 +1183,8 @@ static struct phy_driver gpy_drivers[] =
+ 		.get_features	= genphy_c45_pma_read_abilities,
+ 		.config_init	= gpy21x_config_init,
+ 		.probe		= gpy_probe,
++		.inband_caps	= gpy_inband_caps,
++		.config_inband	= gpy_config_inband,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
+ 		.config_aneg	= gpy_config_aneg,
+@@ -1187,6 +1208,8 @@ static struct phy_driver gpy_drivers[] =
+ 		.get_features	= genphy_c45_pma_read_abilities,
+ 		.config_init	= gpy21x_config_init,
+ 		.probe		= gpy_probe,
++		.inband_caps	= gpy_inband_caps,
++		.config_inband	= gpy_config_inband,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
+ 		.config_aneg	= gpy_config_aneg,
+@@ -1209,6 +1232,8 @@ static struct phy_driver gpy_drivers[] =
+ 		.get_features	= genphy_c45_pma_read_abilities,
+ 		.config_init	= gpy21x_config_init,
+ 		.probe		= gpy_probe,
++		.inband_caps	= gpy_inband_caps,
++		.config_inband	= gpy_config_inband,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
+ 		.config_aneg	= gpy_config_aneg,
+@@ -1231,6 +1256,8 @@ static struct phy_driver gpy_drivers[] =
+ 		.get_features	= genphy_c45_pma_read_abilities,
+ 		.config_init	= gpy_config_init,
+ 		.probe		= gpy_probe,
++		.inband_caps	= gpy_inband_caps,
++		.config_inband	= gpy_config_inband,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
+ 		.config_aneg	= gpy_config_aneg,
+@@ -1248,6 +1275,8 @@ static struct phy_driver gpy_drivers[] =
+ 		.get_features	= genphy_c45_pma_read_abilities,
+ 		.config_init	= gpy_config_init,
+ 		.probe		= gpy_probe,
++		.inband_caps	= gpy_inband_caps,
++		.config_inband	= gpy_config_inband,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
+ 		.config_aneg	= gpy_config_aneg,
+@@ -1265,6 +1294,8 @@ static struct phy_driver gpy_drivers[] =
+ 		.get_features	= genphy_c45_pma_read_abilities,
+ 		.config_init	= gpy_config_init,
+ 		.probe		= gpy_probe,
++		.inband_caps	= gpy_inband_caps,
++		.config_inband	= gpy_config_inband,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
+ 		.config_aneg	= gpy_config_aneg,
+@@ -1282,6 +1313,8 @@ static struct phy_driver gpy_drivers[] =
+ 		.get_features	= genphy_c45_pma_read_abilities,
+ 		.config_init	= gpy_config_init,
+ 		.probe		= gpy_probe,
++		.inband_caps	= gpy_inband_caps,
++		.config_inband	= gpy_config_inband,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
+ 		.config_aneg	= gpy_config_aneg,
diff --git a/target/linux/mediatek/patches-6.12/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch b/target/linux/mediatek/patches-6.12/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch
deleted file mode 100644
index d1ac132ac5..0000000000
--- a/target/linux/mediatek/patches-6.12/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-From a969b663c866129ed9eb217785a6574fbe826f1d Mon Sep 17 00:00:00 2001
-From: Daniel Golle <daniel at makrotopia.org>
-Date: Thu, 6 Apr 2023 23:36:50 +0100
-Subject: [PATCH] net: phy: mxl-gpy: don't use SGMII AN if using phylink
-
-MAC drivers using phylink expect SGMII in-band-status to be switched off
-when attached to a PHY. Make sure this is the case also for mxl-gpy which
-keeps SGMII in-band-status in case of SGMII interface mode is used.
-
-Signed-off-by: Daniel Golle <daniel at makrotopia.org>
----
- drivers/net/phy/mxl-gpy.c | 19 ++++++++++++++++---
- 1 file changed, 16 insertions(+), 3 deletions(-)
-
---- a/drivers/net/phy/mxl-gpy.c
-+++ b/drivers/net/phy/mxl-gpy.c
-@@ -380,8 +380,11 @@ static bool gpy_2500basex_chk(struct phy
- 
- 	phydev->speed = SPEED_2500;
- 	phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
--	phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
--		       VSPEC1_SGMII_CTRL_ANEN, 0);
-+
-+	if (!phydev->phylink)
-+		phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
-+			       VSPEC1_SGMII_CTRL_ANEN, 0);
-+
- 	return true;
- }
- 
-@@ -432,6 +435,14 @@ static int gpy_config_aneg(struct phy_de
- 	u32 adv;
- 	int ret;
- 
-+	/* Disable SGMII auto-negotiation if using phylink */
-+	if (phydev->phylink) {
-+		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
-+				     VSPEC1_SGMII_CTRL_ANEN, 0);
-+		if (ret < 0)
-+			return ret;
-+	}
-+
- 	if (phydev->autoneg == AUTONEG_DISABLE) {
- 		/* Configure half duplex with genphy_setup_forced,
- 		 * because genphy_c45_pma_setup_forced does not support.
-@@ -554,6 +565,8 @@ static int gpy_update_interface(struct p
- 	switch (phydev->speed) {
- 	case SPEED_2500:
- 		phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
-+		if (phydev->phylink)
-+			break;
- 		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
- 				     VSPEC1_SGMII_CTRL_ANEN, 0);
- 		if (ret < 0) {
-@@ -567,7 +580,7 @@ static int gpy_update_interface(struct p
- 	case SPEED_100:
- 	case SPEED_10:
- 		phydev->interface = PHY_INTERFACE_MODE_SGMII;
--		if (gpy_sgmii_aneg_en(phydev))
-+		if (phydev->phylink || gpy_sgmii_aneg_en(phydev))
- 			break;
- 		/* Enable and restart SGMII ANEG for 10/100/1000Mbps link speed
- 		 * if ANEG is disabled (in 2500-BaseX mode).




More information about the lede-commits mailing list