| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From caf32f96f13df7d3ae6cb8bf8001c88ae22025ca Mon Sep 17 00:00:00 2001 |
| 2 | From: Russell King <rmk+kernel@armlinux.org.uk> |
| 3 | Date: Fri, 8 Nov 2019 15:28:22 +0000 |
| 4 | Subject: [PATCH 650/660] net: phylink: support Clause 45 PHYs on SFP+ modules |
| 5 | |
| 6 | Some SFP+ modules have Clause 45 PHYs embedded on them, which need a |
| 7 | little more handling in order to ensure that they are correctly setup, |
| 8 | as they switch the PHY link mode according to the negotiated speed. |
| 9 | |
| 10 | With Clause 22 PHYs, we assumed that they would operate in SGMII mode, |
| 11 | but this assumption is now false. Adapt phylink to support Clause 45 |
| 12 | PHYs on SFP+ modules. |
| 13 | |
| 14 | Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> |
| 15 | --- |
| 16 | drivers/net/phy/phylink.c | 21 ++++++++++++++++----- |
| 17 | 1 file changed, 16 insertions(+), 5 deletions(-) |
| 18 | |
| 19 | --- a/drivers/net/phy/phylink.c |
| 20 | +++ b/drivers/net/phy/phylink.c |
| 21 | @@ -712,7 +712,8 @@ static void phylink_phy_change(struct ph |
| 22 | phy_duplex_to_str(phydev->duplex)); |
| 23 | } |
| 24 | |
| 25 | -static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy) |
| 26 | +static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, |
| 27 | + phy_interface_t interface) |
| 28 | { |
| 29 | struct phylink_link_state config; |
| 30 | __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); |
| 31 | @@ -730,7 +731,7 @@ static int phylink_bringup_phy(struct ph |
| 32 | memset(&config, 0, sizeof(config)); |
| 33 | linkmode_copy(supported, phy->supported); |
| 34 | linkmode_copy(config.advertising, phy->advertising); |
| 35 | - config.interface = pl->link_config.interface; |
| 36 | + config.interface = interface; |
| 37 | |
| 38 | ret = phylink_validate(pl, supported, &config); |
| 39 | if (ret) |
| 40 | @@ -746,6 +747,7 @@ static int phylink_bringup_phy(struct ph |
| 41 | mutex_lock(&phy->lock); |
| 42 | mutex_lock(&pl->state_mutex); |
| 43 | pl->phydev = phy; |
| 44 | + pl->phy_state.interface = interface; |
| 45 | linkmode_copy(pl->supported, supported); |
| 46 | linkmode_copy(pl->link_config.advertising, config.advertising); |
| 47 | |
| 48 | @@ -808,7 +810,7 @@ int phylink_connect_phy(struct phylink * |
| 49 | if (ret < 0) |
| 50 | return ret; |
| 51 | |
| 52 | - ret = phylink_bringup_phy(pl, phy); |
| 53 | + ret = phylink_bringup_phy(pl, phy, pl->link_config.interface); |
| 54 | if (ret) |
| 55 | phy_detach(phy); |
| 56 | |
| 57 | @@ -861,7 +863,7 @@ int phylink_of_phy_connect(struct phylin |
| 58 | if (!phy_dev) |
| 59 | return -ENODEV; |
| 60 | |
| 61 | - ret = phylink_bringup_phy(pl, phy_dev); |
| 62 | + ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface); |
| 63 | if (ret) |
| 64 | phy_detach(phy_dev); |
| 65 | |
| 66 | @@ -1814,13 +1816,22 @@ static void phylink_sfp_link_up(void *up |
| 67 | static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) |
| 68 | { |
| 69 | struct phylink *pl = upstream; |
| 70 | + phy_interface_t interface = pl->link_config.interface; |
| 71 | int ret; |
| 72 | |
| 73 | ret = phylink_attach_phy(pl, phy, pl->link_config.interface); |
| 74 | if (ret < 0) |
| 75 | return ret; |
| 76 | |
| 77 | - ret = phylink_bringup_phy(pl, phy); |
| 78 | + /* Clause 45 PHYs switch their Serdes lane between several different |
| 79 | + * modes, normally 10GBASE-R, SGMII. Some use 2500BASE-X for 2.5G |
| 80 | + * speeds. We really need to know which interface modes the PHY and |
| 81 | + * MAC supports to properly work out which linkmodes can be supported. |
| 82 | + */ |
| 83 | + if (phy->is_c45) |
| 84 | + interface = PHY_INTERFACE_MODE_NA; |
| 85 | + |
| 86 | + ret = phylink_bringup_phy(pl, phy, interface); |
| 87 | if (ret) |
| 88 | phy_detach(phy); |
| 89 | |