Subject: Re: [PATCH net-next v2 00/14] net: stmmac: SerDes, PCS, BASE-X, and inband goodies

From: "Russell King (Oracle)" <[email-masked]>
Date: Fri, 23 Jan 2026 21:32:21 +0000

On Fri, Jan 23, 2026 at 07:05:00PM +0530, Mohd Ayaan Anwar wrote:
> 4. Switching from 1G to 2.5G - similar issues + a NULL pointer
> dereference. I am checking on the reason for it.

For the NULL pointer dereference, this is a bit weird, and may help to
point towards the issue.

> 	[ 1235.996004] qcom-ethqos 23040000.ethernet eth1: phy link down 2500base-x/Unknown/Unknown/none/off/nolpi
> 	[ 1240.517716] qcom-ethqos 23040000.ethernet eth1: phy link up 2500base-x/2.5Gbps/Full/none/off/nolpi
> 	[ 1240.529470] qcom-ethqos 23040000.ethernet eth1: major config, requested phy/2500base-x
> 	[ 1240.537642] qcom-ethqos 23040000.ethernet eth1: interface 2500base-x inband modes: pcs=00 phy=00
> 	[ 1240.546702] qcom-ethqos 23040000.ethernet eth1: major config, active phy/outband/2500base-x
> 	[ 1240.555441] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010

> 	[ 1240.880168] Code: d63f0020 f9400e60 b4000040 f900081f (f9000ad3)

This code line disassembles to:

   0:   d63f0020        blr     x1
   4:   f9400e60        ldr     x0, [x19, #24]
   8:   b4000040        cbz     x0, 10 <.text+0x10>
   c:   f900081f        str     xzr, [x0, #16]
  10:   f9000ad3        str     x19, [x22, #16]

which, after comparing with my disassembly, the blr x1 is the call to
pcs_disable() inside phylink_pcs_disable() in this code:

        if (pcs_changed) {
                phylink_pcs_disable(pl->pcs);

                if (pl->pcs)
                        pl->pcs->phylink = NULL;

                pcs->phylink = pl;

and the failing store is the one for that last line of C code - in
other words, pcs = NULL.

This means that mac_select_pcs() returned NULL when being asked
"which PCS should be used for 2500base-X" ?

This suggests that the SerDes detection of support for 2500BASE-X
isn't working, meaning that stmmac_mac_select_pcs() ends up returning
NULL, rather than &priv->integrated_pcs->pcs.

That would only happen if:

                /* Only allow 2500Base-X if the SerDes has support. */
                ret = dwmac_serdes_validate(priv, PHY_INTERFACE_MODE_2500BASEX);
                if (ret == 0)
                        __set_bit(PHY_INTERFACE_MODE_2500BASEX,
                                  spcs->pcs.supported_interfaces);

fails, meaning we don't set that interface mode for the PCS.
dwmac_serdes_validate() calls phy_validate() for PHY_MODE_ETHERNET
with the PHY interface mode as the sub mode.

Patch 3 adds the required methods to phy-qcom-sgmii-eth.c to allow
phy_validate() to indicate whether this is supported or not:

        .validate       = qcom_dwmac_sgmii_phy_validate,

and its implementation is:

        int ret = qcom_dwmac_sgmii_phy_speed(mode, submode);

        return ret < 0 ? ret : 0;

where qcom_dwmac_sgmii_phy_speed() is:

        if (mode != PHY_MODE_ETHERNET)
                return -EINVAL;

        if (submode == PHY_INTERFACE_MODE_SGMII ||
            submode == PHY_INTERFACE_MODE_1000BASEX)
                return SPEED_1000;

        if (submode == PHY_INTERFACE_MODE_2500BASEX)
                return SPEED_2500;

        return -EINVAL;

So, this should be returning a positive integer (SPEED_2500), which
should cause phy_validate(serdes, PHY_MODE_ETHERNET,
PHY_INTERFACE_MODE_2500BASEX, NULL) to return success (zero). That
should result in PHY_INTERFACE_MODE_2500BASEX being set in
spcs->pcs.supported_interfaces, and thus &priv->integrated_pcs->pcs
being returned for PHY_INTERFACE_MODE_2500BASEX.

Is the particular hardware you're running this oopsing test on not
using a SerDes PHY? If that's the case, how does it switch between
2.5Gbps and 1Gbps data rate on the SerDes?

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!