From: sashiko-bot@kernel.org
To: "Kartik Rajput" <kkartik@nvidia.com>
Cc: robh@kernel.org, olteanv@gmail.com, neil.armstrong@linaro.org,
linux-phy@lists.infradead.org, conor+dt@kernel.org,
devicetree@vger.kernel.org, vkoul@kernel.org
Subject: Re: [PATCH 2/2] phy: tegra: Add Tegra264 MPHY driver
Date: Wed, 09 Sep 2026 09:54:19 +0000 [thread overview]
Message-ID: <20260909095419.C30C81F00A3D@smtp.kernel.org> (raw)
In-Reply-To: <20260909-tegra264-mphy-v1-2-ce61a80dc065@nvidia.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Data race on shared `mphy->power_count` and clock state across multiple PHY instances.
- [High] TX PHY lacks power management operations, creating a fragile API contract that risks system crashes.
- [High] Wrong base address pointer used for `MPHY_RX_APB_CAPABILITY` registers.
- [Medium] Missing reset assertion for `mphy->rst_clk_ctl` in the normal `tegra_mphy_rx_power_off` path.
--
commit bceb08380e03847a80ce77db39c3ff271cbccb0c
Author: Kartik Rajput <kkartik@nvidia.com>
phy: tegra: Add Tegra264 MPHY driver
Add a driver for the MIPI M-PHY found on NVIDIA Tegra264 SoCs. The
M-PHY has two lanes, each with a transmit and a receive direction,
exposed as four PHYs to the UFS host controller.
> diff --git a/drivers/phy/tegra/phy-tegra-mphy.c b/drivers/phy/tegra/phy-tegra-mphy.c
> index 0000000000000..01cafe1c7477f
> --- /dev/null
> +++ b/drivers/phy/tegra/phy-tegra-mphy.c
[ ... ]
> +static int tegra_mphy_rx_power_on(struct phy *phy)
> +{
> + struct tegra_mphy *mphy = dev_get_drvdata(phy->dev.parent);
> + struct tegra_mphy_lane *lane = phy_get_drvdata(phy);
> + u32 value;
> + int err;
> +
> + if (mphy->power_count++ == 0) {
^^^^^^^^^^^^^^^^^^^^^^^
[Severity: High]
Since l0 and l1 are distinct PHY instances exposed to the consumer, can
concurrent phy_power_on() or phy_power_off() calls race on this shared
mphy->power_count?
The PHY framework's internal mutex only serializes operations on a per-PHY
basis. An unprotected read-modify-write here could lead to corrupted
reference counts, unbalanced clock states, and hardware faults.
> + err = clk_bulk_prepare_enable(mphy->num_clks, mphy->clks);
> + if (err) {
> + mphy->power_count--;
> + dev_err(&phy->dev, "failed to enable clocks: %d\n", err);
> + return err;
> + }
> + reset_control_deassert(mphy->rst_clk_ctl);
> + }
> +
> + reset_control_deassert(lane->rst_rx);
> + reset_control_deassert(lane->rst_tx);
^^^^^^^^^^^^^^^^^^^^
[Severity: High]
Is it intentional that the RX power-on path handles the reset logic for the
independently exposed TX PHY?
The TX PHY currently lacks .power_on and .power_off callbacks and seems to
rely implicitly on the RX PHY to enable hardware clocks. If the TX PHY is
accessed via phy_configure() before the RX PHY is fully powered on, could
this result in unclocked memory-mapped I/O and trigger a synchronous
external abort?
> +
> + err = tegra_mphy_rx_write_kick_go(lane, MPHY_RX_APB_VENDOR3B, MPHY_EQ_TIMEOUT);
> + if (err) {
> + dev_err(&phy->dev, "eq_timeout programming failed: %d\n", err);
> + goto err_reset;
> + }
> +
> + err = tegra_mphy_rx_write_kick_go(lane, MPHY_RX_APB_VENDOR49, MPHY_PWR_CHANGE_CLK_BOOST);
> + if (err) {
> + dev_err(&phy->dev, "pwr_change_clk_boost programming failed: %d\n", err);
> + goto err_reset;
> + }
> +
> + value = readl(lane->regs + MPHY_RX_APB_CAPABILITY_88_8B);
^^^^^^^^^^
[Severity: High]
Should this use lane->rx_regs instead of lane->regs for offset application?
Using lane->regs misdirects the read/write operations to offsets 0x88 and
0x94 instead of 0x2088 and 0x2094 (since MPHY_RX_OFFSET is 0x2000), which
may lead to memory corruption and failed configurations.
> + value &= ~RX_HS_G1_SYNC_LENGTH_CAPABILITY(~0);
> + value |= RX_HS_G1_SYNC_LENGTH_CAPABILITY(0xf);
> + writel(value, lane->regs + MPHY_RX_APB_CAPABILITY_88_8B);
> +
> + value = readl(lane->regs + MPHY_RX_APB_CAPABILITY_94_97);
^^^^^^^^^^
[Severity: High]
Does this also need to use lane->rx_regs instead of lane->regs?
> + value &= ~RX_HS_G3_SYNC_LENGTH_CAPABILITY(~0);
> + value |= RX_HS_G3_SYNC_LENGTH_CAPABILITY(0xf);
> + value &= ~RX_HS_G2_SYNC_LENGTH_CAPABILITY(~0);
> + value |= RX_HS_G2_SYNC_LENGTH_CAPABILITY(0xf);
> + writel(value, lane->regs + MPHY_RX_APB_CAPABILITY_94_97);
[ ... ]
> +static int tegra_mphy_rx_power_off(struct phy *phy)
> +{
> + struct tegra_mphy *mphy = dev_get_drvdata(phy->dev.parent);
> + struct tegra_mphy_lane *lane = phy_get_drvdata(phy);
> +
> + if (WARN_ON(mphy->power_count == 0))
> + return -EINVAL;
> +
> + reset_control_assert(lane->rst_rx);
> + reset_control_assert(lane->rst_tx);
> +
> + if (--mphy->power_count == 0)
> + clk_bulk_disable_unprepare(mphy->num_clks, mphy->clks);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Severity: Medium]
Should mphy->rst_clk_ctl be asserted here before or after disabling the
clocks?
The driver intentionally deasserts mphy->rst_clk_ctl in
tegra_mphy_rx_power_on() when power_count goes from 0 to 1, but omits the
corresponding reset_control_assert() in this successful power-off path,
which leaks the reset state across power cycles.
> +
> + return 0;
> +}
[ ... ]
> +static const struct phy_ops tegra_mphy_tx_ops = {
> + .configure = tegra_mphy_tx_configure,
> + .calibrate = tegra_mphy_tx_calibrate,
> +};
^^
[Severity: High]
Are .power_on and .power_off callbacks intentionally omitted for the TX PHY
ops?
Leaving the TX PHY exposed to configuration while in an unclocked state
creates a fragile API contract that risks system crashes.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260909-tegra264-mphy-v1-0-ce61a80dc065@nvidia.com?part=2
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
WARNING: multiple messages have this Message-ID (diff)
From: sashiko-bot@kernel.org
To: "Kartik Rajput" <kkartik@nvidia.com>
Cc: robh@kernel.org, olteanv@gmail.com, neil.armstrong@linaro.org,
linux-phy@lists.infradead.org, conor+dt@kernel.org,
devicetree@vger.kernel.org, vkoul@kernel.org
Subject: Re: [PATCH 2/2] phy: tegra: Add Tegra264 MPHY driver
Date: Wed, 09 Sep 2026 09:54:19 +0000 [thread overview]
Message-ID: <20260909095419.C30C81F00A3D@smtp.kernel.org> (raw)
In-Reply-To: <20260909-tegra264-mphy-v1-2-ce61a80dc065@nvidia.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Data race on shared `mphy->power_count` and clock state across multiple PHY instances.
- [High] TX PHY lacks power management operations, creating a fragile API contract that risks system crashes.
- [High] Wrong base address pointer used for `MPHY_RX_APB_CAPABILITY` registers.
- [Medium] Missing reset assertion for `mphy->rst_clk_ctl` in the normal `tegra_mphy_rx_power_off` path.
--
commit bceb08380e03847a80ce77db39c3ff271cbccb0c
Author: Kartik Rajput <kkartik@nvidia.com>
phy: tegra: Add Tegra264 MPHY driver
Add a driver for the MIPI M-PHY found on NVIDIA Tegra264 SoCs. The
M-PHY has two lanes, each with a transmit and a receive direction,
exposed as four PHYs to the UFS host controller.
> diff --git a/drivers/phy/tegra/phy-tegra-mphy.c b/drivers/phy/tegra/phy-tegra-mphy.c
> index 0000000000000..01cafe1c7477f
> --- /dev/null
> +++ b/drivers/phy/tegra/phy-tegra-mphy.c
[ ... ]
> +static int tegra_mphy_rx_power_on(struct phy *phy)
> +{
> + struct tegra_mphy *mphy = dev_get_drvdata(phy->dev.parent);
> + struct tegra_mphy_lane *lane = phy_get_drvdata(phy);
> + u32 value;
> + int err;
> +
> + if (mphy->power_count++ == 0) {
^^^^^^^^^^^^^^^^^^^^^^^
[Severity: High]
Since l0 and l1 are distinct PHY instances exposed to the consumer, can
concurrent phy_power_on() or phy_power_off() calls race on this shared
mphy->power_count?
The PHY framework's internal mutex only serializes operations on a per-PHY
basis. An unprotected read-modify-write here could lead to corrupted
reference counts, unbalanced clock states, and hardware faults.
> + err = clk_bulk_prepare_enable(mphy->num_clks, mphy->clks);
> + if (err) {
> + mphy->power_count--;
> + dev_err(&phy->dev, "failed to enable clocks: %d\n", err);
> + return err;
> + }
> + reset_control_deassert(mphy->rst_clk_ctl);
> + }
> +
> + reset_control_deassert(lane->rst_rx);
> + reset_control_deassert(lane->rst_tx);
^^^^^^^^^^^^^^^^^^^^
[Severity: High]
Is it intentional that the RX power-on path handles the reset logic for the
independently exposed TX PHY?
The TX PHY currently lacks .power_on and .power_off callbacks and seems to
rely implicitly on the RX PHY to enable hardware clocks. If the TX PHY is
accessed via phy_configure() before the RX PHY is fully powered on, could
this result in unclocked memory-mapped I/O and trigger a synchronous
external abort?
> +
> + err = tegra_mphy_rx_write_kick_go(lane, MPHY_RX_APB_VENDOR3B, MPHY_EQ_TIMEOUT);
> + if (err) {
> + dev_err(&phy->dev, "eq_timeout programming failed: %d\n", err);
> + goto err_reset;
> + }
> +
> + err = tegra_mphy_rx_write_kick_go(lane, MPHY_RX_APB_VENDOR49, MPHY_PWR_CHANGE_CLK_BOOST);
> + if (err) {
> + dev_err(&phy->dev, "pwr_change_clk_boost programming failed: %d\n", err);
> + goto err_reset;
> + }
> +
> + value = readl(lane->regs + MPHY_RX_APB_CAPABILITY_88_8B);
^^^^^^^^^^
[Severity: High]
Should this use lane->rx_regs instead of lane->regs for offset application?
Using lane->regs misdirects the read/write operations to offsets 0x88 and
0x94 instead of 0x2088 and 0x2094 (since MPHY_RX_OFFSET is 0x2000), which
may lead to memory corruption and failed configurations.
> + value &= ~RX_HS_G1_SYNC_LENGTH_CAPABILITY(~0);
> + value |= RX_HS_G1_SYNC_LENGTH_CAPABILITY(0xf);
> + writel(value, lane->regs + MPHY_RX_APB_CAPABILITY_88_8B);
> +
> + value = readl(lane->regs + MPHY_RX_APB_CAPABILITY_94_97);
^^^^^^^^^^
[Severity: High]
Does this also need to use lane->rx_regs instead of lane->regs?
> + value &= ~RX_HS_G3_SYNC_LENGTH_CAPABILITY(~0);
> + value |= RX_HS_G3_SYNC_LENGTH_CAPABILITY(0xf);
> + value &= ~RX_HS_G2_SYNC_LENGTH_CAPABILITY(~0);
> + value |= RX_HS_G2_SYNC_LENGTH_CAPABILITY(0xf);
> + writel(value, lane->regs + MPHY_RX_APB_CAPABILITY_94_97);
[ ... ]
> +static int tegra_mphy_rx_power_off(struct phy *phy)
> +{
> + struct tegra_mphy *mphy = dev_get_drvdata(phy->dev.parent);
> + struct tegra_mphy_lane *lane = phy_get_drvdata(phy);
> +
> + if (WARN_ON(mphy->power_count == 0))
> + return -EINVAL;
> +
> + reset_control_assert(lane->rst_rx);
> + reset_control_assert(lane->rst_tx);
> +
> + if (--mphy->power_count == 0)
> + clk_bulk_disable_unprepare(mphy->num_clks, mphy->clks);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Severity: Medium]
Should mphy->rst_clk_ctl be asserted here before or after disabling the
clocks?
The driver intentionally deasserts mphy->rst_clk_ctl in
tegra_mphy_rx_power_on() when power_count goes from 0 to 1, but omits the
corresponding reset_control_assert() in this successful power-off path,
which leaks the reset state across power cycles.
> +
> + return 0;
> +}
[ ... ]
> +static const struct phy_ops tegra_mphy_tx_ops = {
> + .configure = tegra_mphy_tx_configure,
> + .calibrate = tegra_mphy_tx_calibrate,
> +};
^^
[Severity: High]
Are .power_on and .power_off callbacks intentionally omitted for the TX PHY
ops?
Leaving the TX PHY exposed to configuration while in an unclocked state
creates a fragile API contract that risks system crashes.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260909-tegra264-mphy-v1-0-ce61a80dc065@nvidia.com?part=2
next prev parent reply other threads:[~2026-09-09 9:54 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-09 9:43 [PATCH 0/2] Add M-PHY support for NVIDIA Tegra264 Kartik Rajput
2026-09-09 9:43 ` Kartik Rajput
2026-09-09 9:43 ` [PATCH 1/2] dt-bindings: phy: Add nvidia,tegra264-mphy Kartik Rajput
2026-09-09 9:43 ` Kartik Rajput
2026-09-13 8:38 ` Krzysztof Kozlowski
2026-09-13 8:38 ` Krzysztof Kozlowski
2026-09-09 9:43 ` [PATCH 2/2] phy: tegra: Add Tegra264 MPHY driver Kartik Rajput
2026-09-09 9:43 ` Kartik Rajput
2026-09-09 9:54 ` sashiko-bot [this message]
2026-09-09 9:54 ` 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=20260909095419.C30C81F00A3D@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=kkartik@nvidia.com \
--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 \
/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.