summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2021-11-26 17:31:05 +0000
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2022-01-18 10:17:23 +0000
commit98ac55fa2906aa8a4ecf161c2ee1f4052f266941 (patch)
treefea7c479e713542263f5198766470d8515167b24
parentd27e3e2b10eb25ba1c96177132e8a6e8b8f953af (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.c33
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,