Linux kernel and device drivers for NXP i.MX platforms
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Jan Petrous (OSS)" <jan.petrous@oss.nxp.com>
Cc: linux-pci@vger.kernel.org, vkoul@kernel.org,
	neil.armstrong@linaro.org, olteanv@gmail.com,
	linux-phy@lists.infradead.org, Frank.Li@kernel.org,
	conor+dt@kernel.org, wsa+renesas@sang-engineering.com,
	robh@kernel.org, imx@lists.linux.dev, devicetree@vger.kernel.org
Subject: Re: [PATCH RFC v3 06/12] phy: freescale: s32g: Add SerDes subsystem PHY
Date: Sun, 20 Sep 2026 06:54:56 +0000	[thread overview]
Message-ID: <20260920065456.99D951F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260919-s32g_serdes-v3-6-9d68868c1e89@oss.nxp.com>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] mm: Use-After-Free in s32g_serdes_pcs_create() via lockless drvdata access
- [High] driver: Race condition exposing PHY provider before hardware initialization
- [High] pm: Sleep in atomic context via noirq sleep callbacks
- [Medium] driver: Infinite probe deferral on unconfigured XPCS instance
- [Medium] pm: Missing resource cleanup on resume error path
--

commit 179aba95589906304ef5b4ba6f8b771475155fa2
Author: Vincent Guittot <vincent.guittot@linaro.org>

    phy: freescale: s32g: Add SerDes subsystem PHY

    The S32G SoC family includes two SerDes subsystems, each made of one
    PCIe controller, two XPCS and a shared 2-lane combo PHY. The lanes can
    be configured to carry PCIe and/or SGMII.
    
    Add the SerDes subsystem PHY driver: the PCIe PHY, the shared combo-PHY
    bring-up, and the setup of the XPCS instances added by the previous
    patch.

> diff --git a/drivers/phy/freescale/phy-nxp-s32g-serdes.c b/drivers/phy/freescale/phy-nxp-s32g-serdes.c
> new file mode 100644
> index 0000000000000..e81878137f2e1
> --- /dev/null
> +++ b/drivers/phy/freescale/phy-nxp-s32g-serdes.c
> @@ -0,0 +1,1057 @@

[ ... ]

