diff options
author | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2021-11-26 17:31:05 +0000 |
---|---|---|
committer | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2022-01-18 10:17:23 +0000 |
commit | 98ac55fa2906aa8a4ecf161c2ee1f4052f266941 (patch) | |
tree | fea7c479e713542263f5198766470d8515167b24 | |
parent | d27e3e2b10eb25ba1c96177132e8a6e8b8f953af (diff) |
net: phylink: validate only used interfaces for c45 PHYs
Some clause 45 PHYs such as Marvell 88X33x0 and Broadcom 84881 switch
between a set of interface types depending on the negotiated media
speed.
We currently validate this kind of PHY using all MAC capabilities,
which is not correct if that would give a superset of the ethtool link
modes.
This commit uses the previously introduced phy possible_interfaces, and
the recently introduced supported_interfaces to calculate the union of
interface support, and then validates only those interfaces.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
-rw-r--r-- | drivers/net/phy/phylink.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index c425ddf2d52e..09b9569a7d8f 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1423,18 +1423,39 @@ static int phylink_validate_phy(struct phylink *pl, struct phy_device *phy, unsigned long *supported, struct phylink_link_state *state) { + DECLARE_PHY_INTERFACE_MASK(interfaces); + + /* If this is a clause 22 PHY, it only operates in a single mode. */ + if (!phy->is_c45) + return phylink_validate(pl, supported, state); + /* Clause 45 PHYs switch their Serdes lane between several different - * modes, normally 10GBASE-R, SGMII. Some use 2500BASE-X for 2.5G - * speeds. We really need to know which interface modes the PHY and - * MAC supports to properly work out which linkmodes can be supported. + * modes according to the negotiated media speed. For example, the + * interface may switch between 10GBASE-R, 5GBASE-R, 2500BASE-X and + * SGMII. + */ + + /* Backwards compatibility for those MAC drivers that don't set + * their supported_interfaces, or PHY drivers that don't set + * their possible_interfaces. */ - if (phy->is_c45 && + if ((phy_interface_empty(pl->config->supported_interfaces) || + phy_interface_empty(phy->possible_interfaces)) && state->interface != PHY_INTERFACE_MODE_RXAUI && state->interface != PHY_INTERFACE_MODE_XAUI && - state->interface != PHY_INTERFACE_MODE_USXGMII) + state->interface != PHY_INTERFACE_MODE_USXGMII) { state->interface = PHY_INTERFACE_MODE_NA; + return phylink_validate(pl, supported, state); + } + + /* Calculate the union of the interfaces the PHY supports in + * its configured state, and the host's supported interfaces. + * We never want an interface that isn't supported by the host. + */ + phy_interface_and(interfaces, phy->possible_interfaces, + pl->config->supported_interfaces); - return phylink_validate(pl, supported, state); + return phylink_validate_mask(pl, supported, state, interfaces); } static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, |