public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: Simon Horman <horms@kernel.org>
To: Vincent Guittot <vincent.guittot@linaro.org>
Cc: vkoul@kernel.org, neil.armstrong@linaro.org, krzk+dt@kernel.org,
	conor+dt@kernel.org, ciprianmarian.costea@oss.nxp.com,
	s32@nxp.com, p.zabel@pengutronix.de, linux@armlinux.org.uk,
	ghennadi.procopciuc@nxp.com, bogdan-gabriel.roman@nxp.com,
	Ionut.Vicovan@nxp.com, alexandru-catalin.ionita@nxp.com,
	linux-phy@lists.infradead.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, netdev@vger.kernel.org,
	Frank.li@nxp.com
Subject: Re: [PATCH 3/4] phy: s32g: Add serdes xpcs subsystem
Date: Thu, 29 Jan 2026 11:59:46 +0000	[thread overview]
Message-ID: <aXtLsuOkMMryrUs4@horms.kernel.org> (raw)
In-Reply-To: <20260126092159.815968-4-vincent.guittot@linaro.org>

On Mon, Jan 26, 2026 at 10:21:58AM +0100, Vincent Guittot wrote:

...

> diff --git a/drivers/phy/freescale/phy-nxp-s32g-serdes.c b/drivers/phy/freescale/phy-nxp-s32g-serdes.c

...

> +static void s32g_serdes_prepare_pma_mode5(struct s32g_serdes *serdes)
> +{
> +	u32 val;
> +	/* Configure TX_VBOOST_LVL and TX_TERM_CTRL */
> +	val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MISC_CTRL_2);
> +	val &= ~(EXT_TX_VBOOST_LVL_MASK | EXT_TX_TERM_CTRL_MASK);
> +	val |= FIELD_PREP(EXT_TX_VBOOST_LVL_MASK, 0x3) |
> +		FIELD_PREP(EXT_TX_TERM_CTRL_MASK, 0x4);
> +	writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MISC_CTRL_2);

This is part of an AI Generated review.
I have looked over it and I think it warrants investigation.
For information on how to reproduce locally, as I did, please see [1].

	The entire s32g_serdes_prepare_pma_mode5() function is ~70 lines of
	magic numbers with zero explanation. These appear to be
	hardware-specific PLL/PHY tuning parameters for 2.5G mode.

Please consider using #defines, to give values names.

...

