Skip to content

Commit f56ce54

Browse files
vladimirolteanNipaLocal
authored andcommitted
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 <alexander.wilhelm@westermo.com> Signed-off-by: Alexander Wilhelm <alexander.wilhelm@westermo.com> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: NipaLocal <nipa@local>
1 parent 25285eb commit f56ce54

File tree

1 file changed

+5
-72
lines changed

1 file changed

+5
-72
lines changed

drivers/net/pcs/pcs-lynx.c

Lines changed: 5 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ static unsigned int lynx_pcs_inband_caps(struct phylink_pcs *pcs,
4040
{
4141
switch (interface) {
4242
case PHY_INTERFACE_MODE_1000BASEX:
43+
case PHY_INTERFACE_MODE_2500BASEX:
4344
case PHY_INTERFACE_MODE_SGMII:
4445
case PHY_INTERFACE_MODE_QSGMII:
4546
return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
4647

4748
case PHY_INTERFACE_MODE_10GBASER:
48-
case PHY_INTERFACE_MODE_2500BASEX:
4949
return LINK_INBAND_DISABLE;
5050

5151
case PHY_INTERFACE_MODE_USXGMII:
@@ -80,41 +80,18 @@ static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs,
8080
phylink_decode_usxgmii_word(state, lpa);
8181
}
8282

83-
static void lynx_pcs_get_state_2500basex(struct mdio_device *pcs,
84-
struct phylink_link_state *state)
85-
{
86-
int bmsr;
87-
88-
bmsr = mdiodev_read(pcs, MII_BMSR);
89-
if (bmsr < 0) {
90-
state->link = false;
91-
return;
92-
}
93-
94-
state->link = !!(bmsr & BMSR_LSTATUS);
95-
state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE);
96-
if (!state->link)
97-
return;
98-
99-
state->speed = SPEED_2500;
100-
state->pause |= MLO_PAUSE_TX | MLO_PAUSE_RX;
101-
state->duplex = DUPLEX_FULL;
102-
}
103-
10483
static void lynx_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
10584
struct phylink_link_state *state)
10685
{
10786
struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);
10887

10988
switch (state->interface) {
11089
case PHY_INTERFACE_MODE_1000BASEX:
90+
case PHY_INTERFACE_MODE_2500BASEX:
11191
case PHY_INTERFACE_MODE_SGMII:
11292
case PHY_INTERFACE_MODE_QSGMII:
11393
phylink_mii_c22_pcs_get_state(lynx->mdio, neg_mode, state);
11494
break;
115-
case PHY_INTERFACE_MODE_2500BASEX:
116-
lynx_pcs_get_state_2500basex(lynx->mdio, state);
117-
break;
11895
case PHY_INTERFACE_MODE_USXGMII:
11996
case PHY_INTERFACE_MODE_10G_QXGMII:
12097
lynx_pcs_get_state_usxgmii(lynx->mdio, state);
@@ -152,7 +129,8 @@ static int lynx_pcs_config_giga(struct mdio_device *pcs,
152129
mdiodev_write(pcs, LINK_TIMER_HI, link_timer >> 16);
153130
}
154131

155-
if (interface == PHY_INTERFACE_MODE_1000BASEX) {
132+
if (interface == PHY_INTERFACE_MODE_1000BASEX ||
133+
interface == PHY_INTERFACE_MODE_2500BASEX) {
156134
if_mode = 0;
157135
} else {
158136
/* SGMII and QSGMII */
@@ -202,15 +180,9 @@ static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
202180
case PHY_INTERFACE_MODE_1000BASEX:
203181
case PHY_INTERFACE_MODE_SGMII:
204182
case PHY_INTERFACE_MODE_QSGMII:
183+
case PHY_INTERFACE_MODE_2500BASEX:
205184
return lynx_pcs_config_giga(lynx->mdio, ifmode, advertising,
206185
neg_mode);
207-
case PHY_INTERFACE_MODE_2500BASEX:
208-
if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
209-
dev_err(&lynx->mdio->dev,
210-
"AN not supported on 3.125GHz SerDes lane\n");
211-
return -EOPNOTSUPP;
212-
}
213-
break;
214186
case PHY_INTERFACE_MODE_USXGMII:
215187
case PHY_INTERFACE_MODE_10G_QXGMII:
216188
return lynx_pcs_config_usxgmii(lynx->mdio, ifmode, advertising,
@@ -271,42 +243,6 @@ static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs,
271243
if_mode);
272244
}
273245

274-
/* 2500Base-X is SerDes protocol 7 on Felix and 6 on ENETC. It is a SerDes lane
275-
* clocked at 3.125 GHz which encodes symbols with 8b/10b and does not have
276-
* auto-negotiation of any link parameters. Electrically it is compatible with
277-
* a single lane of XAUI.
278-
* The hardware reference manual wants to call this mode SGMII, but it isn't
279-
* really, since the fundamental features of SGMII:
280-
* - Downgrading the link speed by duplicating symbols
281-
* - Auto-negotiation
282-
* are not there.
283-
* The speed is configured at 1000 in the IF_MODE because the clock frequency
284-
* is actually given by a PLL configured in the Reset Configuration Word (RCW).
285-
* Since there is no difference between fixed speed SGMII w/o AN and 802.3z w/o
286-
* AN, we call this PHY interface type 2500Base-X. In case a PHY negotiates a
287-
* lower link speed on line side, the system-side interface remains fixed at
288-
* 2500 Mbps and we do rate adaptation through pause frames.
289-
*/
290-
static void lynx_pcs_link_up_2500basex(struct mdio_device *pcs,
291-
unsigned int neg_mode,
292-
int speed, int duplex)
293-
{
294-
u16 if_mode = 0;
295-
296-
if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
297-
dev_err(&pcs->dev, "AN not supported for 2500BaseX\n");
298-
return;
299-
}
300-
301-
if (duplex == DUPLEX_HALF)
302-
if_mode |= IF_MODE_HALF_DUPLEX;
303-
if_mode |= IF_MODE_SPEED(SGMII_SPEED_2500);
304-
305-
mdiodev_modify(pcs, IF_MODE,
306-
IF_MODE_HALF_DUPLEX | IF_MODE_SPEED_MSK,
307-
if_mode);
308-
}
309-
310246
static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
311247
phy_interface_t interface,
312248
int speed, int duplex)
@@ -318,9 +254,6 @@ static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
318254
case PHY_INTERFACE_MODE_QSGMII:
319255
lynx_pcs_link_up_sgmii(lynx->mdio, neg_mode, speed, duplex);
320256
break;
321-
case PHY_INTERFACE_MODE_2500BASEX:
322-
lynx_pcs_link_up_2500basex(lynx->mdio, neg_mode, speed, duplex);
323-
break;
324257
case PHY_INTERFACE_MODE_USXGMII:
325258
case PHY_INTERFACE_MODE_10G_QXGMII:
326259
/* At the moment, only in-band AN is supported for USXGMII

0 commit comments

Comments
 (0)