* [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii
@ 2026-08-24 10:36 Patryk Biel
2026-08-25 21:49 ` Vladimir Oltean
2026-08-27 8:55 ` Vladimir Oltean
0 siblings, 2 replies; 10+ messages in thread
From: Patryk Biel @ 2026-08-24 10:36 UTC (permalink / raw)
To: Ioana Ciornei, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: netdev, linux-kernel, Vladimir Oltean, Patryk Biel
The Lynx PCS USXGMII setup programs the replicator advertisement, but
does not explicitly enable and restart in-band autonegotiation or program
the replicator link timers.
This leaves the PCS dependent on firmware or bootloader state. Systems
which do not get the USXGMII replicator preconfigured before Linux may
therefore fail to negotiate the link correctly.
After programming the USXGMII device ability, configure the replicator
BMCR with reset, autonegotiation enable and autonegotiation restart. Also
program the replicator link timer registers with the values used by the
ENETC/Felix setup.
Signed-off-by: Patryk Biel <pbiel7@gmail.com>
---
This is a follow-up to the discussion started here:
Link: https://lore.kernel.org/netdev/CA+DkFDaW_wJ5p9_P7pMpz-8iE6xeKkdF-MQcd2m2GcyVUE3S4Q@mail.gmail.com/
To summarize: on systems that don't rely on the U-Boot Felix switch
driver to pre-configure 10G-QXGMII in-band autonegotiation, the Lynx
PCS USXGMII code programs the replicator device ability but never
actually enables/restarts autonegotiation nor sets up the replicator
link timers. This leaves link establishment dependent on bootloader
state that isn't guaranteed to exist.
This series only addresses the PCS side of the problem: it configures
the USXGMII replicator BMCR (reset/AN enable/AN restart) and the link
timer registers whenever lynx_pcs_config_usxgmii() is called, so that
in-band AN comes up correctly regardless of what the bootloader did.
It intentionally does NOT yet remove the "only supports in-band AN for
now" limitation, nor does it wire up neg_mode-based configuration to
support the managed = "in-band-status" property being absent from the
device tree. That part still needs more work/testing on my side (in
particular the in-band-disable path isn't behaving as expected yet
with the PHY I'm testing against), and I'd like to discuss the right
approach for it separately before sending a follow-up series.
Feedback welcome, especially on whether this is an acceptable
incremental step or whether it should be bundled together with the
neg_mode/in-band-disable work
---
Changes in v2:
- Reorder local variable declarations in lynx_pcs_config_usxgmii().
- Move USXGMII replicator link timer configuration before the autonegotiation restart.
- Use phylink_get_link_timer_ns() instead of hardcoded USXGMII
replicator link timer values, converting to 3.2 ns register step.
- Link to v1: https://lore.kernel.org/r/20260820-b4-fix-pcs-lynx-an-v1-1-62d66391eaff@gmail.com
---
drivers/net/pcs/pcs-lynx.c | 47 ++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 43 insertions(+), 4 deletions(-)
diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c
index a92081560e641ad2b297b7395cc72bf2f59ea16c..564c8a3d2b06fde92a249308f955566d6baac36f 100644
--- a/drivers/net/pcs/pcs-lynx.c
+++ b/drivers/net/pcs/pcs-lynx.c
@@ -20,6 +20,9 @@
#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))
+
struct lynx_pcs {
struct phylink_pcs pcs;
struct mdio_device *mdio;
@@ -156,6 +159,9 @@ static int lynx_pcs_config_usxgmii(struct mdio_device *pcs,
{
struct mii_bus *bus = pcs->bus;
int addr = pcs->addr;
+ int link_timer_ns;
+ u32 link_timer;
+ int ret;
if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) {
dev_err(&pcs->dev, "%s only supports in-band AN for now\n",
@@ -164,10 +170,43 @@ static int lynx_pcs_config_usxgmii(struct mdio_device *pcs,
}
/* Configure device ability for the USXGMII Replicator */
- return mdiobus_c45_write(bus, addr, MDIO_MMD_VEND2, MII_ADVERTISE,
- MDIO_USXGMII_10G | MDIO_USXGMII_LINK |
- MDIO_USXGMII_FULL_DUPLEX |
- ADVERTISE_SGMII | ADVERTISE_LPACK);
+ ret = mdiobus_c45_write(bus, addr, MDIO_MMD_VEND2, MII_ADVERTISE,
+ MDIO_USXGMII_10G | MDIO_USXGMII_LINK |
+ MDIO_USXGMII_FULL_DUPLEX |
+ ADVERTISE_SGMII | ADVERTISE_LPACK);
+ if (ret < 0) {
+ dev_err(&pcs->dev, "could not set USXGMII replicator config\n");
+ return ret;
+ }
+
+ link_timer_ns = phylink_get_link_timer_ns(interface);
+ if (link_timer_ns > 0) {
+ link_timer = USXGMII_LINK_TIMER_VAL(link_timer_ns);
+
+ ret = mdiobus_c45_write(bus, addr, MDIO_MMD_VEND2,
+ LINK_TIMER_LO, link_timer & 0xffff);
+ if (ret < 0) {
+ dev_err(&pcs->dev, "could not set USXGMII Link Timer 1\n");
+ return ret;
+ }
+
+ ret = mdiobus_c45_write(bus, addr, MDIO_MMD_VEND2,
+ LINK_TIMER_HI, (link_timer >> 16) & 0x1f);
+ if (ret < 0) {
+ dev_err(&pcs->dev, "could not set USXGMII Link Timer 2\n");
+ return ret;
+ }
+ }
+
+ /* Configure autonegotiation */
+ ret = mdiobus_c45_write(bus, addr, MDIO_MMD_VEND2, MII_BMCR,
+ BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART);
+ if (ret < 0) {
+ dev_err(&pcs->dev, "could not set USXGMII replicator control config\n");
+ return ret;
+ }
+
+ return ret;
}
static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
---
base-commit: 7cbfb180945ce529608e4d4e24a6d483699fab1e
change-id: 20260820-b4-fix-pcs-lynx-an-3fd1d5e94ce6
Best regards,
--
Patryk Biel <pbiel7@gmail.com>
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii
2026-08-24 10:36 [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii Patryk Biel
@ 2026-08-25 21:49 ` Vladimir Oltean
2026-08-26 7:37 ` Patryk Biel
2026-08-27 8:55 ` Vladimir Oltean
1 sibling, 1 reply; 10+ messages in thread
From: Vladimir Oltean @ 2026-08-25 21:49 UTC (permalink / raw)
To: Patryk Biel
Cc: Ioana Ciornei, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
netdev, linux-kernel, Vladimir Oltean
Hi,
On Mon, Aug 24, 2026 at 12:36:12PM +0200, Patryk Biel wrote:
> The Lynx PCS USXGMII setup programs the replicator advertisement, but
> does not explicitly enable and restart in-band autonegotiation or program
> the replicator link timers.
>
> This leaves the PCS dependent on firmware or bootloader state. Systems
> which do not get the USXGMII replicator preconfigured before Linux may
> therefore fail to negotiate the link correctly.
>
> After programming the USXGMII device ability, configure the replicator
> BMCR with reset, autonegotiation enable and autonegotiation restart. Also
> program the replicator link timer registers with the values used by the
> ENETC/Felix setup.
>
> Signed-off-by: Patryk Biel <pbiel7@gmail.com>
> ---
> This is a follow-up to the discussion started here:
>
> Link: https://lore.kernel.org/netdev/CA+DkFDaW_wJ5p9_P7pMpz-8iE6xeKkdF-MQcd2m2GcyVUE3S4Q@mail.gmail.com/
>
> To summarize: on systems that don't rely on the U-Boot Felix switch
> driver to pre-configure 10G-QXGMII in-band autonegotiation, the Lynx
> PCS USXGMII code programs the replicator device ability but never
> actually enables/restarts autonegotiation nor sets up the replicator
> link timers. This leaves link establishment dependent on bootloader
> state that isn't guaranteed to exist.
>
> This series only addresses the PCS side of the problem: it configures
> the USXGMII replicator BMCR (reset/AN enable/AN restart) and the link
> timer registers whenever lynx_pcs_config_usxgmii() is called, so that
> in-band AN comes up correctly regardless of what the bootloader did.
>
> It intentionally does NOT yet remove the "only supports in-band AN for
> now" limitation, nor does it wire up neg_mode-based configuration to
> support the managed = "in-band-status" property being absent from the
> device tree. That part still needs more work/testing on my side (in
> particular the in-band-disable path isn't behaving as expected yet
> with the PHY I'm testing against), and I'd like to discuss the right
> approach for it separately before sending a follow-up series.
>
> Feedback welcome, especially on whether this is an acceptable
> incremental step or whether it should be bundled together with the
> neg_mode/in-band-disable work
> ---
> Changes in v2:
> - Reorder local variable declarations in lynx_pcs_config_usxgmii().
> - Move USXGMII replicator link timer configuration before the autonegotiation restart.
> - Use phylink_get_link_timer_ns() instead of hardcoded USXGMII
> replicator link timer values, converting to 3.2 ns register step.
> - Link to v1: https://lore.kernel.org/r/20260820-b4-fix-pcs-lynx-an-v1-1-62d66391eaff@gmail.com
> ---
> drivers/net/pcs/pcs-lynx.c | 47 ++++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 43 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c
> index a92081560e641ad2b297b7395cc72bf2f59ea16c..564c8a3d2b06fde92a249308f955566d6baac36f 100644
> --- a/drivers/net/pcs/pcs-lynx.c
> +++ b/drivers/net/pcs/pcs-lynx.c
> @@ -20,6 +20,9 @@
> #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))
> +
> struct lynx_pcs {
> struct phylink_pcs pcs;
> struct mdio_device *mdio;
> @@ -156,6 +159,9 @@ static int lynx_pcs_config_usxgmii(struct mdio_device *pcs,
> {
> struct mii_bus *bus = pcs->bus;
> int addr = pcs->addr;
> + int link_timer_ns;
> + u32 link_timer;
> + int ret;
>
> if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) {
> dev_err(&pcs->dev, "%s only supports in-band AN for now\n",
> @@ -164,10 +170,43 @@ static int lynx_pcs_config_usxgmii(struct mdio_device *pcs,
> }
>
> /* Configure device ability for the USXGMII Replicator */
> - return mdiobus_c45_write(bus, addr, MDIO_MMD_VEND2, MII_ADVERTISE,
> - MDIO_USXGMII_10G | MDIO_USXGMII_LINK |
> - MDIO_USXGMII_FULL_DUPLEX |
> - ADVERTISE_SGMII | ADVERTISE_LPACK);
> + ret = mdiobus_c45_write(bus, addr, MDIO_MMD_VEND2, MII_ADVERTISE,
> + MDIO_USXGMII_10G | MDIO_USXGMII_LINK |
> + MDIO_USXGMII_FULL_DUPLEX |
> + ADVERTISE_SGMII | ADVERTISE_LPACK);
> + if (ret < 0) {
> + dev_err(&pcs->dev, "could not set USXGMII replicator config\n");
> + return ret;
> + }
> +
> + link_timer_ns = phylink_get_link_timer_ns(interface);
> + if (link_timer_ns > 0) {
> + link_timer = USXGMII_LINK_TIMER_VAL(link_timer_ns);
> +
> + ret = mdiobus_c45_write(bus, addr, MDIO_MMD_VEND2,
> + LINK_TIMER_LO, link_timer & 0xffff);
> + if (ret < 0) {
> + dev_err(&pcs->dev, "could not set USXGMII Link Timer 1\n");
> + return ret;
> + }
> +
> + ret = mdiobus_c45_write(bus, addr, MDIO_MMD_VEND2,
> + LINK_TIMER_HI, (link_timer >> 16) & 0x1f);
> + if (ret < 0) {
> + dev_err(&pcs->dev, "could not set USXGMII Link Timer 2\n");
> + return ret;
> + }
> + }
> +
> + /* Configure autonegotiation */
> + ret = mdiobus_c45_write(bus, addr, MDIO_MMD_VEND2, MII_BMCR,
> + BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART);
> + if (ret < 0) {
> + dev_err(&pcs->dev, "could not set USXGMII replicator control config\n");
> + return ret;
> + }
> +
> + return ret;
> }
>
> static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
>
> ---
> base-commit: 7cbfb180945ce529608e4d4e24a6d483699fab1e
> change-id: 20260820-b4-fix-pcs-lynx-an-3fd1d5e94ce6
>
> Best regards,
> --
> Patryk Biel <pbiel7@gmail.com>
>
>
There are some problems with this patch on
arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dtso (AQR412C PHY).
[ 63.529426] mscc_felix 0000:00:00.5: Unsupported speed on port 0: -1
[ 63.529454] mscc_felix 0000:00:00.5 swp0: Link is Up - Unknown/Unknown - flow control off
(and traffic doesn't pass)
There are multiple differences compared to U-Boot does. I haven't yet
been able to definitively determine the cause for regression. I'll debug
more tomorrow. Preliminary testing shows that any link timer values > 0.84 ms
will cause in-band autoneg to not complete with this combination.
To be clear, does your board work with this patch?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii
2026-08-25 21:49 ` Vladimir Oltean
@ 2026-08-26 7:37 ` Patryk Biel
2026-08-26 15:36 ` Vladimir Oltean
0 siblings, 1 reply; 10+ messages in thread
From: Patryk Biel @ 2026-08-26 7:37 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Ioana Ciornei, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
netdev, linux-kernel, Vladimir Oltean
Hi Vladimir,
On Tue, Aug 25, 2026 at 11:49 PM Vladimir Oltean <olteanv@gmail.com> wrote:
> There are multiple differences compared to U-Boot does. I haven't yet
> been able to definitively determine the cause for regression. I'll debug
> more tomorrow. Preliminary testing shows that any link timer values > 0.84 ms
> will cause in-band autoneg to not complete with this combination.
>
> To be clear, does your board work with this patch?
Yes I tested it, I can provide you any logs you would find useful.
Below is just a short log from interface bring up and simple iperf3
test:
root@tru-:~# ip link set up swp0
[ 60.159618] mscc_felix 0000:00:00.5 swp0: configuring for
inband/10g-qxgmii link mode
[ 63.308354] mscc_felix 0000:00:00.5 swp0: Link is Up - 1Gbps/Full -
flow control off
root@tru-:~# ip addr add 192.168.10.2/24 dev swp0
root@tru-:~# iperf3 -s 192.168.10.2
-----------------------------------------------------------
Server listening on 5201 (test #1)
-----------------------------------------------------------
Accepted connection from 192.168.10.1, port 44470
[ 5] local 192.168.10.2 port 5201 connected to 192.168.10.1 port 44484
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 111 MBytes 933 Mbits/sec
[ 5] 1.00-2.00 sec 111 MBytes 934 Mbits/sec
[ 5] 2.00-3.00 sec 112 MBytes 935 Mbits/sec
[ 5] 3.00-4.00 sec 111 MBytes 934 Mbits/sec
[ 5] 4.00-5.00 sec 111 MBytes 934 Mbits/sec
[ 5] 5.00-6.00 sec 111 MBytes 934 Mbits/sec
[ 5] 6.00-7.00 sec 111 MBytes 934 Mbits/sec
[ 5] 7.00-8.00 sec 111 MBytes 934 Mbits/sec
[ 5] 8.00-9.00 sec 111 MBytes 934 Mbits/sec
[ 5] 9.00-10.00 sec 111 MBytes 934 Mbits/sec
[ 5] 10.00-10.24 sec 2.25 MBytes 77.7 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.24 sec 1.09 GBytes 914 Mbits/sec receiver
Will also try to find out what could possibly go wrong.
Best regards
Patryk
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii
2026-08-26 7:37 ` Patryk Biel
@ 2026-08-26 15:36 ` Vladimir Oltean
2026-08-27 8:59 ` Patryk Biel
0 siblings, 1 reply; 10+ messages in thread
From: Vladimir Oltean @ 2026-08-26 15:36 UTC (permalink / raw)
To: Patryk Biel
Cc: Vladimir Oltean, Ioana Ciornei, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, netdev, linux-kernel
On Wed, Aug 26, 2026 at 09:37:45AM +0200, Patryk Biel wrote:
> Hi Vladimir,
>
> On Tue, Aug 25, 2026 at 11:49 PM Vladimir Oltean <olteanv@gmail.com> wrote:
> > There are multiple differences compared to U-Boot does. I haven't yet
> > been able to definitively determine the cause for regression. I'll debug
> > more tomorrow. Preliminary testing shows that any link timer values > 0.84 ms
> > will cause in-band autoneg to not complete with this combination.
> >
> > To be clear, does your board work with this patch?
>
> Yes I tested it, I can provide you any logs you would find useful.
> Below is just a short log from interface bring up and simple iperf3
> test:
>
> root@tru-:~# ip link set up swp0
> [ 60.159618] mscc_felix 0000:00:00.5 swp0: configuring for
> inband/10g-qxgmii link mode
> [ 63.308354] mscc_felix 0000:00:00.5 swp0: Link is Up - 1Gbps/Full -
> flow control off
> root@tru-:~# ip addr add 192.168.10.2/24 dev swp0
> root@tru-:~# iperf3 -s 192.168.10.2
> -----------------------------------------------------------
> Server listening on 5201 (test #1)
> -----------------------------------------------------------
> Accepted connection from 192.168.10.1, port 44470
> [ 5] local 192.168.10.2 port 5201 connected to 192.168.10.1 port 44484
> [ ID] Interval Transfer Bitrate
> [ 5] 0.00-1.00 sec 111 MBytes 933 Mbits/sec
> [ 5] 1.00-2.00 sec 111 MBytes 934 Mbits/sec
> [ 5] 2.00-3.00 sec 112 MBytes 935 Mbits/sec
> [ 5] 3.00-4.00 sec 111 MBytes 934 Mbits/sec
> [ 5] 4.00-5.00 sec 111 MBytes 934 Mbits/sec
> [ 5] 5.00-6.00 sec 111 MBytes 934 Mbits/sec
> [ 5] 6.00-7.00 sec 111 MBytes 934 Mbits/sec
> [ 5] 7.00-8.00 sec 111 MBytes 934 Mbits/sec
> [ 5] 8.00-9.00 sec 111 MBytes 934 Mbits/sec
> [ 5] 9.00-10.00 sec 111 MBytes 934 Mbits/sec
> [ 5] 10.00-10.24 sec 2.25 MBytes 77.7 Mbits/sec
> - - - - - - - - - - - - - - - - - - - - - - - - -
> [ ID] Interval Transfer Bitrate
> [ 5] 0.00-10.24 sec 1.09 GBytes 914 Mbits/sec receiver
>
> Will also try to find out what could possibly go wrong.
>
> Best regards
> Patryk
Thanks for confirming.
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?
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);
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii
2026-08-24 10:36 [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii Patryk Biel
2026-08-25 21:49 ` Vladimir Oltean
@ 2026-08-27 8:55 ` Vladimir Oltean
2026-08-27 9:13 ` Patryk Biel
1 sibling, 1 reply; 10+ messages in thread
From: Vladimir Oltean @ 2026-08-27 8:55 UTC (permalink / raw)
To: Patryk Biel
Cc: Ioana Ciornei, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
netdev, linux-kernel
On Mon, Aug 24, 2026 at 12:36:12PM +0200, Patryk Biel wrote:
> The Lynx PCS USXGMII setup programs the replicator advertisement, but
> does not explicitly enable and restart in-band autonegotiation or program
> the replicator link timers.
>
> This leaves the PCS dependent on firmware or bootloader state. Systems
> which do not get the USXGMII replicator preconfigured before Linux may
> therefore fail to negotiate the link correctly.
>
> After programming the USXGMII device ability, configure the replicator
> BMCR with reset, autonegotiation enable and autonegotiation restart. Also
> program the replicator link timer registers with the values used by the
> ENETC/Felix setup.
>
> Signed-off-by: Patryk Biel <pbiel7@gmail.com>
> ---
> This is a follow-up to the discussion started here:
>
> Link: https://lore.kernel.org/netdev/CA+DkFDaW_wJ5p9_P7pMpz-8iE6xeKkdF-MQcd2m2GcyVUE3S4Q@mail.gmail.com/
>
> To summarize: on systems that don't rely on the U-Boot Felix switch
> driver to pre-configure 10G-QXGMII in-band autonegotiation, the Lynx
> PCS USXGMII code programs the replicator device ability but never
> actually enables/restarts autonegotiation nor sets up the replicator
> link timers. This leaves link establishment dependent on bootloader
> state that isn't guaranteed to exist.
>
> This series only addresses the PCS side of the problem: it configures
> the USXGMII replicator BMCR (reset/AN enable/AN restart) and the link
> timer registers whenever lynx_pcs_config_usxgmii() is called, so that
> in-band AN comes up correctly regardless of what the bootloader did.
>
> It intentionally does NOT yet remove the "only supports in-band AN for
> now" limitation, nor does it wire up neg_mode-based configuration to
> support the managed = "in-band-status" property being absent from the
> device tree. That part still needs more work/testing on my side (in
> particular the in-band-disable path isn't behaving as expected yet
> with the PHY I'm testing against), and I'd like to discuss the right
> approach for it separately before sending a follow-up series.
>
> Feedback welcome, especially on whether this is an acceptable
> incremental step or whether it should be bundled together with the
> neg_mode/in-band-disable work
Furthermore, you don't need such a long text under ---, it will be
discarded when applying the patch. Fold whatever information isn't
duplicated in the commit message and drop the rest.
It is acceptable as an incremental step because logically, it is a
different change compared to also supporting PHYLINK_PCS_NEG_INBAND_DISABLED.
No matter whether you also submit that or not, they would still be
separate patches.
I guess the more important question is: do you also plan to submit a
PHYLINK_PCS_NEG_INBAND_DISABLED patch? Any problems there?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii
2026-08-26 15:36 ` Vladimir Oltean
@ 2026-08-27 8:59 ` Patryk Biel
2026-08-27 9:18 ` Vladimir Oltean
0 siblings, 1 reply; 10+ messages in thread
From: Patryk Biel @ 2026-08-27 8:59 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Vladimir Oltean, Ioana Ciornei, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, netdev, linux-kernel
Hi,
On Wed, Aug 26, 2026 at 5:36 PM Vladimir Oltean <vladimir.oltean@nxp.com> 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.
> 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
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii
2026-08-27 8:55 ` Vladimir Oltean
@ 2026-08-27 9:13 ` Patryk Biel
2026-08-27 9:48 ` Vladimir Oltean
0 siblings, 1 reply; 10+ messages in thread
From: Patryk Biel @ 2026-08-27 9:13 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Ioana Ciornei, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
netdev, linux-kernel
Hi,
On Thu, Aug 27, 2026 at 10:55 AM Vladimir Oltean
<vladimir.oltean@nxp.com> wrote:
> Furthermore, you don't need such a long text under ---, it will be
> discarded when applying the patch. Fold whatever information isn't
> duplicated in the commit message and drop the rest.
>
> It is acceptable as an incremental step because logically, it is a
> different change compared to also supporting PHYLINK_PCS_NEG_INBAND_DISABLED.
> No matter whether you also submit that or not, they would still be
> separate patches.
>
> I guess the more important question is: do you also plan to submit a
> PHYLINK_PCS_NEG_INBAND_DISABLED patch? Any problems there?
Yes I plan to submit this patch also, however I'm still working on
disabling in-band autoneg on phy side as the procedure is not clearly
described and I'm trying to recreate it from vendor's sdk code, and
it's not that easy as the sdk carries I believe support for all their
phys.
However I also have one question regarding
PHYLINK_PCS_NEG_INBAND_DISABLED on the host side. I planned to discuss
it separately however, since you brought up this topic here, I would
like to discuss one thing that is not clear for me and as you are the
expert in this domain, perhaps you would be able to give me some
hints. Looking at the lynx_pcs_link_up_sgmii, once the neg_mode
differs from PHYLINK_PCS_NEG_INBAND_ENABLED, the IF_MODE register is
explicitly programmed with speed and duplex values. I browsed through
the manual but did not find any similar register for 10g-qxgmii. This
may just be due to my limited understanding of this area, but is this
intentional? There is no need to epicly program speed and mode for 10g
qxmgii with in-band autoneg off?
Given all of the above, I just wanted to add that I'll be on vacation
for three weeks starting at the beginning of September.
So if you'd prefer to send these changes yourself before then, please
don't let me be a blocker.
Best regards
Patryk
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii
2026-08-27 8:59 ` Patryk Biel
@ 2026-08-27 9:18 ` Vladimir Oltean
0 siblings, 0 replies; 10+ messages in thread
From: Vladimir Oltean @ 2026-08-27 9:18 UTC (permalink / raw)
To: Patryk Biel
Cc: Vladimir Oltean, Ioana Ciornei, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, netdev, linux-kernel
On Thu, Aug 27, 2026 at 10:59:40AM +0200, Patryk Biel wrote:
> I tested it and it keeps working fine. Logs below, but there is
> nothing new compared to the previous test.
That's great news.
I've started a discussion internally, hoping to get a confirmation from
the design team that our documentation is indeed wrong.
> Given your other email, for v3, I understand that I should retarget
> the patch from net to net-next.
Yeah.
> 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?
No, why would we introduce a bug only to fix it later? The AQR412C
systems must continue to work, so you'd have to fold my change into
yours. Per Documentation/process/submitting-patches.rst, you may use
Co-developed-by: and Signed-off-by: to also credit me for that part of
the change, if you wish.
But note that net-next is currently closed due to the merge window.
https://lore.kernel.org/netdev/20260816155953.072d73da@kernel.org/
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii
2026-08-27 9:13 ` Patryk Biel
@ 2026-08-27 9:48 ` Vladimir Oltean
2026-08-27 10:18 ` Patryk Biel
0 siblings, 1 reply; 10+ messages in thread
From: Vladimir Oltean @ 2026-08-27 9:48 UTC (permalink / raw)
To: Patryk Biel
Cc: Ioana Ciornei, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
netdev, linux-kernel
On Thu, Aug 27, 2026 at 11:13:15AM +0200, Patryk Biel wrote:
> Hi,
>
> On Thu, Aug 27, 2026 at 10:55 AM Vladimir Oltean
> <vladimir.oltean@nxp.com> wrote:
> > Furthermore, you don't need such a long text under ---, it will be
> > discarded when applying the patch. Fold whatever information isn't
> > duplicated in the commit message and drop the rest.
> >
> > It is acceptable as an incremental step because logically, it is a
> > different change compared to also supporting PHYLINK_PCS_NEG_INBAND_DISABLED.
> > No matter whether you also submit that or not, they would still be
> > separate patches.
> >
> > I guess the more important question is: do you also plan to submit a
> > PHYLINK_PCS_NEG_INBAND_DISABLED patch? Any problems there?
>
> Yes I plan to submit this patch also, however I'm still working on
> disabling in-band autoneg on phy side as the procedure is not clearly
> described and I'm trying to recreate it from vendor's sdk code, and
> it's not that easy as the sdk carries I believe support for all their
> phys.
> However I also have one question regarding
> PHYLINK_PCS_NEG_INBAND_DISABLED on the host side. I planned to discuss
> it separately however, since you brought up this topic here, I would
> like to discuss one thing that is not clear for me and as you are the
> expert in this domain, perhaps you would be able to give me some
> hints.
As they say, an expert is someone who has made all the mistakes in one
area. I've definitely made a lot of mistakes, but I'm not sure I'm quite
there yet :-/
> Looking at the lynx_pcs_link_up_sgmii, once the neg_mode
> differs from PHYLINK_PCS_NEG_INBAND_ENABLED, the IF_MODE register is
> explicitly programmed with speed and duplex values. I browsed through
> the manual but did not find any similar register for 10g-qxgmii. This
> may just be due to my limited understanding of this area, but is this
> intentional? There is no need to epicly program speed and mode for 10g
> qxmgii with in-band autoneg off?
Yes, I suppose there should be.
I also don't see a register in the MDIO address space.
I do see QXGMIIaCR2 field USX_FORCE_SPD, but that's in the SerDes
protocol converter wrapper space (which is handled by
drivers/phy/freescale/phy-fsl-lynx-10g.c), so that's a bit unfortunate.
Looking at this register, it's not clear to me how individual 10G-QXGMII
ports could have their speeds forced individually to different values.
The single register handles the entire multi-port protocol converter,
it's not like QXGMIIaCR4-QXGMIIaCR7 which are per port.
This is something else I'll have to ask internally.
> Given all of the above, I just wanted to add that I'll be on vacation
> for three weeks starting at the beginning of September.
> So if you'd prefer to send these changes yourself before then, please
> don't let me be a blocker.
That's fine, I'll also have some vacation time during the same interval,
you can submit the work to net-next when you return.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii
2026-08-27 9:48 ` Vladimir Oltean
@ 2026-08-27 10:18 ` Patryk Biel
0 siblings, 0 replies; 10+ messages in thread
From: Patryk Biel @ 2026-08-27 10:18 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Ioana Ciornei, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
netdev, linux-kernel
On Thu, Aug 27, 2026 at 11:48 AM Vladimir Oltean
<vladimir.oltean@nxp.com> wrote:
> > Looking at the lynx_pcs_link_up_sgmii, once the neg_mode
> > differs from PHYLINK_PCS_NEG_INBAND_ENABLED, the IF_MODE register is
> > explicitly programmed with speed and duplex values. I browsed through
> > the manual but did not find any similar register for 10g-qxgmii. This
> > may just be due to my limited understanding of this area, but is this
> > intentional? There is no need to epicly program speed and mode for 10g
> > qxmgii with in-band autoneg off?
>
> Yes, I suppose there should be.
>
> I also don't see a register in the MDIO address space.
>
> I do see QXGMIIaCR2 field USX_FORCE_SPD, but that's in the SerDes
> protocol converter wrapper space (which is handled by
> drivers/phy/freescale/phy-fsl-lynx-10g.c), so that's a bit unfortunate.
>
> Looking at this register, it's not clear to me how individual 10G-QXGMII
> ports could have their speeds forced individually to different values.
> The single register handles the entire multi-port protocol converter,
> it's not like QXGMIIaCR4-QXGMIIaCR7 which are per port.
> This is something else I'll have to ask internally.
This is exactly where I ended up with my research as well, and I had
similar thoughts. I would be grateful if you could let me know if you
find out anything more about this.
> > Given all of the above, I just wanted to add that I'll be on vacation
> > for three weeks starting at the beginning of September.
> > So if you'd prefer to send these changes yourself before then, please
> > don't let me be a blocker.
>
> That's fine, I'll also have some vacation time during the same interval,
> you can submit the work to net-next when you return.
Okay, great. I'll prepare v3 then and submit it once net-next reopens
after the merge window.
Best regards
Patryk
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-08-27 10:19 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-24 10:36 [PATCH net v2] net: pcs: enable autonegotiation for 10g-usxgmii Patryk Biel
2026-08-25 21:49 ` Vladimir Oltean
2026-08-26 7:37 ` Patryk Biel
2026-08-26 15:36 ` Vladimir Oltean
2026-08-27 8:59 ` Patryk Biel
2026-08-27 9:18 ` Vladimir Oltean
2026-08-27 8:55 ` Vladimir Oltean
2026-08-27 9:13 ` Patryk Biel
2026-08-27 9:48 ` Vladimir Oltean
2026-08-27 10:18 ` Patryk Biel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox