|
|
@@ -0,0 +1,130 @@
|
|
|
+From 8f7a9799c5949f94ecc3acfd71b36437a7ade73b Mon Sep 17 00:00:00 2001
|
|
|
+From: "Russell King (Oracle)" <[email protected]>
|
|
|
+Date: Fri, 24 Nov 2023 12:28:39 +0000
|
|
|
+Subject: [PATCH 7/7] net: phylink: use the PHY's possible_interfaces if
|
|
|
+ populated
|
|
|
+
|
|
|
+Some PHYs such as Aquantia, Broadcom 84881, and Marvell 88X33x0 can
|
|
|
+switch between a set of interface types depending on the negotiated
|
|
|
+media speed, or can use rate adaption for some or all of these
|
|
|
+interface types.
|
|
|
+
|
|
|
+We currently assume that these are Clause 45 PHYs that are configured
|
|
|
+not to use a specific set of interface modes, which has worked so far,
|
|
|
+but is just a work-around. In this workaround, we validate using all
|
|
|
+interfaces that the MAC supports, which can lead to extra modes being
|
|
|
+advertised that can not be supported.
|
|
|
+
|
|
|
+To properly address this, switch to using the newly introduced PHY
|
|
|
+possible_interfaces bitmap which indicates which interface modes will
|
|
|
+be used by the PHY as configured. We calculate the union of the PHY's
|
|
|
+possible interfaces and MACs supported interfaces, checking that is
|
|
|
+non-empty. If the PHY is on a SFP, we further reduce the set by those
|
|
|
+which can be used on a SFP module, again checking that is non-empty.
|
|
|
+Finally, we validate the subset of interfaces, taking account of
|
|
|
+whether rate matching will be used for each individual interface mode.
|
|
|
+
|
|
|
+This becomes independent of whether the PHY is clause 22 or clause 45.
|
|
|
+
|
|
|
+It is encouraged that all PHYs that switch interface modes or use
|
|
|
+rate matching should populate phydev->possible_interfaces.
|
|
|
+
|
|
|
+Tested-by: Luo Jie <[email protected]>
|
|
|
+Signed-off-by: Russell King (Oracle) <[email protected]>
|
|
|
+Reviewed-by: Andrew Lunn <[email protected]>
|
|
|
+Link: https://lore.kernel.org/r/[email protected]
|
|
|
+Signed-off-by: Jakub Kicinski <[email protected]>
|
|
|
+---
|
|
|
+ drivers/net/phy/phylink.c | 67 +++++++++++++++++++++++++++++++--------
|
|
|
+ 1 file changed, 54 insertions(+), 13 deletions(-)
|
|
|
+
|
|
|
+--- a/drivers/net/phy/phylink.c
|
|
|
++++ b/drivers/net/phy/phylink.c
|
|
|
+@@ -121,6 +121,19 @@ do { \
|
|
|
+ })
|
|
|
+ #endif
|
|
|
+
|
|
|
++static const phy_interface_t phylink_sfp_interface_preference[] = {
|
|
|
++ PHY_INTERFACE_MODE_25GBASER,
|
|
|
++ PHY_INTERFACE_MODE_USXGMII,
|
|
|
++ PHY_INTERFACE_MODE_10GBASER,
|
|
|
++ PHY_INTERFACE_MODE_5GBASER,
|
|
|
++ PHY_INTERFACE_MODE_2500BASEX,
|
|
|
++ PHY_INTERFACE_MODE_SGMII,
|
|
|
++ PHY_INTERFACE_MODE_1000BASEX,
|
|
|
++ PHY_INTERFACE_MODE_100BASEX,
|
|
|
++};
|
|
|
++
|
|
|
++static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces);
|
|
|
++
|
|
|
+ /**
|
|
|
+ * phylink_set_port_modes() - set the port type modes in the ethtool mask
|
|
|
+ * @mask: ethtool link mode mask
|
|
|
+@@ -1742,6 +1755,47 @@ static int phylink_validate_phy(struct p
|
|
|
+ unsigned long *supported,
|
|
|
+ struct phylink_link_state *state)
|
|
|
+ {
|
|
|
++ DECLARE_PHY_INTERFACE_MASK(interfaces);
|
|
|
++
|
|
|
++ /* If the PHY provides a bitmap of the interfaces it will be using
|
|
|
++ * depending on the negotiated media speeds, use this to validate
|
|
|
++ * which ethtool link modes can be used.
|
|
|
++ */
|
|
|
++ if (!phy_interface_empty(phy->possible_interfaces)) {
|
|
|
++ /* We only care about the union of the PHY's interfaces and
|
|
|
++ * those which the host supports.
|
|
|
++ */
|
|
|
++ phy_interface_and(interfaces, phy->possible_interfaces,
|
|
|
++ pl->config->supported_interfaces);
|
|
|
++
|
|
|
++ if (phy_interface_empty(interfaces)) {
|
|
|
++ phylink_err(pl, "PHY has no common interfaces\n");
|
|
|
++ return -EINVAL;
|
|
|
++ }
|
|
|
++
|
|
|
++ if (phy_on_sfp(phy)) {
|
|
|
++ /* If the PHY is on a SFP, limit the interfaces to
|
|
|
++ * those that can be used with a SFP module.
|
|
|
++ */
|
|
|
++ phy_interface_and(interfaces, interfaces,
|
|
|
++ phylink_sfp_interfaces);
|
|
|
++
|
|
|
++ if (phy_interface_empty(interfaces)) {
|
|
|
++ phylink_err(pl, "SFP PHY's possible interfaces becomes empty\n");
|
|
|
++ return -EINVAL;
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ phylink_dbg(pl, "PHY %s uses interfaces %*pbl, validating %*pbl\n",
|
|
|
++ phydev_name(phy),
|
|
|
++ (int)PHY_INTERFACE_MODE_MAX,
|
|
|
++ phy->possible_interfaces,
|
|
|
++ (int)PHY_INTERFACE_MODE_MAX, interfaces);
|
|
|
++
|
|
|
++ return phylink_validate_mask(pl, phy, supported, state,
|
|
|
++ interfaces);
|
|
|
++ }
|
|
|
++
|
|
|
+ /* Check whether we would use rate matching for the proposed interface
|
|
|
+ * mode.
|
|
|
+ */
|
|
|
+@@ -2985,19 +3039,6 @@ static void phylink_sfp_detach(void *ups
|
|
|
+ pl->netdev->sfp_bus = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+-static const phy_interface_t phylink_sfp_interface_preference[] = {
|
|
|
+- PHY_INTERFACE_MODE_25GBASER,
|
|
|
+- PHY_INTERFACE_MODE_USXGMII,
|
|
|
+- PHY_INTERFACE_MODE_10GBASER,
|
|
|
+- PHY_INTERFACE_MODE_5GBASER,
|
|
|
+- PHY_INTERFACE_MODE_2500BASEX,
|
|
|
+- PHY_INTERFACE_MODE_SGMII,
|
|
|
+- PHY_INTERFACE_MODE_1000BASEX,
|
|
|
+- PHY_INTERFACE_MODE_100BASEX,
|
|
|
+-};
|
|
|
+-
|
|
|
+-static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces);
|
|
|
+-
|
|
|
+ static phy_interface_t phylink_choose_sfp_interface(struct phylink *pl,
|
|
|
+ const unsigned long *intf)
|
|
|
+ {
|