From: Daniel Golle Date: Wed, 7 Jan 2026 15:41:17 +0000 (+0000) Subject: kernel: net: phy: mxl-gpy: replace downstream SGMII AN hack X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=e5812c7a8c3c5e1cfc2971836f4f04c4038a91ed;p=openwrt%2Fopenwrt.git 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 --- 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 +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)" +Signed-off-by: Daniel Golle +Link: https://patch.msgid.link/71fccf3f56742116eb18cc070d2a9810479ea7f9.1763650701.git.daniel@makrotopia.org +Signed-off-by: Paolo Abeni +--- + 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 +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 +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/cabf3559d6511bed6b8a925f540e3162efc20f6b.1763818120.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + 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 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 +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 +--- + 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 -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 ---- - 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).