[openwrt/openwrt] kernel: phylink: disable autoneg for interfaces that have no inband
LEDE Commits
lede-commits at lists.infradead.org
Sun Jan 4 07:42:56 PST 2026
hauke pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/69d76e3a144f9ad2b613b2d1e0e376c124ffb39f
commit 69d76e3a144f9ad2b613b2d1e0e376c124ffb39f
Author: Hauke Mehrtens <hauke at hauke-m.de>
AuthorDate: Thu Jan 1 19:31:48 2026 +0100
kernel: phylink: disable autoneg for interfaces that have no inband
This patch fixes a bug in a patch we backported.
This patch was cherry picked from upstream Linux because it references a
patch we backported in the fixes tag.
The first two patches are providing function needed by the last patch.
Fixes: 813ecda1f387 ("generic: backport phylink patches for PCS/PHY caps OPs")
Link: https://github.com/openwrt/openwrt/pull/21366
Signed-off-by: Hauke Mehrtens <hauke at hauke-m.de>
---
...-08-net-phylink-add-.pcs_link_down-PCS-OP.patch | 2 +-
...01-v6.17-net-phy-add-phy_interface_weight.patch | 27 +++++
...t-phylink-provide-phylink_get_inband_type.patch | 117 +++++++++++++++++++++
...-disable-autoneg-for-interfaces-that-have.patch | 68 ++++++++++++
...support-active-high-property-for-PHY-LEDs.patch | 2 +-
...y-pass-PHY-driver-to-.match_phy_device-OP.patch | 2 +-
...net-phy-introduce-genphy_match_phy_device.patch | 2 +-
...roduce-phy_id_compare_vendor-PHY-ID-helpe.patch | 4 +-
...-add-detach-callback-to-struct-phy_driver.patch | 2 +-
...pulate-host_interfaces-when-attaching-PHY.patch | 4 +-
.../702-phy-Add-2.5G-SGMII-interface-mode.patch | 2 +-
.../720-NET-no-auto-carrier-off-support.patch | 2 +-
...io-increase-max-ports-for-rtl839x-rtl931x.patch | 4 +-
13 files changed, 225 insertions(+), 13 deletions(-)
diff --git a/target/linux/airoha/patches-6.12/116-08-net-phylink-add-.pcs_link_down-PCS-OP.patch b/target/linux/airoha/patches-6.12/116-08-net-phylink-add-.pcs_link_down-PCS-OP.patch
index 7f5dcc7bd3..34e8d21ebd 100644
--- a/target/linux/airoha/patches-6.12/116-08-net-phylink-add-.pcs_link_down-PCS-OP.patch
+++ b/target/linux/airoha/patches-6.12/116-08-net-phylink-add-.pcs_link_down-PCS-OP.patch
@@ -35,7 +35,7 @@ Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
static void phylink_pcs_poll_stop(struct phylink *pl)
{
if (pl->cfg_link_an_mode == MLO_AN_INBAND)
-@@ -1642,6 +1648,8 @@ static void phylink_link_down(struct phy
+@@ -1651,6 +1657,8 @@ static void phylink_link_down(struct phy
if (ndev)
netif_carrier_off(ndev);
diff --git a/target/linux/generic/backport-6.12/605-01-v6.17-net-phy-add-phy_interface_weight.patch b/target/linux/generic/backport-6.12/605-01-v6.17-net-phy-add-phy_interface_weight.patch
new file mode 100644
index 0000000000..3a09a23703
--- /dev/null
+++ b/target/linux/generic/backport-6.12/605-01-v6.17-net-phy-add-phy_interface_weight.patch
@@ -0,0 +1,27 @@
+From 4beb44a2d62dddfe450f310aa1a950901731cb3a Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Sun, 31 Aug 2025 18:34:33 +0100
+Subject: net: phy: add phy_interface_weight()
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Reviewed-by: Andrew Lunn <andrew at lunn.ch>
+Link: https://patch.msgid.link/E1uslwn-00000001SOx-0a7H@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ include/linux/phy.h | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -187,6 +187,11 @@ static inline bool phy_interface_empty(c
+ return bitmap_empty(intf, PHY_INTERFACE_MODE_MAX);
+ }
+
++static inline unsigned int phy_interface_weight(const unsigned long *intf)
++{
++ return bitmap_weight(intf, PHY_INTERFACE_MODE_MAX);
++}
++
+ static inline void phy_interface_and(unsigned long *dst, const unsigned long *a,
+ const unsigned long *b)
+ {
diff --git a/target/linux/generic/backport-6.12/605-02-v6.17-net-phylink-provide-phylink_get_inband_type.patch b/target/linux/generic/backport-6.12/605-02-v6.17-net-phylink-provide-phylink_get_inband_type.patch
new file mode 100644
index 0000000000..e944f573e0
--- /dev/null
+++ b/target/linux/generic/backport-6.12/605-02-v6.17-net-phylink-provide-phylink_get_inband_type.patch
@@ -0,0 +1,117 @@
+From 1bd905dfea9897eafef532000702e63a66849f54 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Sun, 31 Aug 2025 18:34:38 +0100
+Subject: net: phylink: provide phylink_get_inband_type()
+
+Provide a function to get the type of the inband signalling used for
+a PHY interface type. This will be used in the subsequent patch to
+address problems with 10G optical modules.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Reviewed-by: Andrew Lunn <andrew at lunn.ch>
+Link: https://patch.msgid.link/E1uslws-00000001SP5-1R2R@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/phy/phylink.c | 79 ++++++++++++++++++++++-----------------
+ 1 file changed, 44 insertions(+), 35 deletions(-)
+
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -1147,6 +1147,42 @@ static void phylink_pcs_an_restart(struc
+ pl->pcs->ops->pcs_an_restart(pl->pcs);
+ }
+
++enum inband_type {
++ INBAND_NONE,
++ INBAND_CISCO_SGMII,
++ INBAND_BASEX,
++};
++
++static enum inband_type phylink_get_inband_type(phy_interface_t interface)
++{
++ switch (interface) {
++ case PHY_INTERFACE_MODE_SGMII:
++ case PHY_INTERFACE_MODE_QSGMII:
++ case PHY_INTERFACE_MODE_QUSGMII:
++ case PHY_INTERFACE_MODE_USXGMII:
++ case PHY_INTERFACE_MODE_10G_QXGMII:
++ /* These protocols are designed for use with a PHY which
++ * communicates its negotiation result back to the MAC via
++ * inband communication. Note: there exist PHYs that run
++ * with SGMII but do not send the inband data.
++ */
++ return INBAND_CISCO_SGMII;
++
++ case PHY_INTERFACE_MODE_1000BASEX:
++ case PHY_INTERFACE_MODE_2500BASEX:
++ /* 1000base-X is designed for use media-side for Fibre
++ * connections, and thus the Autoneg bit needs to be
++ * taken into account. We also do this for 2500base-X
++ * as well, but drivers may not support this, so may
++ * need to override this.
++ */
++ return INBAND_BASEX;
++
++ default:
++ return INBAND_NONE;
++ }
++}
++
+ /**
+ * phylink_pcs_neg_mode() - helper to determine PCS inband mode
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+@@ -1174,46 +1210,19 @@ static void phylink_pcs_neg_mode(struct
+ unsigned int pcs_ib_caps = 0;
+ unsigned int phy_ib_caps = 0;
+ unsigned int neg_mode, mode;
+- enum {
+- INBAND_CISCO_SGMII,
+- INBAND_BASEX,
+- } type;
+-
+- mode = pl->req_link_an_mode;
++ enum inband_type type;
+
+- pl->phy_ib_mode = 0;
+-
+- switch (interface) {
+- case PHY_INTERFACE_MODE_SGMII:
+- case PHY_INTERFACE_MODE_QSGMII:
+- case PHY_INTERFACE_MODE_QUSGMII:
+- case PHY_INTERFACE_MODE_USXGMII:
+- case PHY_INTERFACE_MODE_10G_QXGMII:
+- /* These protocols are designed for use with a PHY which
+- * communicates its negotiation result back to the MAC via
+- * inband communication. Note: there exist PHYs that run
+- * with SGMII but do not send the inband data.
+- */
+- type = INBAND_CISCO_SGMII;
+- break;
+-
+- case PHY_INTERFACE_MODE_1000BASEX:
+- case PHY_INTERFACE_MODE_2500BASEX:
+- /* 1000base-X is designed for use media-side for Fibre
+- * connections, and thus the Autoneg bit needs to be
+- * taken into account. We also do this for 2500base-X
+- * as well, but drivers may not support this, so may
+- * need to override this.
+- */
+- type = INBAND_BASEX;
+- break;
+-
+- default:
++ type = phylink_get_inband_type(interface);
++ if (type == INBAND_NONE) {
+ pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE;
+- pl->act_link_an_mode = mode;
++ pl->act_link_an_mode = pl->req_link_an_mode;
+ return;
+ }
+
++ mode = pl->req_link_an_mode;
++
++ pl->phy_ib_mode = 0;
++
+ if (pcs)
+ pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface);
+
diff --git a/target/linux/generic/backport-6.12/605-03-v6.17-net-phylink-disable-autoneg-for-interfaces-that-have.patch b/target/linux/generic/backport-6.12/605-03-v6.17-net-phylink-disable-autoneg-for-interfaces-that-have.patch
new file mode 100644
index 0000000000..0861bb820d
--- /dev/null
+++ b/target/linux/generic/backport-6.12/605-03-v6.17-net-phylink-disable-autoneg-for-interfaces-that-have.patch
@@ -0,0 +1,68 @@
+From a21202743f9ce4063e86b99cccaef48ef9813379 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Sun, 31 Aug 2025 18:34:43 +0100
+Subject: net: phylink: disable autoneg for interfaces that have no inband
+
+Mathew reports that as a result of commit 6561f0e547be ("net: pcs:
+pcs-lynx: implement pcs_inband_caps() method"), 10G SFP modules no
+longer work with the Lynx PCS.
+
+This problem is not specific to the Lynx PCS, but is caused by commit
+df874f9e52c3 ("net: phylink: add pcs_inband_caps() method") which added
+validation of the autoneg state to the optical SFP configuration path.
+
+Fix this by handling interface modes that fundamentally have no
+inband negotiation more correctly - if we only have a single interface
+mode, clear the Autoneg support bit and the advertising mask. If the
+module can operate with several different interface modes, autoneg may
+be supported for other modes, so leave the support mask alone and just
+clear the Autoneg bit in the advertising mask.
+
+This restores 10G optical module functionality with PCS that supply
+their inband support, and makes ethtool output look sane.
+
+Reported-by: Mathew McBride <matt at traverse.com.au>
+Closes: https://lore.kernel.org/r/025c0ebe-5537-4fa3-b05a-8b835e5ad317@app.fastmail.com
+Fixes: df874f9e52c3 ("net: phylink: add pcs_inband_caps() method")
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Tested-by: Vladimir Oltean <vladimir.oltean at nxp.com>
+Link: https://patch.msgid.link/E1uslwx-00000001SPB-2kiM@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/phy/phylink.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -3500,6 +3500,7 @@ static int phylink_sfp_config_optical(st
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(support);
+ DECLARE_PHY_INTERFACE_MASK(interfaces);
+ struct phylink_link_state config;
++ enum inband_type inband_type;
+ phy_interface_t interface;
+ int ret;
+
+@@ -3546,6 +3547,23 @@ static int phylink_sfp_config_optical(st
+ phylink_dbg(pl, "optical SFP: chosen %s interface\n",
+ phy_modes(interface));
+
++ inband_type = phylink_get_inband_type(interface);
++ if (inband_type == INBAND_NONE) {
++ /* If this is the sole interface, and there is no inband
++ * support, clear the advertising mask and Autoneg bit in
++ * the support mask. Otherwise, just clear the Autoneg bit
++ * in the advertising mask.
++ */
++ if (phy_interface_weight(pl->sfp_interfaces) == 1) {
++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
++ pl->sfp_support);
++ linkmode_zero(config.advertising);
++ } else {
++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
++ config.advertising);
++ }
++ }
++
+ if (!phylink_validate_pcs_inband_autoneg(pl, interface,
+ config.advertising)) {
+ phylink_err(pl, "autoneg setting not compatible with PCS");
diff --git a/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch b/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch
index 5563f3dce6..d30159b377 100644
--- a/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch
+++ b/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch
@@ -39,7 +39,7 @@ Signed-off-by: Paolo Abeni <pabeni at redhat.com>
if (!phydev->drv->led_polarity_set)
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
-@@ -892,8 +892,9 @@ struct phy_plca_status {
+@@ -897,8 +897,9 @@ struct phy_plca_status {
/* Modes for PHY LED configuration */
enum phy_led_modes {
diff --git a/target/linux/generic/backport-6.12/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch b/target/linux/generic/backport-6.12/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch
index d2b20cc8a5..2e8ab284f7 100644
--- a/target/linux/generic/backport-6.12/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch
+++ b/target/linux/generic/backport-6.12/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch
@@ -281,7 +281,7 @@ Signed-off-by: Jakub Kicinski <kuba at kernel.org>
}
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
-@@ -1035,7 +1035,8 @@ struct phy_driver {
+@@ -1040,7 +1040,8 @@ struct phy_driver {
* driver for the given phydev. If NULL, matching is based on
* phy_id and phy_id_mask.
*/
diff --git a/target/linux/generic/backport-6.12/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch b/target/linux/generic/backport-6.12/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch
index dd24ba2370..190f68c980 100644
--- a/target/linux/generic/backport-6.12/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch
+++ b/target/linux/generic/backport-6.12/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch
@@ -97,7 +97,7 @@ Signed-off-by: Jakub Kicinski <kuba at kernel.org>
static ssize_t
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
-@@ -1940,6 +1940,9 @@ char *phy_attached_info_irq(struct phy_d
+@@ -1945,6 +1945,9 @@ char *phy_attached_info_irq(struct phy_d
__malloc;
void phy_attached_info(struct phy_device *phydev);
diff --git a/target/linux/generic/backport-6.12/786-01-v6.18-net-phy-introduce-phy_id_compare_vendor-PHY-ID-helpe.patch b/target/linux/generic/backport-6.12/786-01-v6.18-net-phy-introduce-phy_id_compare_vendor-PHY-ID-helpe.patch
index cf74512958..8172afc40c 100644
--- a/target/linux/generic/backport-6.12/786-01-v6.18-net-phy-introduce-phy_id_compare_vendor-PHY-ID-helpe.patch
+++ b/target/linux/generic/backport-6.12/786-01-v6.18-net-phy-introduce-phy_id_compare_vendor-PHY-ID-helpe.patch
@@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski <kuba at kernel.org>
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
-@@ -1256,9 +1256,13 @@ struct phy_driver {
+@@ -1261,9 +1261,13 @@ struct phy_driver {
#define PHY_ANY_ID "MATCH ANY PHY"
#define PHY_ANY_UID 0xffffffff
@@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski <kuba at kernel.org>
/**
* phy_id_compare - compare @id1 with @id2 taking account of @mask
-@@ -1275,6 +1279,19 @@ static inline bool phy_id_compare(u32 id
+@@ -1280,6 +1284,19 @@ static inline bool phy_id_compare(u32 id
}
/**
diff --git a/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch
index f8bcf6744f..4a2b7d0f4e 100644
--- a/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch
+++ b/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch
@@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos <juhosg at openwrt.org>
sysfs_remove_link(&dev->dev.kobj, "phydev");
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
-@@ -1027,6 +1027,12 @@ struct phy_driver {
+@@ -1032,6 +1032,12 @@ struct phy_driver {
/** @handle_interrupt: Override default interrupt handling */
irqreturn_t (*handle_interrupt)(struct phy_device *phydev);
diff --git a/target/linux/generic/pending-6.12/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch b/target/linux/generic/pending-6.12/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch
index 0af507eed3..dea84c7079 100644
--- a/target/linux/generic/pending-6.12/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch
+++ b/target/linux/generic/pending-6.12/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch
@@ -20,7 +20,7 @@ Signed-off-by: Daniel Golle <daniel at makrotopia.org>
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
-@@ -2264,7 +2264,7 @@ int phylink_fwnode_phy_connect(struct ph
+@@ -2273,7 +2273,7 @@ int phylink_fwnode_phy_connect(struct ph
{
struct fwnode_handle *phy_fwnode;
struct phy_device *phy_dev;
@@ -29,7 +29,7 @@ Signed-off-by: Daniel Golle <daniel at makrotopia.org>
/* Fixed links and 802.3z are handled without needing a PHY */
if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
-@@ -2294,6 +2294,25 @@ int phylink_fwnode_phy_connect(struct ph
+@@ -2303,6 +2303,25 @@ int phylink_fwnode_phy_connect(struct ph
if (pl->config->mac_requires_rxc)
flags |= PHY_F_RXC_ALWAYS_ON;
diff --git a/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch b/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch
index af14871b59..20d06924e9 100644
--- a/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch
+++ b/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch
@@ -62,7 +62,7 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya at nxp.com>
PHY_INTERFACE_MODE_MAX,
} phy_interface_t;
-@@ -235,6 +236,8 @@ static inline const char *phy_modes(phy_
+@@ -240,6 +241,8 @@ static inline const char *phy_modes(phy_
return "gmii";
case PHY_INTERFACE_MODE_SGMII:
return "sgmii";
diff --git a/target/linux/ramips/patches-6.12/720-NET-no-auto-carrier-off-support.patch b/target/linux/ramips/patches-6.12/720-NET-no-auto-carrier-off-support.patch
index 68c6888332..25c823931e 100644
--- a/target/linux/ramips/patches-6.12/720-NET-no-auto-carrier-off-support.patch
+++ b/target/linux/ramips/patches-6.12/720-NET-no-auto-carrier-off-support.patch
@@ -21,7 +21,7 @@ Signed-off-by: John Crispin <blogic at openwrt.org>
if (phydev->mii_ts && phydev->mii_ts->link_state)
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
-@@ -675,6 +675,7 @@ struct phy_device {
+@@ -680,6 +680,7 @@ struct phy_device {
unsigned downshifted_rate:1;
unsigned is_on_sfp_module:1;
unsigned mac_managed_pm:1;
diff --git a/target/linux/realtek/patches-6.12/700-dsa-mdio-increase-max-ports-for-rtl839x-rtl931x.patch b/target/linux/realtek/patches-6.12/700-dsa-mdio-increase-max-ports-for-rtl839x-rtl931x.patch
index f299716abc..3431715c63 100644
--- a/target/linux/realtek/patches-6.12/700-dsa-mdio-increase-max-ports-for-rtl839x-rtl931x.patch
+++ b/target/linux/realtek/patches-6.12/700-dsa-mdio-increase-max-ports-for-rtl839x-rtl931x.patch
@@ -35,7 +35,7 @@ Signed-off-by: Markus Stockhausen <markus.stockhausen at gmx.de>
&phy->mdio.reset_assert_delay);
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
-@@ -301,7 +301,7 @@ static inline const char *phy_modes(phy_
+@@ -306,7 +306,7 @@ static inline const char *phy_modes(phy_
#define PHY_INIT_TIMEOUT 100000
#define PHY_FORCE_TIMEOUT 10
@@ -44,7 +44,7 @@ Signed-off-by: Markus Stockhausen <markus.stockhausen at gmx.de>
/* Used when trying to connect to a specific phy (mii bus id:phy device id) */
#define PHY_ID_FMT "%s:%02x"
-@@ -421,10 +421,10 @@ struct mii_bus {
+@@ -426,10 +426,10 @@ struct mii_bus {
struct mdio_device *mdio_map[PHY_MAX_ADDR];
/** @phy_mask: PHY addresses to be ignored when probing */
More information about the lede-commits
mailing list