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: 27+ 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 ` Sebastian Reichel
2026-11-14 2:00 ` 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 ` Sebastian Reichel
2026-11-14 2:00 ` 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 ` Sebastian Reichel
2026-11-14 2:00 ` 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 ` Sebastian Reichel
2026-11-14 2:00 ` Sebastian Reichel
2026-11-14 2:00 ` [PATCH v17 4/7] phy: rockchip: usbdp: Fix power state handling Sebastian Reichel
2026-11-14 2:00 ` Sebastian Reichel
2026-11-14 2:00 ` 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:00 ` Sebastian Reichel
2026-11-14 2:00 ` 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:00 ` Sebastian Reichel
2026-11-14 2:00 ` 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
2026-11-14 2:00 ` Sebastian Reichel
2026-11-14 2:00 ` 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 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.