> +static int s32g_serdes_init(struct s32g_serdes *serdes)
> +{
> +	struct s32g_serdes_ctrl *ctrl = &serdes->ctrl;
> +	u32 reg0;
> +	int ret;
> +
> +	ret = clk_bulk_prepare_enable(ctrl->nclks, ctrl->clks);
> +	if (ret) {
> +		dev_err(serdes->dev, "Failed to enable SerDes clocks\n");
> +		return ret;
> +	}

[ ... ]

> +	/* Wait for the selection of working mode (as per the manual specs) */
> +	usleep_range(100, 110);

[ ... ]

> +static int s32g_serdes_create_pcie_phy(struct s32g_serdes *serdes,
> +				       struct device_node *child_node)
> +{
> +	struct phy_provider *phy_provider;
> +	struct device *dev = serdes->dev;
> +	struct phy *phy;
> +
> +	phy = devm_phy_create(dev, child_node, &serdes_pcie_ops);
> +	if (IS_ERR(phy))
> +		return PTR_ERR(phy);
> +
> +	phy_set_drvdata(phy, serdes);
> +
> +	phy->attrs.mode = PHY_MODE_PCIE;
> +	serdes->pcie.phy = phy;
> +
> +	phy_provider = devm_of_phy_provider_register(&phy->dev,
> +						     s32g_serdes_phy_xlate);

[Severity: High]
Does this expose the PHY provider before the hardware is initialized? 

s32g_serdes_parse_lanes() registers the PHY provider via 
devm_of_phy_provider_register(), making it visible to consumers. The hardware 
clocks and resets aren't initialized until s32g_serdes_init() is called later 
in s32g_serdes_probe(). 

If a consumer probes concurrently and calls phy_power_on(), could it access 
unclocked registers and cause a synchronous external abort?

> +	if (IS_ERR(phy_provider))
> +		return PTR_ERR(phy_provider);
> +
> +	return 0;
> +}

[ ... ]

> +static int s32g_serdes_probe(struct platform_device *pdev)
> +{

[ ... ]

> +	ret = s32g_serdes_parse_lanes(dev, serdes);
> +	if (ret)
> +		return ret;

[ ... ]

> +	ret = s32g_serdes_init(serdes);
> +	if (ret)
> +		return ret;

[ ... ]

> +static int s32g_serdes_resume(struct device *device)
> +{
> +	struct s32g_serdes *serdes = dev_get_drvdata(device);
> +	struct s32g_pcie_ctrl *pcie = &serdes->pcie;
> +	int ret;
> +
> +	ret = s32g_serdes_init(serdes);
> +	if (ret) {
> +		dev_err(device, "Failed to initialize\n");
> +		return ret;
> +	}
> +
> +	/* Restore PCIe phy power */
> +	if (pcie->powered_on) {
> +		ret = s32g_pcie_phy_power_on(serdes);
> +		if (ret)
> +			dev_err(device, "Failed to power-on PCIe phy\n");
> +	}
> +
> +	return ret;

[Severity: Medium]
Does this leak clock resources on the error path?

If s32g_pcie_phy_power_on() fails, the function returns an error without 
undoing the hardware initialization performed earlier in s32g_serdes_init(). 
The PM core will mark the device as having failed to resume, but the leaked 
clock enables might prevent the power domain from fully shutting down.

> +}

[ ... ]

> +struct phylink_pcs *s32g_serdes_pcs_create(struct device *dev,
> +					   struct device_node *np)
> +{

[ ... ]

> +	serdes = platform_get_drvdata(pdev);
> +	if (!serdes) {
> +		put_device(&pdev->dev);
> +		return ERR_PTR(-EPROBE_DEFER);
> +	}

[Severity: High]
Can this race with driver unbind leading to a use-after-free?

This function is exposed to consumer drivers and reads drvdata locklessly. 
If the SerDes driver is unbound concurrently via sysfs, 
dev_set_drvdata(dev, NULL) is called and the devm_kzalloc'd serdes 
structure is freed by devres. 

If platform_get_drvdata() reads the pointer just before the unbind, won't 
accessing serdes->xpcs.phys[instance] below dereference freed memory?

> +
> +	if (!serdes->xpcs.phys[instance]) {
> +		put_device(&pdev->dev);
> +		return ERR_PTR(-EPROBE_DEFER);

[Severity: Medium]
Will this cause an infinite probe deferral loop if the instance is unconfigured?

If the SerDes has probed successfully (meaning drvdata is non-NULL) but 
intentionally did not populate serdes->xpcs.phys[instance] due to lane 
configuration mismatch, this instance will never be populated. Would it be 
better to return an error rather than -EPROBE_DEFER in this case?

> +	}

[ ... ]

> +/* noirq, like the PCIe controller using this PHY */
> +static const struct dev_pm_ops s32g_serdes_pm_ops = {
> +	NOIRQ_SYSTEM_SLEEP_PM_OPS(s32g_serdes_suspend,
> +				  s32g_serdes_resume)

[Severity: High]
Does this call sleepable functions in an atomic context?

The driver assigns s32g_serdes_resume() to the .resume_noirq callback, which 
executes with hardware interrupts disabled. However, s32g_serdes_resume() calls 
s32g_serdes_init(), which invokes clk_bulk_prepare_enable() (takes a mutex) 
and usleep_range() (sleeps via hrtimers).

> +};

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260919-s32g_serdes-v3-0-9d68868c1e89@oss.nxp.com?part=6

  reply	other threads:[~2026-09-20  6:54 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-19  6:54 [PATCH RFC v3 00/12] Add support for the NXP S32G SerDes subsystem Jan Petrous via B4 Relay
2026-09-19  6:54 ` [PATCH RFC v3 01/12] dt-bindings: phy: Add " Jan Petrous via B4 Relay
2026-09-20  6:54   ` sashiko-bot
2026-09-19  6:54 ` [PATCH RFC v3 02/12] dt-bindings: net: nxp,s32-dwmac: Document pcs-handle Jan Petrous via B4 Relay
2026-09-20  6:54   ` sashiko-bot
2026-09-19  6:54 ` [PATCH RFC v3 03/12] dt-bindings: PCI: nxp,s32g-pcie: Fix SerDes PHY phandle in example Jan Petrous via B4 Relay
2026-09-20  6:54   ` sashiko-bot
2026-09-19  6:54 ` [PATCH RFC v3 04/12] net: pcs: add NXP SerDes XPCS shared core Jan Petrous via B4 Relay
2026-09-19 15:31   ` Maxime Chevallier
2026-09-19 16:31     ` Coia Prant
2026-09-20  6:54   ` sashiko-bot
2026-09-20 18:39   ` Andrew Lunn
2026-09-19  6:54 ` [PATCH RFC v3 05/12] net: pcs: Add NXP S32G XPCS driver Jan Petrous via B4 Relay
2026-09-20  6:54   ` sashiko-bot
2026-09-20 17:07   ` Andrew Lunn
2026-09-19  6:54 ` [PATCH RFC v3 06/12] phy: freescale: s32g: Add SerDes subsystem PHY Jan Petrous via B4 Relay
2026-09-20  6:54   ` sashiko-bot [this message]
2026-09-19  6:54 ` [PATCH RFC v3 07/12] net: stmmac: dwmac-s32: Add SGMII support Jan Petrous via B4 Relay
2026-09-19 12:04   ` Maxime Chevallier
2026-09-20  6:54   ` sashiko-bot
2026-09-19  6:54 ` [PATCH RFC v3 08/12] MAINTAINERS: Add NXP S32G SerDes and SerDes xPCS core entries Jan Petrous via B4 Relay
2026-09-19  6:54 ` [PATCH RFC v3 09/12] arm64: dts: s32g: Add SCMI reset controller Jan Petrous via B4 Relay
2026-09-20  6:54   ` sashiko-bot
2026-09-19  6:54 ` [PATCH RFC v3 10/12] arm64: dts: s32g: Add SerDes controller nodes Jan Petrous via B4 Relay
2026-09-20  6:55   ` sashiko-bot
2026-09-19  6:54 ` [PATCH RFC v3 11/12] arm64: dts: s32g: Add PCIe " Jan Petrous via B4 Relay
2026-09-20  6:55   ` sashiko-bot
2026-09-19  6:54 ` [PATCH RFC v3 12/12] arm64: dts: s32g: Add S32G3-RDB3 SerDes routing variants Jan Petrous via B4 Relay
2026-09-20  6:55   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260920065456.99D951F000FF@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=imx@lists.linux.dev \
    --cc=jan.petrous@oss.nxp.com \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-phy@lists.infradead.org \
    --cc=neil.armstrong@linaro.org \
    --cc=olteanv@gmail.com \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=vkoul@kernel.org \
    --cc=wsa+renesas@sang-engineering.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox