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 v17 4/7] phy: rockchip: usbdp: Fix power state handling
Date: Sat, 14 Nov 2026 02:21:13 +0000 [thread overview]
Message-ID: <sashiko-outbox-214051@kernel.org> (raw)
In-Reply-To: <20261114-b4-rockchip-usbdp-cleanup-part3-v17-4-1af5f566408e@collabora.com>
Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [High] phy: rockchip: usbdp: skipped reset handler and port disable on
USB3 exit
- [Medium] phy: rockchip: usbdp: clock and power leak when udphy->hs is
true
- [Low] phy: rockchip: usbdp: state desync on error in
rk_udphy_update_power_state()
--
commit 336f724e3ffaaeb893f1fa7b7dc4865cc0240d95
Author: Sebastian Reichel <sebastian.reichel@collabora.com>
phy: rockchip: usbdp: Fix power state handling
This commit replaces rk_udphy_power_on() and rk_udphy_power_off() with a
single rk_udphy_update_power_state() helper that derives the target PHY
state from udphy->hw_mode and udphy->sw_mode.
> diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> index de8f01bd04672..fc3c4104dcd7e 100644
> --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
> +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
[ ... ]
> @@ -1029,70 +1029,93 @@ void rk_udphy_register_reset_handler(struct phy *phy,
> }
> EXPORT_SYMBOL_GPL(rk_udphy_register_reset_handler);
>
> -static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode)
> +static int rk_udphy_update_power_state(struct rk_udphy *udphy)
> {
> + bool usb3_port_enable;
> + u8 target_mode;
> int ret;
>
> - if (!(udphy->hw_mode & mode)) {
> - dev_info(udphy->dev, "mode 0x%02x is not support\n", mode);
> + /*
> + * Initialize PHY mode according to the hardware setup (either described
> + * in DT or negotiated via the Type-C controller) instead of requesting
> + * only the needed PHY side, because that would break the USB/DP data
> + * streams when the other PHY is being requested. This is not an issue
> + * during the Type-C negotiation as that happens during the hotplug phase
> + * and not during normal operation. Also disable everything if the
> + * software has not requested anything, as there shouldn't be any active
> + * data streams in that case.
> + */
> + target_mode = udphy->hw_mode;
> + if (udphy->sw_mode == UDPHY_MODE_NONE)
> + target_mode = UDPHY_MODE_NONE;
> +
> + usb3_port_enable = !udphy->hs && (target_mode & UDPHY_MODE_USB);
> +
> + if (!udphy->phy_needs_reinit && udphy->status == target_mode) {
> + if (udphy->sw_mode & UDPHY_MODE_USB)
> + rk_udphy_u3_port_disable(udphy, !usb3_port_enable);
> return 0;
> }
>
> - if (udphy->status == UDPHY_MODE_NONE) {
> - rk_udphy_run_reset_handler(udphy, true);
> + /* Avoid to re-init disabled PHY */
> + if (udphy->status == target_mode && target_mode == UDPHY_MODE_NONE)
> + return 0;
> +
> + /*
> + * Inform DWC3 driver, that we are about to reset the PHY, so that it can
> + * assert its PIPE reset lines and avoid DWC3 getting into a buggy state.
> + * This is intentionally done for a PHY disable, since that also changes
> + * the clocks routed to the PHY.
> + */
> + rk_udphy_run_reset_handler(udphy, true);
>
> + /*
> + * Disable USB3 port, which among other things re-routes a DWC3 clock to
> + * avoid SErrors when the DWC3 registers are accessed while the PHY is
> + * disabled. This is only done, when the DWC3 is running as the accessed
> + * GRF registers and in PD_USB.
> + */
> + if (udphy->sw_mode & UDPHY_MODE_USB) {
> rk_udphy_u3_port_disable(udphy, true);
> udelay(10);
> + }
>
> + if (udphy->status == UDPHY_MODE_NONE) {
> + /* Power up (incl. clocks) */
> ret = rk_udphy_setup(udphy);
> if (ret) {
> rk_udphy_run_reset_handler(udphy, false);
> return ret;
> }
> -
> - if (!udphy->hs && udphy->hw_mode & UDPHY_MODE_USB)
> - rk_udphy_u3_port_disable(udphy, false);
> - udphy->phy_needs_reinit = false;
> -
> - rk_udphy_run_reset_handler(udphy, false);
> - } else if (udphy->phy_needs_reinit) {
> - rk_udphy_run_reset_handler(udphy, true);
> -
> - rk_udphy_u3_port_disable(udphy, true);
> - udelay(10);
> -
> + } else if (target_mode == UDPHY_MODE_NONE) {
> + /* Power down (incl. clocks) */
> + rk_udphy_disable(udphy);
[Severity: High]
Does clearing UDPHY_MODE_USB from udphy->sw_mode in rk_udphy_usb3_phy_exit()
before calling rk_udphy_update_power_state() skip both
rk_udphy_run_reset_handler() and rk_udphy_u3_port_disable(udphy, true) on
USB3 teardown and PHY disable?
rk_udphy_run_reset_handler() returns early when !(udphy->sw_mode &
UDPHY_MODE_USB), and target_mode only becomes UDPHY_MODE_NONE when
udphy->sw_mode == UDPHY_MODE_NONE. When rk_udphy_usb3_phy_exit() runs, or
whenever rk_udphy_disable() is reached, UDPHY_MODE_USB is already clear in
udphy->sw_mode, so the DWC3 reset callback is never invoked and the USB3
port is left enabled in usbgrf without re-routing the DWC3 PIPE clock,
which can trigger SErrors if DWC3 registers are accessed while the PHY is
disabled.
> + } else {
> + /* Mode change => re-init */
> + ret = rk_udphy_init(udphy);
> + if (ret) {
> + rk_udphy_run_reset_handler(udphy, false);
> + return ret;
> + }
> }
[ ... ]
> @@ -1135,9 +1158,7 @@ static int rk_udphy_dp_phy_power_off(struct phy *phy)
> udphy->sw_mode &= ~UDPHY_MODE_DP;
>
> rk_udphy_dp_lane_enable(udphy, 0);
> - rk_udphy_power_off(udphy, UDPHY_MODE_DP);
> -
> - return 0;
> + return rk_udphy_update_power_state(udphy);
> }
[Severity: Low]
If a pending re-init (udphy->phy_needs_reinit) fails inside
rk_udphy_init() when rk_udphy_dp_phy_power_off() or
rk_udphy_usb3_phy_exit() calls rk_udphy_update_power_state(), can state
become desynchronized?
On failure, rk_udphy_init() asserts all PHY resets while leaving the
clocks enabled, the USB3 port disabled, and udphy->status set to the old
mode. Propagating that error causes phy_power_off() or phy_exit() to keep
phy->power_count or phy->init_count elevated even though the caller has
already cleared its bit in udphy->sw_mode.
> @@ -1349,12 +1370,12 @@ static int rk_udphy_usb3_phy_init(struct phy *phy)
> udphy->sw_mode |= UDPHY_MODE_USB;
>
> /* DP only or high-speed, disable U3 port */
> - if (!(udphy->hw_mode & UDPHY_MODE_USB) || udphy->hs) {
> + if (udphy->hs) {
> rk_udphy_u3_port_disable(udphy, true);
> return 0;
> }
>
> - ret = rk_udphy_power_on(udphy, UDPHY_MODE_USB);
> + ret = rk_udphy_update_power_state(udphy);
> if (ret) {
> udphy->sw_mode &= ~UDPHY_MODE_USB;
> return ret;
> @@ -1371,13 +1392,10 @@ static int rk_udphy_usb3_phy_exit(struct phy *phy)
>
> udphy->sw_mode &= ~UDPHY_MODE_USB;
>
> - /* DP only or high-speed */
> - if (!(udphy->hw_mode & UDPHY_MODE_USB) || udphy->hs)
> + if (udphy->hs)
> return 0;
>
> - rk_udphy_power_off(udphy, UDPHY_MODE_USB);
> -
> - return 0;
> + return rk_udphy_update_power_state(udphy);
> }
[Severity: Medium]
When udphy->hs is true, does setting UDPHY_MODE_USB in udphy->sw_mode and
returning early from rk_udphy_usb3_phy_init() and rk_udphy_usb3_phy_exit()
leak the PHY clocks and leave the PHY powered on after DisplayPort is used?
If rk_udphy_usb3_phy_init() runs first with udphy->hs set, udphy->sw_mode
holds UDPHY_MODE_USB while udphy->status stays UDPHY_MODE_NONE. Powering
DisplayPort on via rk_udphy_dp_phy_power_on() then enables udphy->clks in
rk_udphy_setup(), but rk_udphy_dp_phy_power_off() sees udphy->sw_mode ==
UDPHY_MODE_USB and keeps target_mode at udphy->hw_mode instead of disabling
the PHY. A subsequent rk_udphy_usb3_phy_exit() clears UDPHY_MODE_USB and
returns early at if (udphy->hs) without calling
rk_udphy_update_power_state(), so rk_udphy_disable() is never called.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261114-b4-rockchip-usbdp-cleanup-part3-v17-0-1af5f566408e@collabora.com?part=4
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
next prev parent reply other threads:[~2026-11-14 2:21 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-14 2:00 [PATCH v17 0/7] phy: rockchip: usbdp: Fix runtime muxing between USB3 and DP Sebastian Reichel
2026-11-14 2:00 ` [PATCH v17 1/7] phy: rockchip: usbdp: Disable USB3 port during normal power-on Sebastian Reichel
2026-11-14 2:00 ` [PATCH v17 2/7] phy: rockchip: usbdp: Drop -EPROBE_DEFER hack Sebastian Reichel
2026-11-14 2:00 ` [PATCH v17 3/7] phy: rockchip: usbdp: Rename mode to hw_mode Sebastian Reichel
2026-11-14 2:00 ` [PATCH v17 4/7] phy: rockchip: usbdp: Fix power state handling Sebastian Reichel
2026-11-14 2:21 ` sashiko-bot [this message]
2026-11-14 2:00 ` [PATCH v17 5/7] phy: rockchip: usbdp: Re-init PHY on mux change Sebastian Reichel
2026-11-14 2:31 ` sashiko-bot
2026-11-14 2:00 ` [PATCH v17 6/7] phy: rockchip: usbdp: Add USB-C state without DP enabled Sebastian Reichel
2026-11-14 2:25 ` sashiko-bot
2026-11-14 2:00 ` [PATCH v17 7/7] phy: rockchip: usbdp: Add DP lane setup to power state update Sebastian Reichel
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-214051@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