From: "Marek Behún" <kabel@kernel.org>
To: netdev@vger.kernel.org, "David S. Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>
Cc: "Russell King" <rmk+kernel@armlinux.org.uk>,
"Andrew Lunn" <andrew@lunn.ch>,
"Vladimir Oltean" <vladimir.oltean@nxp.com>,
"Marek Behún" <kabel@kernel.org>
Subject: [PATCH net-next 03/12] net: phylink: use phy_interface_t bitmaps for optical modules
Date: Fri, 30 Sep 2022 16:21:01 +0200 [thread overview]
Message-ID: <20220930142110.15372-4-kabel@kernel.org> (raw)
In-Reply-To: <20220930142110.15372-1-kabel@kernel.org>
From: Russell King <rmk+kernel@armlinux.org.uk>
Where a MAC provides a phy_interface_t bitmap, use these bitmaps to
select the operating interface mode for optical SFP modules, rather
than using the linkmode bitmaps.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: Marek Behún <kabel@kernel.org>
---
drivers/net/phy/phylink.c | 164 +++++++++++++++++++++++++++++++-------
1 file changed, 134 insertions(+), 30 deletions(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index b76bf8df83ff..ab32ef767d69 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -2803,6 +2803,70 @@ static void phylink_sfp_detach(void *upstream, struct sfp_bus *bus)
pl->netdev->sfp_bus = NULL;
}
+static const phy_interface_t phylink_sfp_interface_preference[] = {
+ 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 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;
+}
+
+static void phylink_sfp_set_config(struct phylink *pl, u8 mode,
+ unsigned long *supported,
+ struct phylink_link_state *state)
+{
+ bool changed = false;
+
+ phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n",
+ phylink_an_mode_str(mode), phy_modes(state->interface),
+ __ETHTOOL_LINK_MODE_MASK_NBITS, supported);
+
+ if (!linkmode_equal(pl->supported, supported)) {
+ linkmode_copy(pl->supported, supported);
+ changed = true;
+ }
+
+ if (!linkmode_equal(pl->link_config.advertising, state->advertising)) {
+ linkmode_copy(pl->link_config.advertising, state->advertising);
+ changed = true;
+ }
+
+ if (pl->cur_link_an_mode != mode ||
+ pl->link_config.interface != state->interface) {
+ pl->cur_link_an_mode = mode;
+ pl->link_config.interface = state->interface;
+
+ changed = true;
+
+ phylink_info(pl, "switched to %s/%s link mode\n",
+ phylink_an_mode_str(mode),
+ phy_modes(state->interface));
+ }
+
+ if (changed && !test_bit(PHYLINK_DISABLE_STOPPED,
+ &pl->phylink_disable_state))
+ phylink_mac_initial_config(pl, false);
+}
+
static int phylink_sfp_config(struct phylink *pl, u8 mode,
const unsigned long *supported,
const unsigned long *advertising)
@@ -2811,7 +2875,6 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode,
__ETHTOOL_DECLARE_LINK_MODE_MASK(support);
struct phylink_link_state config;
phy_interface_t iface;
- bool changed;
int ret;
linkmode_copy(support, supported);
@@ -2854,61 +2917,103 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode,
return ret;
}
- phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n",
- phylink_an_mode_str(mode), phy_modes(config.interface),
- __ETHTOOL_LINK_MODE_MASK_NBITS, support);
-
if (phy_interface_mode_is_8023z(iface) && pl->phydev)
return -EINVAL;
- changed = !linkmode_equal(pl->supported, support) ||
- !linkmode_equal(pl->link_config.advertising,
- config.advertising);
- if (changed) {
- linkmode_copy(pl->supported, support);
- linkmode_copy(pl->link_config.advertising, config.advertising);
+ pl->link_port = pl->sfp_port;
+
+ phylink_sfp_set_config(pl, mode, support, &config);
+
+ return 0;
+}
+
+static int phylink_sfp_config_optical(struct phylink *pl)
+{
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(support);
+ DECLARE_PHY_INTERFACE_MASK(interfaces);
+ struct phylink_link_state config;
+ phy_interface_t interface;
+ int ret;
+
+ phylink_dbg(pl, "optical SFP: interfaces=[mac=%*pbl, sfp=%*pbl]\n",
+ (int)PHY_INTERFACE_MODE_MAX,
+ pl->config->supported_interfaces,
+ (int)PHY_INTERFACE_MODE_MAX,
+ pl->sfp_interfaces);
+
+ /* Find the union of the supported interfaces by the PCS/MAC and
+ * the SFP module.
+ */
+ phy_interface_and(interfaces, pl->config->supported_interfaces,
+ pl->sfp_interfaces);
+ if (phy_interface_empty(interfaces)) {
+ phylink_err(pl, "unsupported SFP module: no common interface modes\n");
+ return -EINVAL;
}
- if (pl->cur_link_an_mode != mode ||
- pl->link_config.interface != config.interface) {
- pl->link_config.interface = config.interface;
- pl->cur_link_an_mode = mode;
+ memset(&config, 0, sizeof(config));
+ linkmode_copy(support, pl->sfp_support);
+ linkmode_copy(config.advertising, pl->sfp_support);
+ config.speed = SPEED_UNKNOWN;
+ config.duplex = DUPLEX_UNKNOWN;
+ config.pause = MLO_PAUSE_AN;
+ config.an_enabled = true;
- changed = true;
+ /* For all the interfaces that are supported, reduce the sfp_support
+ * mask to only those link modes that can be supported.
+ */
+ ret = phylink_validate_mask(pl, pl->sfp_support, &config, interfaces);
+ if (ret) {
+ phylink_err(pl, "unsupported SFP module: validation with support %*pb failed\n",
+ __ETHTOOL_LINK_MODE_MASK_NBITS, support);
+ return ret;
+ }
- phylink_info(pl, "switched to %s/%s link mode\n",
- phylink_an_mode_str(mode),
- phy_modes(config.interface));
+ interface = phylink_choose_sfp_interface(pl, interfaces);
+ if (interface == PHY_INTERFACE_MODE_NA) {
+ phylink_err(pl, "failed to select SFP interface\n");
+ return -EINVAL;
+ }
+
+ phylink_dbg(pl, "optical SFP: chosen %s interface\n",
+ phy_modes(interface));
+
+ config.interface = interface;
+
+ /* Ignore errors if we're expecting a PHY to attach later */
+ ret = phylink_validate(pl, support, &config);
+ if (ret) {
+ phylink_err(pl, "validation with support %*pb failed: %pe\n",
+ __ETHTOOL_LINK_MODE_MASK_NBITS, support,
+ ERR_PTR(ret));
+ return ret;
}
pl->link_port = pl->sfp_port;
- if (changed && !test_bit(PHYLINK_DISABLE_STOPPED,
- &pl->phylink_disable_state))
- phylink_mac_initial_config(pl, false);
+ phylink_sfp_set_config(pl, MLO_AN_INBAND, pl->sfp_support, &config);
- return ret;
+ return 0;
}
static int phylink_sfp_module_insert(void *upstream,
const struct sfp_eeprom_id *id)
{
struct phylink *pl = upstream;
- unsigned long *support = pl->sfp_support;
ASSERT_RTNL();
- linkmode_zero(support);
+ linkmode_zero(pl->sfp_support);
phy_interface_zero(pl->sfp_interfaces);
- sfp_parse_support(pl->sfp_bus, id, support, pl->sfp_interfaces);
- pl->sfp_port = sfp_parse_port(pl->sfp_bus, id, support);
+ sfp_parse_support(pl->sfp_bus, id, pl->sfp_support, pl->sfp_interfaces);
+ pl->sfp_port = sfp_parse_port(pl->sfp_bus, id, pl->sfp_support);
/* If this module may have a PHY connecting later, defer until later */
pl->sfp_may_have_phy = sfp_may_have_phy(pl->sfp_bus, id);
if (pl->sfp_may_have_phy)
return 0;
- return phylink_sfp_config(pl, MLO_AN_INBAND, support, support);
+ return phylink_sfp_config_optical(pl);
}
static int phylink_sfp_module_start(void *upstream)
@@ -2927,8 +3032,7 @@ static int phylink_sfp_module_start(void *upstream)
if (!pl->sfp_may_have_phy)
return 0;
- return phylink_sfp_config(pl, MLO_AN_INBAND,
- pl->sfp_support, pl->sfp_support);
+ return phylink_sfp_config_optical(pl);
}
static void phylink_sfp_module_stop(void *upstream)
--
2.35.1
next prev parent reply other threads:[~2022-09-30 14:22 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-30 14:20 [PATCH net-next 00/12] RollBall / Hilink / Turris 10G copper SFP support Marek Behún
2022-09-30 14:20 ` [PATCH net-next 01/12] net: phylink: add ability to validate a set of interface modes Marek Behún
2022-09-30 14:21 ` [PATCH net-next 02/12] net: sfp: augment SFP parsing with phy_interface_t bitmap Marek Behún
2022-09-30 14:21 ` Marek Behún [this message]
2022-09-30 14:21 ` [PATCH net-next 04/12] net: phylink: rename phylink_sfp_config() Marek Behún
2022-09-30 14:21 ` [PATCH net-next 05/12] net: phylink: pass supported host PHY interface modes to phylib for SFP's PHYs Marek Behún
2022-09-30 14:21 ` [PATCH net-next 06/12] net: phy: marvell10g: Use tabs instead of spaces for indentation Marek Behún
2022-09-30 14:21 ` [PATCH net-next 07/12] net: phy: marvell10g: select host interface configuration Marek Behún
2022-09-30 14:21 ` [PATCH net-next 08/12] net: phylink: allow attaching phy for SFP modules on 802.3z mode Marek Behún
2022-09-30 14:21 ` [PATCH net-next 09/12] net: sfp: Add and use macros for SFP quirks definitions Marek Behún
2022-09-30 14:21 ` [PATCH net-next 10/12] net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY release Marek Behún
2022-09-30 14:21 ` [PATCH net-next 11/12] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules Marek Behún
2022-09-30 14:21 ` [PATCH net-next 12/12] net: sfp: add support for multigig RollBall transceivers Marek Behún
2022-10-03 10:20 ` [PATCH net-next 00/12] RollBall / Hilink / Turris 10G copper SFP support patchwork-bot+netdevbpf
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=20220930142110.15372-4-kabel@kernel.org \
--to=kabel@kernel.org \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=rmk+kernel@armlinux.org.uk \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.