[PATCH net-next v2 00/14] net: stmmac: SerDes, PCS, BASE-X, and inband goodies
Russell King (Oracle)
linux at armlinux.org.uk
Fri Jan 23 13:32:21 PST 2026
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!
More information about the linux-arm-kernel
mailing list