diff options
| author | Tan, Tee Min <tee.min.tan@intel.com> | 2022-03-08 14:14:30 +0800 |
|---|---|---|
| committer | Philip Cox <philip.cox@canonical.com> | 2022-11-14 14:16:06 -0500 |
| commit | d0bb42ad6b726056781f9c8a83f003e0e478017a (patch) | |
| tree | 73fbb88bb426f7914d60b5a8b2922bd8a0d1bb8a | |
| parent | 1e3ff292ba12cd983c603f68fbdebba66594cc16 (diff) | |
net: phy: update in-band AN mode when changing interface by PHY driver
BugLink: https://bugs.launchpad.net/bugs/1982282 Add cur_link_an_mode into phy_device struct for PHY drivers to communicate the in-band AN mode setting with phylink framework. As there is a mechanism in PHY drivers to switch the PHY interface between SGMII and 2500BaseX according to link speed. In this case, the in-band AN mode should be switching based on the PHY interface as well, if the PHY interface has been changed/updated by PHY driver. For e.g., disable in-band AN in 2500BaseX mode, or enable in-band AN back for SGMII mode (10/100/1000Mbps). Signed-off-by: Tan, Tee Min <tee.min.tan@intel.com> (picked from https://github.com/intel/linux-intel-quilt/tree/lts-v5.15.36-linux-220520T033542Z-1/patches/0038-net-phy-update-in-band-AN-mode-when-changing-interfa.patch) Signed-off-by: Philip Cox <philip.cox@canonical.com>
| -rw-r--r-- | drivers/net/phy/marvell10g.c | 6 | ||||
| -rw-r--r-- | drivers/net/phy/mxl-gpy.c | 5 | ||||
| -rw-r--r-- | drivers/net/phy/phylink.c | 5 | ||||
| -rw-r--r-- | include/linux/phy.h | 4 |
4 files changed, 20 insertions, 0 deletions
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index ea060aa0dbd1..1bd044fbd584 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -29,6 +29,7 @@ #include <linux/phy.h> #include <linux/sfp.h> #include <linux/netdevice.h> +#include <linux/phylink.h> #define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe #define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa) @@ -748,6 +749,9 @@ static void mv3310_update_interface(struct phy_device *phydev) * xaui / rxaui modes according to the speed. * Florian suggests setting phydev->interface to communicate this to the * MAC. Only do this if we are already in one of the above modes. + * In-band Auto-negotiation is not supported in 2500BASE-X. + * Setting phydev->cur_link_an_mode to communicate this to the + * phylink framework. */ switch (phydev->speed) { case SPEED_10000: @@ -758,11 +762,13 @@ static void mv3310_update_interface(struct phy_device *phydev) break; case SPEED_2500: phydev->interface = PHY_INTERFACE_MODE_2500BASEX; + phydev->cur_link_an_mode = MLO_AN_PHY; break; case SPEED_1000: case SPEED_100: case SPEED_10: phydev->interface = PHY_INTERFACE_MODE_SGMII; + phydev->cur_link_an_mode = MLO_AN_INBAND; break; default: break; diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c index 5ce1bf03bbd7..e2d714824166 100644 --- a/drivers/net/phy/mxl-gpy.c +++ b/drivers/net/phy/mxl-gpy.c @@ -10,6 +10,7 @@ #include <linux/bitfield.h> #include <linux/phy.h> #include <linux/netdevice.h> +#include <linux/phylink.h> /* PHY ID */ #define PHY_ID_GPYx15B_MASK 0xFFFFFFFC @@ -266,10 +267,13 @@ static void gpy_update_interface(struct phy_device *phydev) /* Automatically switch SERDES interface between SGMII and 2500-BaseX * according to speed. Disable ANEG in 2500-BaseX mode. + * Setting phydev->cur_link_an_mode to communicate this to the + * phylink framework. */ switch (phydev->speed) { case SPEED_2500: phydev->interface = PHY_INTERFACE_MODE_2500BASEX; + phydev->cur_link_an_mode = MLO_AN_PHY; ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, VSPEC1_SGMII_CTRL_ANEN, 0); if (ret < 0) @@ -281,6 +285,7 @@ static void gpy_update_interface(struct phy_device *phydev) case SPEED_100: case SPEED_10: phydev->interface = PHY_INTERFACE_MODE_SGMII; + phydev->cur_link_an_mode = MLO_AN_INBAND; if (gpy_sgmii_aneg_en(phydev)) break; /* Enable and restart SGMII ANEG for 10/100/1000Mbps link speed diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index fef1416dcee4..5d5c0e5e6ba7 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -963,6 +963,9 @@ static void phylink_phy_change(struct phy_device *phydev, bool up) pl->phy_state.pause |= MLO_PAUSE_RX; pl->phy_state.interface = phydev->interface; pl->phy_state.link = up; + /* Update current link AN mode if phy driver has changed it */ + if (pl->cur_link_an_mode != phydev->cur_link_an_mode) + pl->cur_link_an_mode = phydev->cur_link_an_mode; mutex_unlock(&pl->state_mutex); phylink_run_resolve(pl); @@ -1050,6 +1053,8 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, if (phy_interrupt_is_valid(phy)) phy_request_interrupt(phy); + pl->phydev->cur_link_an_mode = pl->cur_link_an_mode; + return 0; } diff --git a/include/linux/phy.h b/include/linux/phy.h index 946ccec17858..f55604c01f0f 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -676,6 +676,10 @@ struct phy_device { /* MACsec management functions */ const struct macsec_ops *macsec_ops; #endif + /* Use phydev->cur_link_an_mode to communicate the in-band + * AN mode setting with phylink framework. + */ + u8 cur_link_an_mode; }; static inline struct phy_device *to_phy_device(const struct device *dev) |
