From: Maxime Chevallier <maxime.chevallier@bootlin.com>
To: davem@davemloft.net
Cc: "Maxime Chevallier" <maxime.chevallier@bootlin.com>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-msm@vger.kernel.org, thomas.petazzoni@bootlin.com,
"Andrew Lunn" <andrew@lunn.ch>,
"Jakub Kicinski" <kuba@kernel.org>,
"Eric Dumazet" <edumazet@google.com>,
"Paolo Abeni" <pabeni@redhat.com>,
"Russell King" <linux@armlinux.org.uk>,
linux-arm-kernel@lists.infradead.org,
"Christophe Leroy" <christophe.leroy@csgroup.eu>,
"Herve Codina" <herve.codina@bootlin.com>,
"Florian Fainelli" <f.fainelli@gmail.com>,
"Heiner Kallweit" <hkallweit1@gmail.com>,
"Vladimir Oltean" <vladimir.oltean@nxp.com>,
"Köry Maincent" <kory.maincent@bootlin.com>,
"Marek Behún" <kabel@kernel.org>,
"Oleksij Rempel" <o.rempel@pengutronix.de>,
"Nicolò Veronese" <nicveronese@gmail.com>,
"Simon Horman" <horms@kernel.org>,
mwojtas@chromium.org, "Antoine Tenart" <atenart@kernel.org>,
devicetree@vger.kernel.org, "Conor Dooley" <conor+dt@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Rob Herring" <robh@kernel.org>,
"Romain Gantois" <romain.gantois@bootlin.com>,
"Daniel Golle" <daniel@makrotopia.org>,
"Dimitri Fedrau" <dimitri.fedrau@liebherr.com>,
"Florian Fainelli" <florian.fainelli@broadcom.com>
Subject: [PATCH net-next v13 09/18] net: phylink: Move sfp interface selection and filtering to phy_caps
Date: Sun, 21 Sep 2025 21:34:07 +0530 [thread overview]
Message-ID: <20250921160419.333427-10-maxime.chevallier@bootlin.com> (raw)
In-Reply-To: <20250921160419.333427-1-maxime.chevallier@bootlin.com>
Phylink's helpers to get the interfaces usable on an SFP module based on
speed and linkmodes can be modes to phy_caps, so that it can benefit to
PHY-driver SFP support.
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Tested-by: Oleksij Rempel <o.rempel@pengutronix.de>
Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
Tested-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
drivers/net/phy/phy-caps.h | 6 ++++
drivers/net/phy/phy_caps.c | 73 ++++++++++++++++++++++++++++++++++++++
drivers/net/phy/phylink.c | 72 +++++--------------------------------
3 files changed, 87 insertions(+), 64 deletions(-)
diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h
index ba81cd75e122..ebed340a2e77 100644
--- a/drivers/net/phy/phy-caps.h
+++ b/drivers/net/phy/phy-caps.h
@@ -66,4 +66,10 @@ void phy_caps_medium_get_supported(unsigned long *supported,
int lanes);
u32 phy_caps_mediums_from_linkmodes(unsigned long *linkmodes);
+void phy_caps_filter_sfp_interfaces(unsigned long *dst,
+ const unsigned long *interfaces);
+phy_interface_t phy_caps_select_sfp_interface_speed(const unsigned long *interfaces,
+ u32 speed);
+phy_interface_t phy_caps_choose_sfp_interface(const unsigned long *interfaces);
+
#endif /* __PHY_CAPS_H */
diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c
index b38c567ec6ef..d23b0e5da928 100644
--- a/drivers/net/phy/phy_caps.c
+++ b/drivers/net/phy/phy_caps.c
@@ -63,6 +63,22 @@ static int speed_duplex_to_capa(int speed, unsigned int duplex)
#define for_each_link_caps_desc_speed(cap) \
for (cap = &link_caps[__LINK_CAPA_MAX - 1]; cap >= link_caps; cap--)
+static const phy_interface_t phy_caps_sfp_interface_preference[] = {
+ PHY_INTERFACE_MODE_100GBASEP,
+ PHY_INTERFACE_MODE_50GBASER,
+ PHY_INTERFACE_MODE_LAUI,
+ PHY_INTERFACE_MODE_25GBASER,
+ PHY_INTERFACE_MODE_USXGMII,
+ PHY_INTERFACE_MODE_10GBASER,
+ PHY_INTERFACE_MODE_5GBASER,
+ PHY_INTERFACE_MODE_2500BASEX,
+ PHY_INTERFACE_MODE_SGMII,
+ PHY_INTERFACE_MODE_1000BASEX,
+ PHY_INTERFACE_MODE_100BASEX,
+};
+
+static DECLARE_PHY_INTERFACE_MASK(phy_caps_sfp_interfaces);
+
/**
* phy_caps_init() - Initializes the link_caps array from the link_mode_params.
*
@@ -100,6 +116,10 @@ int phy_caps_init(void)
__set_bit(i, link_caps[capa].linkmodes);
}
+ for (int i = 0; i < ARRAY_SIZE(phy_caps_sfp_interface_preference); ++i)
+ __set_bit(phy_caps_sfp_interface_preference[i],
+ phy_caps_sfp_interfaces);
+
return 0;
}
@@ -520,3 +540,56 @@ int phy_caps_interface_max_speed(phy_interface_t interface)
return SPEED_UNKNOWN;
}
EXPORT_SYMBOL_GPL(phy_caps_interface_max_speed);
+
+void phy_caps_filter_sfp_interfaces(unsigned long *dst,
+ const unsigned long *interfaces)
+{
+ phy_interface_and(dst, interfaces, phy_caps_sfp_interfaces);
+}
+EXPORT_SYMBOL_GPL(phy_caps_filter_sfp_interfaces);
+
+phy_interface_t
+phy_caps_select_sfp_interface_speed(const unsigned long *interfaces, u32 speed)
+{
+ phy_interface_t best_interface = PHY_INTERFACE_MODE_NA;
+ phy_interface_t interface;
+ u32 max_speed;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(phy_caps_sfp_interface_preference); i++) {
+ interface = phy_caps_sfp_interface_preference[i];
+ if (!test_bit(interface, interfaces))
+ continue;
+
+ max_speed = phy_caps_interface_max_speed(interface);
+
+ /* The logic here is: if speed == max_speed, then we've found
+ * the best interface. Otherwise we find the interface that
+ * can just support the requested speed.
+ */
+ if (max_speed >= speed)
+ best_interface = interface;
+
+ if (max_speed <= speed)
+ break;
+ }
+
+ return best_interface;
+}
+EXPORT_SYMBOL_GPL(phy_caps_select_sfp_interface_speed);
+
+phy_interface_t phy_caps_choose_sfp_interface(const unsigned long *interfaces)
+{
+ phy_interface_t interface;
+ size_t i;
+
+ interface = PHY_INTERFACE_MODE_NA;
+ for (i = 0; i < ARRAY_SIZE(phy_caps_sfp_interface_preference); i++)
+ if (test_bit(phy_caps_sfp_interface_preference[i], interfaces)) {
+ interface = phy_caps_sfp_interface_preference[i];
+ break;
+ }
+
+ return interface;
+}
+EXPORT_SYMBOL_GPL(phy_caps_choose_sfp_interface);
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 6e667a2aa374..79cd64a49c02 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -128,22 +128,6 @@ do { \
})
#endif
-static const phy_interface_t phylink_sfp_interface_preference[] = {
- PHY_INTERFACE_MODE_100GBASEP,
- PHY_INTERFACE_MODE_50GBASER,
- PHY_INTERFACE_MODE_LAUI,
- PHY_INTERFACE_MODE_25GBASER,
- PHY_INTERFACE_MODE_USXGMII,
- PHY_INTERFACE_MODE_10GBASER,
- PHY_INTERFACE_MODE_5GBASER,
- PHY_INTERFACE_MODE_2500BASEX,
- PHY_INTERFACE_MODE_SGMII,
- PHY_INTERFACE_MODE_1000BASEX,
- PHY_INTERFACE_MODE_100BASEX,
-};
-
-static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces);
-
/**
* phylink_set_port_modes() - set the port type modes in the ethtool mask
* @mask: ethtool link mode mask
@@ -1941,8 +1925,7 @@ static int phylink_validate_phy(struct phylink *pl, struct phy_device *phy,
/* If the PHY is on a SFP, limit the interfaces to
* those that can be used with a SFP module.
*/
- phy_interface_and(interfaces, interfaces,
- phylink_sfp_interfaces);
+ phy_caps_filter_sfp_interfaces(interfaces, interfaces);
if (phy_interface_empty(interfaces)) {
phylink_err(pl, "SFP PHY's possible interfaces becomes empty\n");
@@ -2668,34 +2651,16 @@ static phy_interface_t phylink_sfp_select_interface(struct phylink *pl,
static phy_interface_t phylink_sfp_select_interface_speed(struct phylink *pl,
u32 speed)
{
- phy_interface_t best_interface = PHY_INTERFACE_MODE_NA;
phy_interface_t interface;
- u32 max_speed;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(phylink_sfp_interface_preference); i++) {
- interface = phylink_sfp_interface_preference[i];
- if (!test_bit(interface, pl->sfp_interfaces))
- continue;
-
- max_speed = phy_caps_interface_max_speed(interface);
- /* The logic here is: if speed == max_speed, then we've found
- * the best interface. Otherwise we find the interface that
- * can just support the requested speed.
- */
- if (max_speed >= speed)
- best_interface = interface;
-
- if (max_speed <= speed)
- break;
- }
+ interface = phy_caps_select_sfp_interface_speed(pl->sfp_interfaces,
+ speed);
- if (best_interface == PHY_INTERFACE_MODE_NA)
+ if (interface == PHY_INTERFACE_MODE_NA)
phylink_err(pl, "selection of interface failed, speed %u\n",
speed);
- return best_interface;
+ return interface;
}
static void phylink_merge_link_mode(unsigned long *dst, const unsigned long *b)
@@ -3475,17 +3440,7 @@ static void phylink_sfp_detach(void *upstream, struct sfp_bus *bus)
static phy_interface_t phylink_choose_sfp_interface(struct phylink *pl,
const unsigned long *intf)
{
- phy_interface_t interface;
- size_t i;
-
- interface = PHY_INTERFACE_MODE_NA;
- for (i = 0; i < ARRAY_SIZE(phylink_sfp_interface_preference); i++)
- if (test_bit(phylink_sfp_interface_preference[i], intf)) {
- interface = phylink_sfp_interface_preference[i];
- break;
- }
-
- return interface;
+ return phy_caps_choose_sfp_interface(intf);
}
static void phylink_sfp_set_config(struct phylink *pl, unsigned long *supported,
@@ -3762,8 +3717,8 @@ static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
phy_support_asym_pause(phy);
/* Set the PHY's host supported interfaces */
- phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces,
- pl->config->supported_interfaces);
+ phy_caps_filter_sfp_interfaces(phy->host_interfaces,
+ pl->config->supported_interfaces);
/* Do the initial configuration */
return phylink_sfp_config_phy(pl, phy);
@@ -4191,16 +4146,5 @@ void phylink_mii_c45_pcs_get_state(struct mdio_device *pcs,
}
EXPORT_SYMBOL_GPL(phylink_mii_c45_pcs_get_state);
-static int __init phylink_init(void)
-{
- for (int i = 0; i < ARRAY_SIZE(phylink_sfp_interface_preference); ++i)
- __set_bit(phylink_sfp_interface_preference[i],
- phylink_sfp_interfaces);
-
- return 0;
-}
-
-module_init(phylink_init);
-
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("phylink models the MAC to optional PHY connection");
--
2.49.0
next prev parent reply other threads:[~2025-09-21 16:07 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-21 16:03 [PATCH net-next v13 00/18] net: phy: Introduce PHY ports representation Maxime Chevallier
2025-09-21 16:03 ` [PATCH net-next v13 01/18] dt-bindings: net: Introduce the ethernet-connector description Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 02/18] net: ethtool: common: Indicate that BaseT works on up to 4 lanes Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 03/18] net: ethtool: Introduce ETHTOOL_LINK_MEDIUM_* values Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 04/18] net: phy: Introduce PHY ports representation Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 05/18] net: phy: dp83822: Add support for phy_port representation Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 06/18] dt-bindings: net: dp83822: Deprecate ti,fiber-mode Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 07/18] net: phy: Create a phy_port for PHY-driven SFPs Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 08/18] net: phylink: Move phylink_interface_max_speed to phy_caps Maxime Chevallier
2025-09-21 16:04 ` Maxime Chevallier [this message]
2025-09-21 16:04 ` [PATCH net-next v13 10/18] net: phy: Introduce generic SFP handling for PHY drivers Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 11/18] net: phy: marvell-88x2222: Support SFP through phy_port interface Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 12/18] net: phy: marvell: " Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 13/18] net: phy: marvell10g: Support SFP through phy_port Maxime Chevallier
2025-09-24 1:24 ` Jakub Kicinski
2025-09-24 3:53 ` Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 14/18] net: phy: at803x: Support SFP through phy_port interface Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 15/18] net: phy: qca807x: " Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 16/18] net: phy: Only rely on phy_port for PHY-driven SFP Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 17/18] net: phy: dp83822: Add SFP support through the phy_port interface Maxime Chevallier
2025-09-21 16:04 ` [PATCH net-next v13 18/18] Documentation: networking: Document the phy_port infrastructure Maxime Chevallier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250921160419.333427-10-maxime.chevallier@bootlin.com \
--to=maxime.chevallier@bootlin.com \
--cc=andrew@lunn.ch \
--cc=atenart@kernel.org \
--cc=christophe.leroy@csgroup.eu \
--cc=conor+dt@kernel.org \
--cc=daniel@makrotopia.org \
--cc=davem@davemloft.net \
--cc=devicetree@vger.kernel.org \
--cc=dimitri.fedrau@liebherr.com \
--cc=edumazet@google.com \
--cc=f.fainelli@gmail.com \
--cc=florian.fainelli@broadcom.com \
--cc=herve.codina@bootlin.com \
--cc=hkallweit1@gmail.com \
--cc=horms@kernel.org \
--cc=kabel@kernel.org \
--cc=kory.maincent@bootlin.com \
--cc=krzk+dt@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=mwojtas@chromium.org \
--cc=netdev@vger.kernel.org \
--cc=nicveronese@gmail.com \
--cc=o.rempel@pengutronix.de \
--cc=pabeni@redhat.com \
--cc=robh@kernel.org \
--cc=romain.gantois@bootlin.com \
--cc=thomas.petazzoni@bootlin.com \
--cc=vladimir.oltean@nxp.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox