From 056166710543a01ebcf25449bb462388e44b6ef6 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Thu, 5 Feb 2026 10:23:04 +0100 Subject: [PATCH 1/3] net: phy: initialize the port support based on the PHY's for OF ports With the phy_port infrastructure came an ethernet-connector binding, allowing to represent the MDI of a PHY in devicetree. This allows specifying the mediums and pairs of a port. Let's initialize the port's supported list based on what the PHY reports, so that we can then filter it with what the connector allows using. Signed-off-by: Maxime Chevallier Reviewed-by: Christophe Leroy (CS GROUP) Link: https://patch.msgid.link/20260205092317.755906-2-maxime.chevallier@bootlin.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/phy_device.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 8a3eb1839a3d..9b8eaac63b90 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -3499,6 +3499,9 @@ static int of_phy_ports(struct phy_device *phydev) port->parent_type = PHY_PORT_PHY; port->phy = phydev; + + linkmode_copy(port->supported, phydev->supported); + err = phy_add_port(phydev, port); if (err) { phy_port_destroy(port); From 6248f3dc4ec536163bf8e1761f3c08d6f31c3cfe Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Thu, 5 Feb 2026 10:23:05 +0100 Subject: [PATCH 2/3] net: phy: phy_port: Cleanup the of-parsing logic for phy_port We don't need to maintain a mediums bitfield, let's drop it and drop a bogus check for empty mediums, as we already check it above. Signed-off-by: Maxime Chevallier Reviewed-by: Christophe Leroy (CS GROUP) Link: https://patch.msgid.link/20260205092317.755906-3-maxime.chevallier@bootlin.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/phy_port.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/net/phy/phy_port.c b/drivers/net/phy/phy_port.c index ec93c8ca051e..a269e9ea12c4 100644 --- a/drivers/net/phy/phy_port.c +++ b/drivers/net/phy/phy_port.c @@ -53,7 +53,7 @@ struct phy_port *phy_of_parse_port(struct device_node *dn) enum ethtool_link_medium medium; struct phy_port *port; const char *med_str; - u32 pairs = 0, mediums = 0; + u32 pairs = 0; int ret; ret = fwnode_property_read_string(fwnode, "media", &med_str); @@ -85,17 +85,12 @@ struct phy_port *phy_of_parse_port(struct device_node *dn) return ERR_PTR(-EINVAL); } - mediums |= BIT(medium); - - if (!mediums) - return ERR_PTR(-EINVAL); - port = phy_port_alloc(); if (!port) return ERR_PTR(-ENOMEM); port->pairs = pairs; - port->mediums = mediums; + port->mediums = BIT(medium); return port; } From 4cebb26ac6f02b49b8a7c6974af3b4f23685e1a2 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Thu, 5 Feb 2026 10:23:06 +0100 Subject: [PATCH 3/3] net: phy: phy_port: Correctly recompute the port's linkmodes a PHY-driven phy_port contains a 'supported' field containing the linkmodes available on this port. This is populated based on : - The PHY's reported features - The DT representation of the connector - The PHY's attach_mdi() callback As these different attrbution methods work in conjunction, the helper phy_port_update_supported() recomputes the final 'supported' value based on the populated mediums, linkmodes and pairs. However this recompute wasn't correctly implemented, and added more modes than necessary by or'ing the medium-specific modes to the existing support. Let's fix this and properly filter the modes. Fixes: 589e934d2735 ("net: phy: Introduce PHY ports representation") Signed-off-by: Maxime Chevallier Reviewed-by: Christophe Leroy (CS GROUP) Link: https://patch.msgid.link/20260205092317.755906-4-maxime.chevallier@bootlin.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/phy_port.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/net/phy/phy_port.c b/drivers/net/phy/phy_port.c index a269e9ea12c4..63d1bb154dc7 100644 --- a/drivers/net/phy/phy_port.c +++ b/drivers/net/phy/phy_port.c @@ -108,16 +108,10 @@ EXPORT_SYMBOL_GPL(phy_of_parse_port); */ void phy_port_update_supported(struct phy_port *port) { - __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0 }; + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = {0}; unsigned long mode; int i; - for_each_set_bit(i, &port->mediums, __ETHTOOL_LINK_MEDIUM_LAST) { - linkmode_zero(supported); - phy_caps_medium_get_supported(supported, i, port->pairs); - linkmode_or(port->supported, port->supported, supported); - } - /* If there's no pairs specified, we grab the default number of * pairs as the max of the default pairs for each linkmode */ @@ -127,6 +121,22 @@ void phy_port_update_supported(struct phy_port *port) port->pairs = max_t(int, port->pairs, ethtool_linkmode_n_pairs(mode)); + for_each_set_bit(i, &port->mediums, __ETHTOOL_LINK_MEDIUM_LAST) { + __ETHTOOL_DECLARE_LINK_MODE_MASK(med_supported) = {0}; + + phy_caps_medium_get_supported(med_supported, i, port->pairs); + linkmode_or(supported, supported, med_supported); + } + + /* If port->supported is already populated, filter it out with the + * medium/pair support. Otherwise, let's just use this medium-based + * support as the port's supported list. + */ + if (linkmode_empty(port->supported)) + linkmode_copy(port->supported, supported); + else + linkmode_and(port->supported, supported, port->supported); + /* Serdes ports supported through SFP may not have any medium set, * as they will output PHY_INTERFACE_MODE_XXX modes. In that case, derive * the supported list based on these interfaces