>From 19a375a81f3dae953410f8da607e89c34095a21c Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 3 Oct 2025 17:20:20 +0300 Subject: [PATCH] net: pcs: lynx: accept in-band autoneg for 2500base-x Testing in two circumstances: 1. back to back optical SFP+ connection between two LS1028A-QDS ports with the SCH-26908 riser card 2. T1042 with on-board AQR115 PHY using "OCSGMII", as per https://lore.kernel.org/lkml/aIuEvaSCIQdJWcZx@FUE-ALEWI-WINX/ strongly suggests that enabling in-band auto-negotiation is actually possible when the lane baud rate is 3.125 Gbps. It was previously thought that this would not be the case, because it was only tested on 2500base-x links with on-board Aquantia PHYs, where it was noticed that MII_LPA is always reported as zero, and it was thought that this is because of the PCS. Test case #1 above shows it is not, and the configured MII_ADVERTISE on system A ends up in the MII_LPA on system B, when in 2500base-x mode (IF_MODE=0). Test case #2, which uses "SGMII" auto-negotiation (IF_MODE=3) for the 3.125 Gbps lane, is actually a misconfiguration, but it is what led to the discovery. There is actually an old bug in the Lynx PCS driver - it expects all register values to contain their default out-of-reset values, as if the PCS were initialized by the Reset Configuration Word (RCW) settings. There are 2 cases in which this is problematic: - if the bootloader (or previous kexec-enabled Linux) wrote a different IF_MODE value - if dynamically changing the SerDes protocol from 1000base-x to 2500base-x, e.g. by replacing the optical SFP module. Specifically in test case #2, an accidental alignment between the bootloader configuring the PCS to expect SGMII in-band code words, and the AQR115 PHY actually transmitting SGMII in-band code words when operating in the "OCSGMII" system interface protocol, led to the PCS transmitting replicated symbols at 3.125 Gbps baud rate. This could only have happened if the PCS saw and reacted to the SGMII code words in the first place. Since test #2 is invalid from a protocol perspective (there seems to be no standard way of negotiating the data rate of 2500 Mbps with SGMII, and the lower data rates should remain 10/100/1000), in-band auto-negotiation for 2500base-x effectively means Clause 37 (i.e. IF_MODE=0). Make 2500base-x be treated like 1000base-x in this regard, by removing all prior limitations and calling lynx_pcs_config_giga(). This adds a new feature: LINK_INBAND_ENABLE and at the same time fixes the Lynx PCS's long standing problem that the registers (specifically IF_MODE, but others could be misconfigured as well) are not written by the driver to the known valid values for 2500base-x. Co-developed-by: Alexander Wilhelm Signed-off-by: Alexander Wilhelm Signed-off-by: Vladimir Oltean --- drivers/net/pcs/pcs-lynx.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c index 677f92883976..a88cbe67cc9d 100644 --- a/drivers/net/pcs/pcs-lynx.c +++ b/drivers/net/pcs/pcs-lynx.c @@ -40,12 +40,12 @@ static unsigned int lynx_pcs_inband_caps(struct phylink_pcs *pcs, { switch (interface) { case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_QSGMII: return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; case PHY_INTERFACE_MODE_10GBASER: - case PHY_INTERFACE_MODE_2500BASEX: return LINK_INBAND_DISABLE; case PHY_INTERFACE_MODE_USXGMII: @@ -152,7 +152,8 @@ static int lynx_pcs_config_giga(struct mdio_device *pcs, mdiodev_write(pcs, LINK_TIMER_HI, link_timer >> 16); } - if (interface == PHY_INTERFACE_MODE_1000BASEX) { + if (interface == PHY_INTERFACE_MODE_1000BASEX || + interface == PHY_INTERFACE_MODE_2500BASEX) { if_mode = 0; } else { /* SGMII and QSGMII */ @@ -202,15 +203,9 @@ static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, case PHY_INTERFACE_MODE_1000BASEX: case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_2500BASEX: return lynx_pcs_config_giga(lynx->mdio, ifmode, advertising, neg_mode); - case PHY_INTERFACE_MODE_2500BASEX: - if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { - dev_err(&lynx->mdio->dev, - "AN not supported on 3.125GHz SerDes lane\n"); - return -EOPNOTSUPP; - } - break; case PHY_INTERFACE_MODE_USXGMII: case PHY_INTERFACE_MODE_10G_QXGMII: return lynx_pcs_config_usxgmii(lynx->mdio, ifmode, advertising, -- 2.34.1