Linux-PHY Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Cody Kang" <codykang.hk@gmail.com>
Cc: dri-devel@lists.freedesktop.org, vkoul@kernel.org,
	linux-phy@lists.infradead.org, neil.armstrong@linaro.org,
	robh@kernel.org, devicetree@vger.kernel.org, olteanv@gmail.com,
	conor+dt@kernel.org
Subject: Re: [PATCH RESEND 05/17] phy: spacemit: add Innosilicon DP TX PHY driver
Date: Sat, 25 Jul 2026 05:02:54 +0000	[thread overview]
Message-ID: <20260725050254.9F7091F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260725-k3-display-v1-5-6de34d80e86c@gmail.com>

Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [High] PHY provider is registered before probe finishes, exposing it to early concurrent access and potential Use-After-Free (UAF) on probe failure.
- [High] Lack of driver-level synchronization between CCF and PHY frameworks leads to concurrent hardware state corruption.
- [Medium] The MPLL (main link PLL) is powered on during PHY initialization but is never powered off in the power down sequence.
- [Medium] Missing hardware state cleanup on error paths in `k3_inno_dp_phy_power_on` leaves the PHY powered on.
- [Medium] Rate configuration functions unconditionally power on the PLLs, overriding the logical PHY power state.
- [Medium] PLL programming functions do not poll for hardware lock before proceeding.
--

--- Patch [5]: [PATCH RESEND 05/17] phy: spacemit: add Innosilicon DP TX PHY driver ---
commit 31db74eae7dc59ddc61373dbe3e2c6c1e6966ccd
Author: Cody Kang <codykang.hk@gmail.com>
Subject: phy: spacemit: add Innosilicon DP TX PHY driver

This commit introduces the SpacemiT K3 Innosilicon DisplayPort PHY driver.
It integrates the PHY as a child of the DP controller, registering a PHY
provider and exposing the pixel PLL as a clock provider.

> diff --git a/drivers/phy/spacemit/phy-k3-inno-dp.c b/drivers/phy/spacemit/phy-k3-inno-dp.c
> new file mode 100644
> index 0000000000000..9dd62edb7a5af
> --- /dev/null
> +++ b/drivers/phy/spacemit/phy-k3-inno-dp.c
> @@ -0,0 +1,948 @@

[ ... ]

> +static int k3_inno_dp_phy_power_on(struct phy *phy)
> +{
> +	struct k3_inno_dp_phy *p = phy_get_drvdata(phy);
> +	u32 lane_en;
> +	u32 val;
> +	int ret;

[ ... ]

> +	ret = regmap_read_poll_timeout(p->regmap, DPTX_ANA_MPLL, val,
> +				       val & DPTX_ANA_MPLL_LOCKED,
> +				       2000, 10 * 1000);
> +	if (ret) {
> +		dev_err(p->dev, "DP PHY core PLL lock timed out\n");
> +		return ret;
> +	}

[Severity: Medium]
If the MPLL or PREPLL fails to lock within 10ms, this immediately returns an
error without restoring the power down bits or XMIT_EN.

Since the generic PHY framework does not automatically call phy_power_off()
when phy_power_on() fails, could this leave the hardware running in an
inconsistent state and leak power?

> +
> +	ret = regmap_read_poll_timeout(p->regmap, DPTX_ANA_PREPLL, val,
> +				       val & DPTX_ANA_PREPLL_LOCKED,
> +				       2000, 10 * 1000);
> +	if (ret)
> +		dev_err(p->dev, "DP PHY pixel PLL lock timed out\n");
> +
> +	return ret;
> +}
> +
> +static int k3_inno_dp_phy_power_off(struct phy *phy)
> +{
> +	struct k3_inno_dp_phy *p = phy_get_drvdata(phy);
> +
> +	regmap_write_bits(p->regmap, DPTX_PHY_CTRL, DPTX_PHY_CTRL_XMIT_EN, 0);
> +	usleep_range(2000, 4000);
> +
> +	regmap_write_bits(p->regmap, DPTX_ANA_PREPLL, DPTX_ANA_PREPLL_PD,
> +			  DPTX_ANA_PREPLL_PD);
> +	usleep_range(2000, 4000);
> +
> +	return 0;
> +}

