From: Nathan Rossi <nathan.ro...@digi.com>

The mv88e6xxx devices cannot automatically select between 1000BASE-X and
2500BASE-X and rely on configuration (gpio pins Px_SMODE/S_MODE and/or
OF phy-mode) to select between the two modes.

However when configuring a cpu/dsa port as 1000BASE-X with a inband or
fixed link phy the mode is always overridden to 2500BASE-X by the call of
phylink_helper_basex_speed in phylink_validate due to the order of setup
with respect to advertised modes and auto negotiation being enabled.

During the initial setup of the phy the phy-mode property defined for
the port is configured before any calls to phylink_validate. The first
call to phylink_validate sets the advertised modes to all valid modes
and phylink_validate masks to supported modes, for the ports that
support 1000BASE-X/2500BASE-X both are advertised. At this stage the
speed is not yet configured and the phylink_helper_basex_speed function
overrides the mode to 2500BASE-X due to all modes being advertised and
auto negotiation being enabled. After the speed is configured
phylink_validate is called again, the same logic applies and the mode is
set to 2500BASE-X (due to auto negotiation).

As such it is not possible for a fixed link to be configured as
1000BASE-X, as the mode cannot be configured (e.g. via phy-mode
property) and the link cannot be automatically selected as 1000BASE-X.

This change prevents the advertising of 2500BASE-X when the port is
already configured for 1000BASE-X, which in turn prevents the
phylink_helper_basex_speed from always overriding to 2500BASE-X. This
allows for the mode to correctly propagate from the phy-mode property to
the port configuration.

Signed-off-by: Nathan Rossi <nathan.ro...@digi.com>
---
 drivers/net/dsa/mv88e6xxx/chip.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 54aa942eed..5c52906b29 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -650,6 +650,13 @@ static void mv88e6xxx_validate(struct dsa_switch *ds, int 
port,
        if (chip->info->ops->phylink_validate)
                chip->info->ops->phylink_validate(chip, port, mask, state);
 
+       /* Advertise 2500BASEX only if 1000BASEX is not configured, this
+        * prevents phylink_helper_basex_speed from always overriding the
+        * 1000BASEX mode since auto negotiation is always enabled.
+        */
+       if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
+               phylink_clear(mask, 2500baseX_Full);
+
        bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS);
        bitmap_and(state->advertising, state->advertising, mask,
                   __ETHTOOL_LINK_MODE_MASK_NBITS);
---
2.30.0

Reply via email to