1 From 8f7a9799c5949f94ecc3acfd71b36437a7ade73b Mon Sep 17 00:00:00 2001
2 From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
3 Date: Fri, 24 Nov 2023 12:28:39 +0000
4 Subject: [PATCH 7/7] net: phylink: use the PHY's possible_interfaces if
7 Some PHYs such as Aquantia, Broadcom 84881, and Marvell 88X33x0 can
8 switch between a set of interface types depending on the negotiated
9 media speed, or can use rate adaption for some or all of these
12 We currently assume that these are Clause 45 PHYs that are configured
13 not to use a specific set of interface modes, which has worked so far,
14 but is just a work-around. In this workaround, we validate using all
15 interfaces that the MAC supports, which can lead to extra modes being
16 advertised that can not be supported.
18 To properly address this, switch to using the newly introduced PHY
19 possible_interfaces bitmap which indicates which interface modes will
20 be used by the PHY as configured. We calculate the union of the PHY's
21 possible interfaces and MACs supported interfaces, checking that is
22 non-empty. If the PHY is on a SFP, we further reduce the set by those
23 which can be used on a SFP module, again checking that is non-empty.
24 Finally, we validate the subset of interfaces, taking account of
25 whether rate matching will be used for each individual interface mode.
27 This becomes independent of whether the PHY is clause 22 or clause 45.
29 It is encouraged that all PHYs that switch interface modes or use
30 rate matching should populate phydev->possible_interfaces.
32 Tested-by: Luo Jie <quic_luoj@quicinc.com>
33 Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
34 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
35 Link: https://lore.kernel.org/r/E1r6VIV-00DDMF-Pi@rmk-PC.armlinux.org.uk
36 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
38 drivers/net/phy/phylink.c | 67 +++++++++++++++++++++++++++++++--------
39 1 file changed, 54 insertions(+), 13 deletions(-)
41 --- a/drivers/net/phy/phylink.c
42 +++ b/drivers/net/phy/phylink.c
43 @@ -121,6 +121,19 @@ do { \
47 +static const phy_interface_t phylink_sfp_interface_preference[] = {
48 + PHY_INTERFACE_MODE_25GBASER,
49 + PHY_INTERFACE_MODE_USXGMII,
50 + PHY_INTERFACE_MODE_10GBASER,
51 + PHY_INTERFACE_MODE_5GBASER,
52 + PHY_INTERFACE_MODE_2500BASEX,
53 + PHY_INTERFACE_MODE_SGMII,
54 + PHY_INTERFACE_MODE_1000BASEX,
55 + PHY_INTERFACE_MODE_100BASEX,
58 +static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces);
61 * phylink_set_port_modes() - set the port type modes in the ethtool mask
62 * @mask: ethtool link mode mask
63 @@ -1779,6 +1792,47 @@ static int phylink_validate_phy(struct p
64 unsigned long *supported,
65 struct phylink_link_state *state)
67 + DECLARE_PHY_INTERFACE_MASK(interfaces);
69 + /* If the PHY provides a bitmap of the interfaces it will be using
70 + * depending on the negotiated media speeds, use this to validate
71 + * which ethtool link modes can be used.
73 + if (!phy_interface_empty(phy->possible_interfaces)) {
74 + /* We only care about the union of the PHY's interfaces and
75 + * those which the host supports.
77 + phy_interface_and(interfaces, phy->possible_interfaces,
78 + pl->config->supported_interfaces);
80 + if (phy_interface_empty(interfaces)) {
81 + phylink_err(pl, "PHY has no common interfaces\n");
85 + if (phy_on_sfp(phy)) {
86 + /* If the PHY is on a SFP, limit the interfaces to
87 + * those that can be used with a SFP module.
89 + phy_interface_and(interfaces, interfaces,
90 + phylink_sfp_interfaces);
92 + if (phy_interface_empty(interfaces)) {
93 + phylink_err(pl, "SFP PHY's possible interfaces becomes empty\n");
98 + phylink_dbg(pl, "PHY %s uses interfaces %*pbl, validating %*pbl\n",
100 + (int)PHY_INTERFACE_MODE_MAX,
101 + phy->possible_interfaces,
102 + (int)PHY_INTERFACE_MODE_MAX, interfaces);
104 + return phylink_validate_mask(pl, phy, supported, state,
108 /* Check whether we would use rate matching for the proposed interface
111 @@ -3047,19 +3101,6 @@ static void phylink_sfp_detach(void *ups
112 pl->netdev->sfp_bus = NULL;
115 -static const phy_interface_t phylink_sfp_interface_preference[] = {
116 - PHY_INTERFACE_MODE_25GBASER,
117 - PHY_INTERFACE_MODE_USXGMII,
118 - PHY_INTERFACE_MODE_10GBASER,
119 - PHY_INTERFACE_MODE_5GBASER,
120 - PHY_INTERFACE_MODE_2500BASEX,
121 - PHY_INTERFACE_MODE_SGMII,
122 - PHY_INTERFACE_MODE_1000BASEX,
123 - PHY_INTERFACE_MODE_100BASEX,
126 -static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces);
128 static phy_interface_t phylink_choose_sfp_interface(struct phylink *pl,
129 const unsigned long *intf)