diff options
author | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2024-04-22 16:44:44 +0100 |
---|---|---|
committer | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2024-04-27 16:54:58 +0100 |
commit | 8c9419fb2fda6c784624d6acdcdbc336dd7d6270 (patch) | |
tree | 19873ae323d92327e953936d989330704105ccd7 | |
parent | 5e19ef6084485795591839b8a60c8b9c2710683c (diff) |
net: phylink: switch to MLO_AN_PHY when PCS uses outband
phylink_pcs_neg_mode() currently only outband mode when we are using
MLO_AN_PHY or MLO_AN_FIXED. However, we want to extend the use of this
to MLO_AN_INBAND when the PCS and/or PHY are unable to use inband mode.
For example, when a PHY is not capable of supporting inband mode, we
need to operate in outband mode. However, using outband mode for the
PCS while using MLO_AN_INBAND causes drivers to misbehave as it is not
a situation they are expecting. Therefore, we need to switch to
MLO_AN_PHY when using outband mode.
Add the logic to select MLO_AN_PHY mode when phylink_pcs_neg_mode()
indicates that it will be using outband mode with a PHY and the
requested mode is MLO_AN_INBAND.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
-rw-r--r-- | drivers/net/phy/phylink.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 161c4d828437..39c4b8e29fae 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1144,6 +1144,15 @@ static unsigned int phylink_pcs_neg_mode(unsigned int mode, return neg_mode; } +static u8 phylink_choose_act_link_an_mode(struct phylink *pl) +{ + if (pl->req_link_an_mode == MLO_AN_INBAND && pl->phydev && + pl->pcs_neg_mode == PHYLINK_PCS_NEG_OUTBAND) + return MLO_AN_PHY; + + return pl->req_link_an_mode; +} + static void phylink_major_config(struct phylink *pl, bool restart, const struct phylink_link_state *state) { @@ -1171,7 +1180,10 @@ static void phylink_major_config(struct phylink *pl, bool restart, pcs_changed = pcs && pl->pcs != pcs; } - pl->act_link_an_mode = pl->req_link_an_mode; + /* set the active link AN mode, which may end up different from the + * current link AN mode depending on the PCS and PHY capabilities. + */ + pl->act_link_an_mode = phylink_choose_act_link_an_mode(pl); phylink_pcs_poll_stop(pl); @@ -1267,7 +1279,10 @@ static int phylink_change_inband_advert(struct phylink *pl) pl->link_config.interface, pl->link_config.advertising); - pl->act_link_an_mode = pl->req_link_an_mode; + /* set the active link AN mode, which may end up different from the + * current link AN mode depending on the PCS and PHY capabilities. + */ + pl->act_link_an_mode = phylink_choose_act_link_an_mode(pl); neg_mode = pl->act_link_an_mode; if (pl->pcs->neg_mode) |