The lynx_28g_pll_get function may return NULL when called with an
unsupported submode argument.
This function is only called from the lynx_28g_lane_set_{10gbaser,sgmii}
functions, and lynx_28g_set_mode checks available modes before setting a
protocol.
NXP vendor kernel based on v6.6.52 however is missing any checks and
connecting a 2.5/5gbase-t ethernet phy can cause null pointer
dereference [1].
Check return value at every invocation and abort in the unlikely error
case. Further print a warning message the first time lynx_28g_pll_get
returns null, to catch this case should it occur after future changes.
[1]
[ 127.019924] fsl_dpaa2_eth dpni.4 eth5: dpmac_set_protocol(2500base-x) = -ENOTSUPP
[ 127.027451] Unable to handle kernel NULL pointer dereference at virtual address
0000000000000014
[ 127.036245] Mem abort info:
[ 127.039044] ESR = 0x0000000096000004
[ 127.042794] EC = 0x25: DABT (current EL), IL = 32 bits
[ 127.048107] SET = 0, FnV = 0
[ 127.051161] EA = 0, S1PTW = 0
[ 127.054301] FSC = 0x04: level 0 translation fault
[ 127.059179] Data abort info:
[ 127.062059] ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
[ 127.067547] CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[ 127.072596] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[ 127.077907] user pgtable: 4k pages, 48-bit VAs, pgdp=
00000020816c9000
[ 127.084344] [
0000000000000014] pgd=
0000000000000000, p4d=
0000000000000000
[ 127.091133] Internal error: Oops:
0000000096000004 [#1] PREEMPT SMP
[ 127.097390] Modules linked in: cfg80211 rfkill fsl_jr_uio caam_jr dpaa2_caam caamkeyblob_desc crypto_engine caamhash_desc onboard_usb_hub caamalg_desc crct10dif_ce libdes caam error at24 rtc_ds1307 rtc_fsl_ftm_alarm nvmem_layerscape_sfp layerscape_edac_mod dm_mod nfnetlink ip_tables
[ 127.122436] CPU: 5 PID: 96 Comm: kworker/u35:0 Not tainted
6.6.52-g3578ef896722 #10
[ 127.130083] Hardware name: SolidRun LX2162A Clearfog (DT)
[ 127.135470] Workqueue: events_power_efficient phylink_resolve
[ 127.141219] pstate:
60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 127.148170] pc : lynx_28g_set_lane_mode+0x300/0x818
[ 127.153041] lr : lynx_28g_set_lane_mode+0x2fc/0x818
[ 127.157909] sp :
ffff8000806f3b80
[ 127.161212] x29:
ffff8000806f3b80 x28:
0000000000000000 x27:
0000000000000000
[ 127.168340] x26:
ffff29d6c11f3098 x25:
0000000000000000 x24:
0000000000000000
[ 127.175467] x23:
ffff29d6c11f31f0 x22:
ffff29d6c11f3080 x21:
0000000000000001
[ 127.182595] x20:
ffff29d6c11f4c00 x19:
0000000000000000 x18:
0000000000000006
[ 127.189722] x17:
4f4e452d203d2029 x16:
782d657361623030 x15:
3532286c6f636f74
[ 127.196849] x14:
6f72705f7465735f x13:
ffffd7a8ff991cc0 x12:
0000000000000acb
[ 127.203976] x11:
0000000000000399 x10:
ffffd7a8ff9e9cc0 x9 :
0000000000000000
[ 127.211104] x8 :
0000000000000000 x7 :
0000000000000000 x6 :
ffff29d6c11f3080
[ 127.218231] x5 :
0000000000000000 x4 :
0000000040800030 x3 :
000000000000034c
[ 127.225358] x2 :
ffff29d6c11f3080 x1 :
000000000000034c x0 :
0000000000000000
[ 127.232486] Call trace:
[ 127.234921] lynx_28g_set_lane_mode+0x300/0x818
[ 127.239443] lynx_28g_set_mode+0x12c/0x148
[ 127.243529] phy_set_mode_ext+0x5c/0xa8
[ 127.247356] lynx_pcs_config+0x64/0x294
[ 127.251184] phylink_major_config+0x184/0x49c
[ 127.255532] phylink_resolve+0x2a0/0x5d8
[ 127.259446] process_one_work+0x138/0x248
[ 127.263448] worker_thread+0x320/0x438
[ 127.267187] kthread+0x114/0x118
[ 127.270406] ret_from_fork+0x10/0x20
[ 127.273973] Code:
2a1303e1 aa0603e0 97fffd3b aa0003e5 (
b9401400)
[ 127.280055] ---[ end trace
0000000000000000 ]---
Signed-off-by: Josua Mayer <josua@solid-run.com>
Link: https://lore.kernel.org/r/20250826-lynx-28g-nullptr-v1-1-e4de0098f822@solid-run.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
return pll;
}
+ /* no pll supports requested mode, either caller forgot to check
+ * lynx_28g_supports_lane_mode, or this is a bug.
+ */
+ dev_WARN_ONCE(priv->dev, 1, "no pll for interface %s\n", phy_modes(intf));
return NULL;
}
lynx_28g_lane_rmw(lane, LNaGCR0, PROTO_SEL_SGMII, PROTO_SEL_MSK);
lynx_28g_lane_rmw(lane, LNaGCR0, IF_WIDTH_10_BIT, IF_WIDTH_MSK);
- /* Switch to the PLL that works with this interface type */
+ /* Find the PLL that works with this interface type */
pll = lynx_28g_pll_get(priv, PHY_INTERFACE_MODE_SGMII);
+ if (unlikely(pll == NULL))
+ return;
+
+ /* Switch to the PLL that works with this interface type */
lynx_28g_lane_set_pll(lane, pll);
/* Choose the portion of clock net to be used on this lane */
lynx_28g_lane_rmw(lane, LNaGCR0, PROTO_SEL_XFI, PROTO_SEL_MSK);
lynx_28g_lane_rmw(lane, LNaGCR0, IF_WIDTH_20_BIT, IF_WIDTH_MSK);
- /* Switch to the PLL that works with this interface type */
+ /* Find the PLL that works with this interface type */
pll = lynx_28g_pll_get(priv, PHY_INTERFACE_MODE_10GBASER);
+ if (unlikely(pll == NULL))
+ return;
+
+ /* Switch to the PLL that works with this interface type */
lynx_28g_lane_set_pll(lane, pll);
/* Choose the portion of clock net to be used on this lane */