[Severity: Medium]
Does this power down sequence omit the MPLL?

The k3_inno_dp_phy_power_on() function powers up the MPLL by clearing
DPTX_ANA_MPLL_PD, but this power_off function does not appear to re-assert
it. Could this leave the main link PLL running indefinitely when the DP
controller is suspended or torn down?

[ ... ]

> +static void k3_inno_dp_phy_program_mpll(struct k3_inno_dp_phy *p,
> +					const struct k3_inno_dp_mpll_cfg *cfg)
> +{
> +	struct regmap *rm = p->regmap;

[ ... ]

> +	regmap_write_bits(rm, DPTX_ANA_PREPLL_CTRL, DPTX_ANA_PREPLL_LOCK_BYPEN,
> +		FIELD_PREP(DPTX_ANA_PREPLL_LOCK_BYPEN, 1));
> +
> +	regmap_write_bits(rm, DPTX_ANA_MPLL, DPTX_ANA_MPLL_PD,
> +		FIELD_PREP(DPTX_ANA_MPLL_PD, 0));

[Severity: Medium]
Does unconditionally writing 0 to DPTX_ANA_MPLL_PD override the logical
power state of the PHY?

If a DRM driver configures the link rate (calling phy_configure()) while the
PHY is logically powered off, this will force the PLL to run and
desynchronize the hardware from the PHY framework's power state.

> +	usleep_range(2000, 4000);
> +}

[Severity: Medium]
Is it safe to rely on a fixed 2-4ms sleep here instead of polling
DPTX_ANA_MPLL_LOCKED?

The power_on() function polls the locked bit for up to 10ms. A fixed delay
here might proceed with an unstable clock if the hardware takes longer to
lock, potentially causing display failures or link training issues.

[ ... ]

> +static void k3_inno_dp_program_prepll(struct k3_inno_dp_phy *p,
> +				      const struct k3_inno_dp_prepll_cfg *cfg)
> +{
> +	regmap_write_bits(p->regmap, DPTX_ANA_PREPLL, DPTX_ANA_PREPLL_PD,
> +		FIELD_PREP(DPTX_ANA_PREPLL_PD, 1));
> +	usleep_range(2000, 4000);

[Severity: High]
Is a driver-level lock needed to synchronize access to the PHY registers
between the CCF and PHY frameworks?

Since this driver exposes both a clock (via CCF) and a PHY that share the
same hardware registers, concurrent calls to clk_set_rate() and
phy_power_on() can interleave.

If clk_set_rate() begins this multi-step programming sequence, a concurrent
phy_power_on() could clear the PD bit while the clock is still being
configured, corrupting the hardware state.

[ ... ]

> +	regmap_write_bits(p->regmap, DPTX_ANA_PREPLL,
> +		DPTX_ANA_PREPLL_PCLK_NORMAL,
> +		FIELD_PREP(DPTX_ANA_PREPLL_PCLK_NORMAL, 1));
> +	usleep_range(2000, 4000);
> +
> +	regmap_write_bits(p->regmap, DPTX_ANA_PREPLL, DPTX_ANA_PREPLL_PD,
> +		FIELD_PREP(DPTX_ANA_PREPLL_PD, 0));

[Severity: Medium]
Similar to the MPLL configuration, does unconditionally clearing
DPTX_ANA_PREPLL_PD here override the PHY power state if the clock rate is
set while the PHY is logically off?

> +	usleep_range(2000, 4000);
> +}

[Severity: Medium]
Is it safe to rely on a fixed delay here instead of polling the
DPTX_ANA_PREPLL_LOCKED bit, which could lead to proceeding with an unstable
pixel clock?

[ ... ]

> +static int k3_inno_dp_phy_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct k3_inno_dp_phy *p;
> +	struct phy_provider *provider;
> +	struct clk_init_data init = {};
> +	int ret;

[ ... ]

