All of lore.kernel.org
 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

WARNING: multiple messages have this Message-ID (diff)
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

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

Thread overview: 91+ 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 ` Jan Petrous (OSS)
2026-09-19  6:54 ` 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-19  6:54   ` Jan Petrous (OSS)
2026-09-19  6:54   ` Jan Petrous via B4 Relay
2026-09-20  6:54   ` sashiko-bot
2026-09-20  6:54     ` sashiko-bot
2026-10-12 18:57   ` Frank Li
2026-10-12 18:57     ` Frank Li
2026-10-13 14:40     ` Jan Petrous
2026-10-13 14:40       ` Jan Petrous
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-19  6:54   ` Jan Petrous (OSS)
2026-09-19  6:54   ` Jan Petrous via B4 Relay
2026-09-20  6:54   ` sashiko-bot
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-19  6:54   ` Jan Petrous (OSS)
2026-09-19  6:54   ` Jan Petrous via B4 Relay
2026-09-20  6:54   ` sashiko-bot
2026-09-20  6:54     ` sashiko-bot
2026-10-12 18:43   ` Frank Li
2026-10-12 18:43     ` Frank Li
2026-10-13 14:37     ` Jan Petrous
2026-10-13 14:37       ` Jan Petrous
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  6:54   ` Jan Petrous (OSS)
2026-09-19  6:54   ` Jan Petrous via B4 Relay
2026-09-19 15:31   ` Maxime Chevallier
2026-09-19 15:31     ` Maxime Chevallier
2026-09-19 16:31     ` Coia Prant
2026-09-19 16:31       ` Coia Prant
2026-10-11  6:01     ` Jan Petrous
2026-10-11  6:01       ` Jan Petrous
2026-10-12 19:47       ` Coia Prant
2026-10-12 19:47         ` Coia Prant
2026-10-13 14:47         ` Jan Petrous
2026-10-13 14:47           ` Jan Petrous
2026-09-20  6:54   ` sashiko-bot
2026-09-20  6:54     ` sashiko-bot
2026-09-20 18:39   ` Andrew Lunn
2026-09-20 18:39     ` Andrew Lunn
2026-10-11  6:03     ` Jan Petrous
2026-10-11  6:03       ` Jan Petrous
2026-09-19  6:54 ` [PATCH RFC v3 05/12] net: pcs: Add NXP S32G XPCS driver Jan Petrous via B4 Relay
2026-09-19  6:54   ` Jan Petrous (OSS)
2026-09-19  6:54   ` Jan Petrous via B4 Relay
2026-09-20  6:54   ` sashiko-bot
2026-09-20  6:54     ` sashiko-bot
2026-09-20 17:07   ` Andrew Lunn
2026-09-20 17:07     ` Andrew Lunn
2026-10-11  5:56     ` Jan Petrous
2026-10-11  5:56       ` Jan Petrous
2026-09-19  6:54 ` [PATCH RFC v3 06/12] phy: freescale: s32g: Add SerDes subsystem PHY Jan Petrous via B4 Relay
2026-09-19  6:54   ` Jan Petrous (OSS)
2026-09-19  6:54   ` Jan Petrous via B4 Relay
2026-09-20  6:54   ` sashiko-bot [this message]
2026-09-20  6:54     ` sashiko-bot
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  6:54   ` Jan Petrous (OSS)
2026-09-19  6:54   ` Jan Petrous via B4 Relay
2026-09-19 12:04   ` Maxime Chevallier
2026-09-19 12:04     ` Maxime Chevallier
2026-10-11  5:53     ` Jan Petrous
2026-10-11  5:53       ` Jan Petrous
2026-09-20  6:54   ` sashiko-bot
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   ` Jan Petrous (OSS)
2026-09-19  6:54   ` 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-19  6:54   ` Jan Petrous (OSS)
2026-09-19  6:54   ` Jan Petrous via B4 Relay
2026-09-20  6:54   ` sashiko-bot
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-19  6:54   ` Jan Petrous (OSS)
2026-09-19  6:54   ` Jan Petrous via B4 Relay
2026-09-20  6:55   ` sashiko-bot
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-19  6:54   ` Jan Petrous (OSS)
2026-09-19  6:54   ` Jan Petrous via B4 Relay
2026-09-20  6:55   ` sashiko-bot
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-19  6:54   ` Jan Petrous (OSS)
2026-09-19  6:54   ` Jan Petrous via B4 Relay
2026-09-20  6:55   ` sashiko-bot
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.