> +static int s32g_serdes_init_clks(struct s32g_serdes *serdes)
> +{
> +	struct s32g_serdes_ctrl *ctrl = &serdes->ctrl;
> +	struct s32g_xpcs_ctrl *xpcs = &serdes->xpcs;
> +	int ret, order[2], xpcs_id;
> +	size_t i;
> +
> +	switch (ctrl->ss_mode) {
> +	case 0:
> +		return 0;
> +	case 1:
> +		order[0] = 0;
> +		order[1] = XPCS_DISABLED;
> +		break;
> +	case 2:
> +	case 5:
> +		order[0] = 1;
> +		order[1] = XPCS_DISABLED;
> +		break;
> +	case 3:
> +		order[0] = 1;
> +		order[1] = 0;
> +		break;
> +	case 4:
> +		order[0] = 0;
> +		order[1] = 1;
> +		break;
> +	default:
> +		return -EINVAL;

AI review also flags that s32g_serdes_get_ctrl_resources() ensures that
ss_mode is <= 5.  So this check is unnecessary.

> +	}
> +
> +	for (i = 0; i < ARRAY_SIZE(order); i++) {
> +		xpcs_id = order[i];
> +
> +		if (xpcs_id == XPCS_DISABLED)
> +			continue;
> +
> +		ret = s32g_xpcs_init_plls(xpcs->phys[xpcs_id]);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	if (ctrl->ss_mode == 5) {
> +		s32g_serdes_prepare_pma_mode5(serdes);
> +
> +		ret = s32g_xpcs_pre_pcie_2g5(xpcs->phys[1]);

Also from the AI review:

	In mode 5, code directly accesses xpcs->phys[1] without checking if
	it was created. If XPCS1 wasn't created for some reason (DT
	misconfiguration, probe failure), this NULL dereferences.

...

> @@ -460,6 +741,41 @@ static int s32g2_serdes_create_phy(struct s32g_serdes *serdes, struct device_nod

...

> +		xpcs = devm_kmalloc(dev, sizeof(*xpcs), GFP_KERNEL);
> +		if (IS_ERR(xpcs)) {
> +			dev_err(dev, "Failed to allocate xpcs\n");
> +			return -ENOMEM;
> +		}

AI review also flags:

	devm_kmalloc() returns NULL on failure, not an error pointer.
	This check will never trigger.

[1] https://netdev-ai.bots.linux.dev/ai-local.html

> +
> +		xpcs_ctrl->phys[port] = xpcs;
> +
> +		xpcs->an = of_property_read_bool(dev->of_node, "nxp,xpcs_an");

AI review flags that nxp,xpcs_an is not part of the binding.

...

> +struct phylink_pcs *s32g_serdes_pcs_create(struct device *dev, struct device_node *np)
> +{
> +	struct platform_device *pdev;
> +	struct device_node *pcs_np;
> +	struct s32g_serdes *serdes;
> +	u32 port;
> +
> +	if (of_property_read_u32(np, "reg", &port))
> +		return ERR_PTR(-EINVAL);
> +
> +	if (port > S32G_SERDES_XPCS_MAX)
> +		return ERR_PTR(-EINVAL);
> +
> +	/* The PCS pdev is attached to the parent node */
> +	pcs_np = of_get_parent(np);
> +	if (!pcs_np)
> +		return ERR_PTR(-ENODEV);
> +
> +	if (!of_device_is_available(pcs_np)) {
> +		of_node_put(pcs_np);
> +		return ERR_PTR(-ENODEV);
> +	}
> +
> +	pdev = of_find_device_by_node(pcs_np);
> +	of_node_put(pcs_np);
> +	if (!pdev || !platform_get_drvdata(pdev)) {
> +		if (pdev)
> +			put_device(&pdev->dev);
> +		return ERR_PTR(-EPROBE_DEFER);
> +	}
> +
> +	serdes = platform_get_drvdata(pdev);

Also from the AI review:

	On success, the function gets a reference to pdev but never
	releases it. This leaks a device reference every time a MAC driver
	calls s32g_serdes_pcs_create().

> +
> +	return &serdes->xpcs.phys[port]->pcs;

Also from the AI review:

	The check port > S32G_SERDES_XPCS_MAX allows port=2,
	but array only has indices 0 and 1.

Also I'm not seeing bounds checking on port in s32g2_serdes_create_phy
which uses port as an index for the same array both directly and indirectly
via s32g_serdes_xpcs_init().

...

> diff --git a/drivers/phy/freescale/phy-nxp-s32g-xpcs.c b/drivers/phy/freescale/phy-nxp-s32g-xpcs.c

...

> +static int s32g_xpcs_regmap_reg_read(void *context, unsigned int reg,
> +				     unsigned int *result)
> +{
> +	struct s32g_xpcs *xpcs = context;
> +	u16 ofsleft = (reg >> 8) & 0xffffU;
> +	u16 ofsright = (reg & 0xffU);
> +
> +	writew(ofsleft, xpcs->base + ADDR1_OFS);
> +	*result = readw(xpcs->base + (ofsright * 4));
> +
> +	return 0;
> +}
> +
> +static int s32g_xpcs_regmap_reg_write(void *context, unsigned int reg,
> +				      unsigned int val)
> +{
> +	struct s32g_xpcs *xpcs = context;
> +	u16 ofsleft = (reg >> 8) & 0xffffU;
> +	u16 ofsright = (reg & 0xffU);
> +
> +	writew(ofsleft, xpcs->base + ADDR1_OFS);
> +	writew(val, xpcs->base + (ofsright * 4));
> +
> +	return 0;
> +}
> +
> +static const struct regmap_config s32g_xpcs_regmap_config = {
> +	.reg_bits = 16,
> +	.val_bits = 16,
> +	.reg_read = s32g_xpcs_regmap_reg_read,
> +	.reg_write = s32g_xpcs_regmap_reg_write,
> +	.wr_table = &s32g_xpcs_wr_table,
> +	.rd_table = &s32g_xpcs_rd_table,
> +	.max_register = 0x1F80E1,
> +};

AI review also flags that s32g_xpcs_regmap_reg_read and
s32g_xpcs_regmap_reg_write do not protect against concurrent access.

...

  reply	other threads:[~2026-01-29 11:59 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-26  9:21 [PATCH 0/4] Serdes: s32g: Add support for serdes subsystem Vincent Guittot
2026-01-26  9:21 ` [PATCH 1/4] dt-bindings: serdes: s32g: Add NXP " Vincent Guittot
2026-01-29 12:50   ` Russell King (Oracle)
2026-01-29 13:05     ` Vincent Guittot
2026-01-26  9:21 ` [PATCH 2/4] phy: s32g: Add serdes subsystem phy Vincent Guittot
2026-01-26 13:11   ` Philipp Zabel
2026-01-27 10:07     ` Vincent Guittot
2026-01-29  9:54   ` Simon Horman
2026-01-29 13:01     ` Vincent Guittot
2026-01-29 13:23       ` Russell King (Oracle)
2026-01-29 13:36         ` Vincent Guittot
2026-01-29 13:51           ` Russell King (Oracle)
2026-01-29 14:30             ` Vinod Koul
2026-01-29 14:36               ` Russell King (Oracle)
2026-01-30 14:50                 ` Russell King (Oracle)
2026-01-29 11:17   ` Russell King (Oracle)
2026-01-29 13:02     ` Vincent Guittot
2026-01-26  9:21 ` [PATCH 3/4] phy: s32g: Add serdes xpcs subsystem Vincent Guittot
2026-01-29 11:59   ` Simon Horman [this message]
2026-01-29 13:24     ` Vincent Guittot
2026-01-29 16:20       ` Simon Horman
2026-01-29 12:30   ` Russell King (Oracle)
2026-01-29 13:45     ` Vincent Guittot
2026-01-26  9:21 ` [PATCH 4/4] MAINTAINERS: Add MAINTAINER for NXP S32G Serdes driver Vincent Guittot
2026-01-29 12:07   ` Simon Horman
2026-01-29 13:25     ` Vincent Guittot
2026-01-29 12:36 ` [PATCH 0/4] Serdes: s32g: Add support for serdes subsystem Russell King (Oracle)
2026-01-29 13:26   ` Vincent Guittot

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=aXtLsuOkMMryrUs4@horms.kernel.org \
    --to=horms@kernel.org \
    --cc=Frank.li@nxp.com \
    --cc=Ionut.Vicovan@nxp.com \
    --cc=alexandru-catalin.ionita@nxp.com \
    --cc=bogdan-gabriel.roman@nxp.com \
    --cc=ciprianmarian.costea@oss.nxp.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=ghennadi.procopciuc@nxp.com \
    --cc=krzk+dt@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-phy@lists.infradead.org \
    --cc=linux@armlinux.org.uk \
    --cc=neil.armstrong@linaro.org \
    --cc=netdev@vger.kernel.org \
    --cc=p.zabel@pengutronix.de \
    --cc=s32@nxp.com \
    --cc=vincent.guittot@linaro.org \
    --cc=vkoul@kernel.org \
    /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