From: sashiko-bot@kernel.org
To: "Sebastian Reichel" <sebastian.reichel@collabora.com>
Cc: linux-phy@lists.infradead.org, vkoul@kernel.org,
neil.armstrong@linaro.org, olteanv@gmail.com
Subject: Re: [PATCH v3 4/4] phy: rockchip: inno-usb2: move suspend handling into clock prepare/unprepare for RK3588/RK3576
Date: Wed, 04 Nov 2026 23:36:27 +0000 [thread overview]
Message-ID: <sashiko-outbox-198301@kernel.org> (raw)
In-Reply-To: <20261105-phy-rockchip-inno-usb2-clock-fix-v3-4-b20608c08b94@collabora.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] phy: rockchip: inno-usb2: NULL deref in rockchip_usb2phy_clk480m_unprepare()
- [High] phy: rockchip: inno-usb2: -EAGAIN in rockchip_usb2phy_clk480m_prepare()
--
commit 0477bc2cc59adc2dfda01c728633637be8e1f046
Author: Sebastian Reichel <sebastian.reichel@collabora.com>
phy: rockchip: inno-usb2: move suspend handling into clock prepare/unprepare for RK3588/RK3576
This commit moves PHY suspend handling on single-port PHYs (RK3588 and
RK3576) from the PHY power_on and power_off callbacks into the 480MHz clock
prepare and unprepare callbacks so the PHY PLL is running whenever the clock
is prepared.
> diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
> index 2919c2e11968b..b2633b83f7ab3 100644
> --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
> +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
> @@ -363,10 +363,15 @@ static int rockchip_usb2phy_set_suspend(struct rockchip_usb2phy *rphy,
>
> static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
> {
> + struct rockchip_usb2phy *rphy =
> + container_of(hw, struct rockchip_usb2phy, clk480m_hw);
> const struct usb2phy_reg *clkout_ctl;
> struct regmap *base;
> int ret;
>
> + if (rphy->phy_cfg->num_ports == 1 && !rphy->ports[0].port_cfg)
> + return -EAGAIN;
[Severity: High]
As reported by Sashiko on v2 [1], in rockchip_usb2phy_probe(), the 480MHz
clock provider is registered via rockchip_usb2phy_clk480m_register() and
of_clk_add_provider() before input clocks are enabled, before phy_tuning()
runs, and before the child port loop initializes rphy->ports[0].port_cfg:
drivers/phy/rockchip/phy-rockchip-inno-usb2.c:rockchip_usb2phy_probe() {
...
ret = rockchip_usb2phy_clk480m_register(rphy);
if (ret)
return dev_err_probe(dev, ret, "failed to register 480m output clock\n");
ret = clk_bulk_prepare_enable(rphy->num_clks, rphy->clks);
if (ret)
return dev_err_probe(dev, ret, "failed to enable usb2phy clks\n");
...
for_each_available_child_of_node(np, child_np) {
struct rockchip_usb2phy_port *rport = &rphy->ports[index];
...
}
Clock consumers on RK3588 and RK3576 include ohci-platform and ehci-platform
(both of which set PROBE_PREFER_ASYNCHRONOUS and call pdata->power_on() ->
clk_prepare_enable() in their probe functions before usb_add_hcd() requests
the PHY) as well as phy-rockchip-usbdp (which prepares and enables the utmi
clock in rk_udphy_setup()).
If an asynchronous consumer calls clk_prepare_enable() after
of_clk_add_provider() publishes the clock but before rphy->ports[0].port_cfg
is initialized (or on boards where the parent usb2phy node is enabled to
supply the utmi clock to usbdp_phy while the child port subnode is disabled
in DT), rockchip_usb2phy_clk480m_prepare() will return -EAGAIN.
Neither clk_prepare_enable() nor the callers in ohci_platform_probe(),
ehci_platform_probe(), or rk_udphy_setup() retry on -EAGAIN, and the driver
core only defers probing on -EPROBE_DEFER. Can returning -EAGAIN here cause
consumer probing or PHY setup to fail permanently instead of waiting for port
initialization?
> +
> rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl);
>
> /* turn on 480m clk output if it is off */
> @@ -379,16 +384,31 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
> usleep_range(1200, 1300);
> }
>
> + if (rphy->phy_cfg->num_ports == 1) {
> + ret = rockchip_usb2phy_set_suspend(rphy, &rphy->ports[0], false);
> + if (ret)
> + goto disable_clkout;
> + }
> +
> return 0;
> +
> +disable_clkout:
> + property_enable(base, clkout_ctl, false);
> + return ret;
> }
>
> static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
> {
> + struct rockchip_usb2phy *rphy =
> + container_of(hw, struct rockchip_usb2phy, clk480m_hw);
> const struct usb2phy_reg *clkout_ctl;
> struct regmap *base;
>
> rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl);
>
> + if (rphy->phy_cfg->num_ports == 1)
> + rockchip_usb2phy_set_suspend(rphy, &rphy->ports[0], true);
[Severity: High]
What happens in rockchip_usb2phy_clk480m_unprepare() if
rphy->ports[0].port_cfg is NULL?
In rk3588-base.dtsi, rk3588-extra.dtsi, and rk3576.dtsi, the parent usb2phy
nodes and their child otg-port or host-port nodes have independent status
properties. If a parent usb2phy node is enabled while its child port node is
disabled in DT, rockchip_usb2phy_probe() registers clk480m with
rphy->ports[0].port_cfg left as NULL.
Because rockchip_usb2phy_clkout_ops defines .is_prepared =
rockchip_usb2phy_clk480m_prepared(), which checks property_enabled(base,
clkout_ctl), and clkout_ctl defaults to enabled in hardware at reset on
RK3588 and RK3576, clk_unprepare_unused_subtree() will see the clock as
prepared and call rockchip_usb2phy_clk480m_unprepare() during
clk_disable_unused() even if rockchip_usb2phy_clk480m_prepare() was never
called or returned -EAGAIN.
Unlike rockchip_usb2phy_clk480m_prepare(), rockchip_usb2phy_clk480m_unprepare()
does not check rphy->ports[0].port_cfg before calling
rockchip_usb2phy_set_suspend(rphy, &rphy->ports[0], true), which then
dereferences &rport->port_cfg->phy_sus:
rockchip_usb2phy_clk480m_unprepare()
-> rockchip_usb2phy_set_suspend()
-> property_enable(rphy->grf, &rport->port_cfg->phy_sus, do_suspend)
Can this cause a NULL pointer dereference when unpreparing unused clocks at
boot?
[1] https://lore.kernel.org/r/20261001-phy-rockchip-inno-usb2-clock-fix-v2-4-e01bf509359e@collabora.com
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261105-phy-rockchip-inno-usb2-clock-fix-v3-0-b20608c08b94@collabora.com?part=4
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
prev parent reply other threads:[~2026-11-04 23:36 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 23:07 [PATCH v3 0/4] phy: rockchip: inno-usb2: ensure PHY is running when clock is requested Sebastian Reichel
2026-11-04 23:07 ` [PATCH v3 1/4] phy: rockchip: inno-usb2: simplify and unify PHY op debug messages Sebastian Reichel
2026-11-04 23:07 ` [PATCH v3 2/4] phy: rockchip: inno-usb2: drop duplicated update of rport->suspended Sebastian Reichel
2026-11-04 23:16 ` sashiko-bot
2026-11-04 23:07 ` [PATCH v3 3/4] phy: rockchip: inno-usb2: move suspend handling into new function Sebastian Reichel
2026-11-04 23:08 ` [PATCH v3 4/4] phy: rockchip: inno-usb2: move suspend handling into clock prepare/unprepare for RK3588/RK3576 Sebastian Reichel
2026-11-04 23:36 ` sashiko-bot [this message]
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=sashiko-outbox-198301@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=neil.armstrong@linaro.org \
--cc=olteanv@gmail.com \
--cc=sashiko-reviews@lists.linux.dev \
--cc=sebastian.reichel@collabora.com \
--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