Re: [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii
From: Patryk Biel <hidden>
Date: 2026-08-27 08:59:56
Also in:
lkml
Hi, On Wed, Aug 26, 2026 at 5:36 PM Vladimir Oltean [off-list ref] wrote:
I suspect our documentation is wrong, in that both for USXGMII and for 10G-QXGMII, we have the same text: Set the Link Timer value from 0 to 6.4ms in 3.2ns steps (312.5MHz clock periods or 312.5 million XGMII columns per second). The reset value sets the Link Timer to 1ms (312500). But when you think about it, 10G-QXGMII multiplexes 4 ports over the same lane. So each XGMII receives one block at 1/4 the rate of the lane, because of the time slicing. Consequently, by my logic, the PCS link timer, which uses the rate of those columns to keep track of time, *can't* have the same link timer tick for both the single-port as for the multi-port mode. I was suspicious of the link timer limit I obtained (263050 ticks, corresponding to the ~0.84 ms I was talking about yesterday). Higher than that, and the AQR412C system side autoneg would restart (and a PHY counter would continuously increase, indicating this). Furthermore, the AQR412C system side PCS would never lose block lock. So I wanted to see whether an ENETC, using the single-port USXGMII mode, could also make its AQR112 PHY to fail in-band autoneg in the same way. And surprise, I could, by increasing the link timer to 1037500 ticks. Surprisingly (or not), the maximum # of link timer ticks for USXGMII is 3.94x the maximum # of link timer ticks for 10G-QXGMII. So actually, I suspect that when we program a link_timer of LINK_TIMER_VAL(1600000 ns) on 10G-QXGMII, in reality this results in a link timer of 6.4 ms. And my AQR412C doesn't like a value this large. The above is pure speculation/intuition, but it's the only thing that seems to be consistent with all data so far. The only unknown is - why does your PHY tolerate a link timer value that the AQR412C doesn't, and will it work when we set the link timer to 1/4 that value?
That sounds plausible to me, especially given the ~4x difference you measured between USXGMII and 10G-QXGMII. I hadn't considered the effect of the time slicing on the link timer before.
quoted hunk ↗ jump to hunk
Could you please test the diff below, which should give us the info to the second question?diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c index 305740b577fc..735ef4069a7f 100644 --- a/drivers/net/pcs/pcs-lynx.c +++ b/drivers/net/pcs/pcs-lynx.c@@ -24,8 +24,11 @@ #define IF_MODE_SPEED_MSK GENMASK(3, 2) #define IF_MODE_HALF_DUPLEX BIT(4) -/* USXGMII replicator link timer step is 3.2 ns (312.5 MHz clock) */ -#define USXGMII_LINK_TIMER_VAL(ns) ((u32)((ns) * 10 / 32)) +/* USXGMII replicator link timer step is 3.2 ns (312.5M XGMII columns per sec) + * for single port mode. For quad port mode, it is 1/4 of that. + */ +#define LINK_TIMER_VAL_USXGMII(ns) ((u32)((ns) * 10 / 32)) +#define LINK_TIMER_VAL_10G_QXGMII(ns) ((u32)((ns) * 10 / 128)) struct lynx_pcs { struct phylink_pcs pcs;@@ -187,7 +190,10 @@ static int lynx_pcs_config_usxgmii(struct mdio_device *pcs, link_timer_ns = phylink_get_link_timer_ns(interface); if (link_timer_ns > 0) { - link_timer = USXGMII_LINK_TIMER_VAL(link_timer_ns); + if (interface == PHY_INTERFACE_MODE_10G_QXGMII) + link_timer = LINK_TIMER_VAL_10G_QXGMII(link_timer_ns); + else + link_timer = LINK_TIMER_VAL_USXGMII(link_timer_ns); ret = mdiobus_c45_write(bus, addr, MDIO_MMD_VEND2, LINK_TIMER_LO, link_timer & 0xffff);
I tested it and it keeps working fine. Logs below, but there is nothing new compared to the previous test. Given your other email, for v3, I understand that I should retarget the patch from net to net-next. I'm just not sure how you'd prefer to handle your changes. Should I fold them into my patch for v3, or are you planning to send them separately? root@tru-:~# ip link set up swp0 [ 134.191267] mscc_felix 0000:00:00.5 swp0: configuring for inband/10g-qxgmii link mode [ 137.215349] mscc_felix 0000:00:00.5 swp0: Link is Up - 1Gbps/Full - flow control off Best regards Patryk