summaryrefslogtreecommitdiff
path: root/drivers/net/phy/phylink.c
diff options
context:
space:
mode:
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2024-04-22 16:44:44 +0100
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2024-05-07 10:49:38 +0100
commit8add7c1dbaf415d1fcbf75ff5a5a67adb78344a7 (patch)
treef2f7bb267cb771183987728cce34ec3ec2916c24 /drivers/net/phy/phylink.c
parenta00faceee9da83a3fbf2327003fe3ee9e06b2e59 (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>
Diffstat (limited to 'drivers/net/phy/phylink.c')
-rw-r--r--drivers/net/phy/phylink.c19
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)