mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-23 15:32:33 +00:00
131 lines
4.6 KiB
Diff
131 lines
4.6 KiB
Diff
|
From 8f7a9799c5949f94ecc3acfd71b36437a7ade73b Mon Sep 17 00:00:00 2001
|
||
|
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||
|
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 <quic_luoj@quicinc.com>
|
||
|
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||
|
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||
|
Link: https://lore.kernel.org/r/E1r6VIV-00DDMF-Pi@rmk-PC.armlinux.org.uk
|
||
|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||
|
---
|
||
|
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
|
||
|
@@ -1779,6 +1792,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.
|
||
|
*/
|
||
|
@@ -3047,19 +3101,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)
|
||
|
{
|