> +	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +	if (IS_ERR(provider))
> +		return dev_err_probe(dev, PTR_ERR(provider),
> +				     "failed to register PHY provider\n");
> +
> +	/* PHY takes a 24 MHz reference clock */
> +	p->ref_clk_khz = 24000;
> +
> +	/* The APMU pixel-clock mux references this clock by name. */
> +	of_property_read_string(dev->of_node, "clock-output-names", &init.name);
> +	if (!init.name)
> +		init.name = dev_name(dev);
> +	init.ops = &k3_inno_dp_pxclk_ops;
> +	init.parent_names = NULL;
> +	init.num_parents = 0;
> +	init.flags = 0;
> +	p->pxclk_hw.init = &init;
> +
> +	ret = devm_clk_hw_register(dev, &p->pxclk_hw);
> +	if (ret)
> +		return dev_err_probe(dev, ret,
> +				     "failed to register pixel clock\n");

[Severity: High]
Can the PHY provider be accessed by consumers before probe completes
successfully?

The PHY provider is registered via devm_of_phy_provider_register() before
the pixel clock is registered. If devm_clk_hw_register() fails, probe will
return an error and devres will free the driver context struct.

If a consumer driver acquires a reference to the PHY during this race
window, it could retain the reference after probe fails, leading to a
use-after-free when it attempts PHY operations on the freed pointer.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260725-k3-display-v1-0-6de34d80e86c@gmail.com?part=5

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

  reply	other threads:[~2026-07-25  5:02 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-25  4:51 [PATCH RESEND 00/17] drm/spacemit: add SpacemiT K3 display support Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 01/17] dt-bindings: display: spacemit: add K3 Saturn DPU controller Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 02/17] dt-bindings: phy: add SpacemiT K3 Innosilicon DP PHY Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 03/17] dt-bindings: display: spacemit: add K3 Innosilicon DP/eDP controller Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 04/17] dt-bindings: soc: spacemit: allow eDP/DP PHY PLL pixel clocks on K3 APMU Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 05/17] phy: spacemit: add Innosilicon DP TX PHY driver Cody Kang via B4 Relay
2026-07-25  5:02   ` sashiko-bot [this message]
2026-07-25  4:51 ` [PATCH RESEND 06/17] clk: spacemit: k3: parent eDP/DP pixel clock to the PHY PLL Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 07/17] drm/spacemit: add Saturn DPU register model Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 08/17] drm/spacemit: add Saturn DPU core types, cmdlist and display MMU Cody Kang via B4 Relay
2026-07-25  5:04   ` sashiko-bot
2026-07-25  4:51 ` [PATCH RESEND 09/17] drm/spacemit: add Saturn DPU hardware backend Cody Kang via B4 Relay
2026-07-25  5:12   ` sashiko-bot
2026-07-25  4:51 ` [PATCH RESEND 10/17] drm/spacemit: add Saturn DPU KMS pipeline Cody Kang via B4 Relay
2026-07-25  5:04   ` sashiko-bot
2026-07-25  4:51 ` [PATCH RESEND 11/17] drm/spacemit: add Saturn DPU DRM device driver Cody Kang via B4 Relay
2026-07-25  5:05   ` sashiko-bot
2026-07-25  4:51 ` [PATCH RESEND 12/17] drm/spacemit: add Innosilicon DP/eDP controller bridge driver Cody Kang via B4 Relay
2026-07-25  5:04   ` sashiko-bot
2026-07-25  4:51 ` [PATCH RESEND 13/17] MAINTAINERS: add SpacemiT K3 display driver entry Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 14/17] riscv: dts: spacemit: k3: add display nodes Cody Kang via B4 Relay
2026-07-25  5:08   ` sashiko-bot
2026-07-25  4:51 ` [PATCH RESEND 15/17] riscv: dts: spacemit: k3-pico-itx: enable the DisplayPort output Cody Kang via B4 Relay
2026-07-25  5:12   ` sashiko-bot
2026-07-25  4:51 ` [PATCH RESEND 16/17] riscv: dts: spacemit: k3-com260-ifx: " Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 17/17] riscv: defconfig: spacemit: k3: enable display driver Cody Kang via B4 Relay

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=20260725050254.9F7091F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=codykang.hk@gmail.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.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 \
    /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