From: sashiko-bot@kernel.org
To: "Marek Vasut" <marex@nabladev.com>
Cc: robh@kernel.org, devicetree@vger.kernel.org, vkoul@kernel.org,
neil.armstrong@linaro.org, olteanv@gmail.com,
linux-phy@lists.infradead.org, conor+dt@kernel.org
Subject: Re: [PATCH 2/8] phy: stm32: Add support for ST STM32MP25 USB2-FEMTO PHY
Date: Wed, 12 Aug 2026 01:12:40 +0000 [thread overview]
Message-ID: <20260812011241.2C7D41F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260812010157.1772849-3-marex@nabladev.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Error paths in `stm32_usb2phy_enable` and `stm32_usb2phy_disable` fail to balance the `en_refcnt` reference counter.
- [High] Concurrent hardware initialization between the PHY framework and the Clock framework is not serialized.
- [High] System suspend/resume logic fails to correctly suspend and restore hardware state.
- [Medium] Configuring the host-only PHY into device mode physically corrupts the reference clock selection register.
- [Low] Missing validation of `device_get_match_data()` return value leads to a NULL pointer dereference.
--
--- Patch [2]: [PATCH 2/8] phy: stm32: Add support for ST STM32MP25 USB2-FEMTO PHY ---
commit f2add7ff621e9f11087271861a198a27e1da818a
Author: Pankaj Dev <pankaj.dev@st.com>
phy: stm32: Add support for ST STM32MP25 USB2-FEMTO PHY
This commit adds the USB2 PHY driver for STM32MP25 USB2 controllers. It
supports both the USB2.0 host-only controller and the USB 2.0 part of the
DWC3 controller by differentiating them via compatible strings.
> diff --git a/drivers/phy/st/phy-stm32-usb2phy.c b/drivers/phy/st/phy-stm32-usb2phy.c
> new file mode 100644
> index 0000000000000..d902354f88b69
> --- /dev/null
> +++ b/drivers/phy/st/phy-stm32-usb2phy.c
[ ... ]
> +static int stm32_usb2phy_enable(struct stm32_usb2phy *phy_dev)
> +{
> + const struct stm32mp2_usb2phy_hw_data *phy_data = phy_dev->hw_data;
> + unsigned long rate;
> + int refsel, ret;
> +
> + /* Check if a phy is already init or clk48 in use */
> + if (atomic_inc_return(&phy_dev->en_refcnt) > 1)
> + return 0;
[Severity: High]
Is there a race condition here if both the PHY and Clock frameworks
attempt to enable the hardware concurrently?
If Thread A calls stm32_usb2phy_enable() via phy_init and Thread B calls
it via clk_prepare concurrently:
Thread A increments en_refcnt to 1 and proceeds with initialization.
Thread B increments en_refcnt to 2 and returns success immediately.
Since no mutex is held during the multi-step hardware initialization,
could Thread B start using the hardware before Thread A has finished
configuring it?
> +
> + rate = clk_get_rate(phy_dev->phyref);
> + if (rate == 19200000)
> + refsel = 0;
> + else if (rate == 20000000)
> + refsel = 1;
> + else if (rate == 24000000)
> + refsel = 2;
> + else
> + return -EINVAL;
> +
> + ret = regmap_update_bits(phy_dev->regmap,
> + phy_dev->cr_offset,
> + phy_data->phyrefsel_mask,
> + field_prep(phy_data->phyrefsel_mask, refsel));
> + if (ret)
> + return ret;
[Severity: High]
If regmap_update_bits() fails, does this return early without decrementing
en_refcnt?
This looks like it could leave the reference counter permanently incremented,
preventing future attempts to initialize the PHY or clock if a resource
allocation fails here or in subsequent steps like regulator_enable().
> +
> + if (phy_data->is_usb2_host_only) {
[ ... ]
> +static int stm32_usb2phy_disable(struct stm32_usb2phy *phy_dev)
> +{
> + int ret;
> +
> + /* Check if a phy is still init or clk48 in use */
> + if (atomic_dec_return(&phy_dev->en_refcnt) > 0)
> + return 0;
> +
> + ret = reset_control_assert(phy_dev->rstc);
> + if (ret)
> + return ret;
[Severity: High]
If reset_control_assert() fails, does this skip the remaining hardware disable
steps while leaving en_refcnt already decremented?
> +
> + clk_disable_unprepare(phy_dev->phyref);
> +
> + return regulator_disable(phy_dev->vdd33);
> +}
> +
> +static int stm32_usb2phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
> +{
> + struct stm32_usb2phy *phy_dev = phy_get_drvdata(phy);
> + const struct stm32mp2_usb2phy_hw_data *phy_data = phy_dev->hw_data;
> + u32 val, mask = SYSCFG_USB2PHY2CR_USB2PHY2CMN;
> + int ret;
> +
> + if (mode == PHY_MODE_USB_HOST) {
[ ... ]
> + } else if (mode == PHY_MODE_USB_DEVICE) {
> + val = SYSCFG_USB2PHY2CR_USB2PHY2CMN |
> + SYSCFG_USB2PHY2CR_VBUSVLDEXTSEL;
> + mask |= SYSCFG_USB2PHY2CR_VBUSVALID |
> + SYSCFG_USB2PHY2CR_VBUSVLDEXTSEL |
> + SYSCFG_USB2PHY2CR_VBUSVLDEXT;
> + if (submode != USB_ROLE_NONE)
> + val |= SYSCFG_USB2PHY2CR_VBUSVLDEXT;
> + } else {
> + return -EINVAL;
> + }
> +
> + ret = regmap_update_bits(phy_dev->regmap, phy_dev->cr_offset, mask, val);
[Severity: Medium]
If device mode is mistakenly requested on the host-only PHY variant, does
this unconditionally write the device-mode configuration to bits 4, 5, and 6
of SYSCFG_USB2PHY2CR?
Looking at the hardware data definition for the host-only PHY:
static const struct stm32mp2_usb2phy_hw_data stm32mp25_usb2phy1_hwdata = {
.phyrefsel_mask = GENMASK(6, 4),
.is_usb2_host_only = true,
};
Since those exact bits are used for the reference clock selection, could
this silently corrupt the PHY clock configuration?
> + if (ret)
> + return ret;
[ ... ]
> +static int stm32_usb2phy_probe(struct platform_device *pdev)
> +{
[ ... ]
> + phy_dev->regmap = syscon_regmap_lookup_by_phandle_args(dev->of_node, "st,syscfg", 1,
> + &phy_dev->cr_offset);
> + if (IS_ERR(phy_dev->regmap)) {
> + return dev_err_probe(dev, PTR_ERR(phy_dev->regmap),
> + "No st,syscfg phandle specified\n");
> + }
> +
> + phy_dev->hw_data = device_get_match_data(dev);
[Severity: Low]
If the driver is manually bound via sysfs to a device that does not match
the OF compatible strings, device_get_match_data() could return NULL.
Since the return value is not validated here, could this lead to a NULL
pointer dereference when phy_data->phyrefsel_mask is accessed later in
stm32_usb2phy_enable()?
> +
> + phy = devm_phy_create(dev, NULL, &stm32_usb2phy_data);
> + if (IS_ERR(phy))
> + return dev_err_probe(dev, PTR_ERR(phy), "Failed to create PHY\n");
[ ... ]
> +static int stm32_usb2phy_suspend(struct device *dev)
> +{
> + struct stm32_usb2phy *phy_dev = dev_get_drvdata(dev);
> +
> + if (phy_dev->is_init)
> + return stm32_usb2phy_disable(phy_dev);
> +
> + return 0;
> +}
> +
> +static int stm32_usb2phy_resume(struct device *dev)
> +{
> + struct stm32_usb2phy *phy_dev = dev_get_drvdata(dev);
> +
> + if (phy_dev->is_init)
> + return stm32_usb2phy_enable(phy_dev);
> +
> + return 0;
> +}
[Severity: High]
Does this system suspend/resume logic properly save and restore hardware
state when both the PHY and clock consumers are active?
If en_refcnt is 2, calling stm32_usb2phy_disable() during suspend will merely
decrement the counter to 1 and skip the actual hardware teardown. Conversely,
on resume, stm32_usb2phy_enable() increments the counter to 2 and skips
hardware initialization.
If power is lost during suspend, could the hardware remain completely
uninitialized upon resume?
Additionally, stm32_usb2phy_resume() does not appear to call
stm32_usb2phy_set_mode(), which might mean the PHY mode configuration is lost
after resuming.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260812010157.1772849-1-marex@nabladev.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: "Marek Vasut" <marex@nabladev.com>
Cc: robh@kernel.org, devicetree@vger.kernel.org, vkoul@kernel.org,
neil.armstrong@linaro.org, olteanv@gmail.com,
linux-phy@lists.infradead.org, conor+dt@kernel.org
Subject: Re: [PATCH 2/8] phy: stm32: Add support for ST STM32MP25 USB2-FEMTO PHY
Date: Wed, 12 Aug 2026 01:12:40 +0000 [thread overview]
Message-ID: <20260812011241.2C7D41F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260812010157.1772849-3-marex@nabladev.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Error paths in `stm32_usb2phy_enable` and `stm32_usb2phy_disable` fail to balance the `en_refcnt` reference counter.
- [High] Concurrent hardware initialization between the PHY framework and the Clock framework is not serialized.
- [High] System suspend/resume logic fails to correctly suspend and restore hardware state.
- [Medium] Configuring the host-only PHY into device mode physically corrupts the reference clock selection register.
- [Low] Missing validation of `device_get_match_data()` return value leads to a NULL pointer dereference.
--
--- Patch [2]: [PATCH 2/8] phy: stm32: Add support for ST STM32MP25 USB2-FEMTO PHY ---
commit f2add7ff621e9f11087271861a198a27e1da818a
Author: Pankaj Dev <pankaj.dev@st.com>
phy: stm32: Add support for ST STM32MP25 USB2-FEMTO PHY
This commit adds the USB2 PHY driver for STM32MP25 USB2 controllers. It
supports both the USB2.0 host-only controller and the USB 2.0 part of the
DWC3 controller by differentiating them via compatible strings.
> diff --git a/drivers/phy/st/phy-stm32-usb2phy.c b/drivers/phy/st/phy-stm32-usb2phy.c
> new file mode 100644
> index 0000000000000..d902354f88b69
> --- /dev/null
> +++ b/drivers/phy/st/phy-stm32-usb2phy.c
[ ... ]
> +static int stm32_usb2phy_enable(struct stm32_usb2phy *phy_dev)
> +{
> + const struct stm32mp2_usb2phy_hw_data *phy_data = phy_dev->hw_data;
> + unsigned long rate;
> + int refsel, ret;
> +
> + /* Check if a phy is already init or clk48 in use */
> + if (atomic_inc_return(&phy_dev->en_refcnt) > 1)
> + return 0;
[Severity: High]
Is there a race condition here if both the PHY and Clock frameworks
attempt to enable the hardware concurrently?
If Thread A calls stm32_usb2phy_enable() via phy_init and Thread B calls
it via clk_prepare concurrently:
Thread A increments en_refcnt to 1 and proceeds with initialization.
Thread B increments en_refcnt to 2 and returns success immediately.
Since no mutex is held during the multi-step hardware initialization,
could Thread B start using the hardware before Thread A has finished
configuring it?
> +
> + rate = clk_get_rate(phy_dev->phyref);
> + if (rate == 19200000)
> + refsel = 0;
> + else if (rate == 20000000)
> + refsel = 1;
> + else if (rate == 24000000)
> + refsel = 2;
> + else
> + return -EINVAL;
> +
> + ret = regmap_update_bits(phy_dev->regmap,
> + phy_dev->cr_offset,
> + phy_data->phyrefsel_mask,
> + field_prep(phy_data->phyrefsel_mask, refsel));
> + if (ret)
> + return ret;
[Severity: High]
If regmap_update_bits() fails, does this return early without decrementing
en_refcnt?
This looks like it could leave the reference counter permanently incremented,
preventing future attempts to initialize the PHY or clock if a resource
allocation fails here or in subsequent steps like regulator_enable().
> +
> + if (phy_data->is_usb2_host_only) {
[ ... ]
> +static int stm32_usb2phy_disable(struct stm32_usb2phy *phy_dev)
> +{
> + int ret;
> +
> + /* Check if a phy is still init or clk48 in use */
> + if (atomic_dec_return(&phy_dev->en_refcnt) > 0)
> + return 0;
> +
> + ret = reset_control_assert(phy_dev->rstc);
> + if (ret)
> + return ret;
[Severity: High]
If reset_control_assert() fails, does this skip the remaining hardware disable
steps while leaving en_refcnt already decremented?
> +
> + clk_disable_unprepare(phy_dev->phyref);
> +
> + return regulator_disable(phy_dev->vdd33);
> +}
> +
> +static int stm32_usb2phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
> +{
> + struct stm32_usb2phy *phy_dev = phy_get_drvdata(phy);
> + const struct stm32mp2_usb2phy_hw_data *phy_data = phy_dev->hw_data;
> + u32 val, mask = SYSCFG_USB2PHY2CR_USB2PHY2CMN;
> + int ret;
> +
> + if (mode == PHY_MODE_USB_HOST) {
[ ... ]
> + } else if (mode == PHY_MODE_USB_DEVICE) {
> + val = SYSCFG_USB2PHY2CR_USB2PHY2CMN |
> + SYSCFG_USB2PHY2CR_VBUSVLDEXTSEL;
> + mask |= SYSCFG_USB2PHY2CR_VBUSVALID |
> + SYSCFG_USB2PHY2CR_VBUSVLDEXTSEL |
> + SYSCFG_USB2PHY2CR_VBUSVLDEXT;
> + if (submode != USB_ROLE_NONE)
> + val |= SYSCFG_USB2PHY2CR_VBUSVLDEXT;
> + } else {
> + return -EINVAL;
> + }
> +
> + ret = regmap_update_bits(phy_dev->regmap, phy_dev->cr_offset, mask, val);
[Severity: Medium]
If device mode is mistakenly requested on the host-only PHY variant, does
this unconditionally write the device-mode configuration to bits 4, 5, and 6
of SYSCFG_USB2PHY2CR?
Looking at the hardware data definition for the host-only PHY:
static const struct stm32mp2_usb2phy_hw_data stm32mp25_usb2phy1_hwdata = {
.phyrefsel_mask = GENMASK(6, 4),
.is_usb2_host_only = true,
};
Since those exact bits are used for the reference clock selection, could
this silently corrupt the PHY clock configuration?
> + if (ret)
> + return ret;
[ ... ]
> +static int stm32_usb2phy_probe(struct platform_device *pdev)
> +{
[ ... ]
> + phy_dev->regmap = syscon_regmap_lookup_by_phandle_args(dev->of_node, "st,syscfg", 1,
> + &phy_dev->cr_offset);
> + if (IS_ERR(phy_dev->regmap)) {
> + return dev_err_probe(dev, PTR_ERR(phy_dev->regmap),
> + "No st,syscfg phandle specified\n");
> + }
> +
> + phy_dev->hw_data = device_get_match_data(dev);
[Severity: Low]
If the driver is manually bound via sysfs to a device that does not match
the OF compatible strings, device_get_match_data() could return NULL.
Since the return value is not validated here, could this lead to a NULL
pointer dereference when phy_data->phyrefsel_mask is accessed later in
stm32_usb2phy_enable()?
> +
> + phy = devm_phy_create(dev, NULL, &stm32_usb2phy_data);
> + if (IS_ERR(phy))
> + return dev_err_probe(dev, PTR_ERR(phy), "Failed to create PHY\n");
[ ... ]
> +static int stm32_usb2phy_suspend(struct device *dev)
> +{
> + struct stm32_usb2phy *phy_dev = dev_get_drvdata(dev);
> +
> + if (phy_dev->is_init)
> + return stm32_usb2phy_disable(phy_dev);
> +
> + return 0;
> +}
> +
> +static int stm32_usb2phy_resume(struct device *dev)
> +{
> + struct stm32_usb2phy *phy_dev = dev_get_drvdata(dev);
> +
> + if (phy_dev->is_init)
> + return stm32_usb2phy_enable(phy_dev);
> +
> + return 0;
> +}
[Severity: High]
Does this system suspend/resume logic properly save and restore hardware
state when both the PHY and clock consumers are active?
If en_refcnt is 2, calling stm32_usb2phy_disable() during suspend will merely
decrement the counter to 1 and skip the actual hardware teardown. Conversely,
on resume, stm32_usb2phy_enable() increments the counter to 2 and skips
hardware initialization.
If power is lost during suspend, could the hardware remain completely
uninitialized upon resume?
Additionally, stm32_usb2phy_resume() does not appear to call
stm32_usb2phy_set_mode(), which might mean the PHY mode configuration is lost
after resuming.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260812010157.1772849-1-marex@nabladev.com?part=2
next prev parent reply other threads:[~2026-08-12 1:12 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-12 0:55 [PATCH 0/8] arm64: dts: phy: st: usb: Add STM32MP2 USB support Marek Vasut
2026-08-12 0:55 ` Marek Vasut
2026-08-12 0:55 ` [PATCH 1/8] dt-bindings: phy: Document ST STM32MP25 USB2-FEMTO PHY Marek Vasut
2026-08-12 0:55 ` Marek Vasut
2026-08-12 1:05 ` sashiko-bot
2026-08-12 1:05 ` sashiko-bot
2026-08-12 2:45 ` Rob Herring (Arm)
2026-08-12 2:45 ` Rob Herring (Arm)
2026-08-12 0:55 ` [PATCH 2/8] phy: stm32: Add support for " Marek Vasut
2026-08-12 0:55 ` Marek Vasut
2026-08-12 1:12 ` sashiko-bot [this message]
2026-08-12 1:12 ` sashiko-bot
2026-08-12 0:55 ` [PATCH 3/8] dt-bindings: usb: generic-ehci: Document access-controllers property Marek Vasut
2026-08-12 0:55 ` Marek Vasut
2026-08-12 1:10 ` sashiko-bot
2026-08-12 1:10 ` sashiko-bot
2026-08-12 0:55 ` [PATCH 4/8] dt-bindings: usb: generic-ohci: " Marek Vasut
2026-08-12 0:55 ` Marek Vasut
2026-08-12 0:55 ` [PATCH 5/8] dt-bindings: usb: dwc3: Document ST STM32MP2 DWC3 xHCI USB controller Marek Vasut
2026-08-12 0:55 ` Marek Vasut
2026-08-12 1:08 ` sashiko-bot
2026-08-12 1:08 ` sashiko-bot
2026-08-12 0:55 ` [PATCH 6/8] usb: dwc3: dwc3-generic-plat: Add ST STM32MP2 DWC3 xHCI USB controller glue Marek Vasut
2026-08-12 0:55 ` Marek Vasut
2026-08-12 1:11 ` sashiko-bot
2026-08-12 1:11 ` sashiko-bot
2026-08-12 0:55 ` [PATCH 7/8] arm64: dts: st: Add USB nodes on stm32mp231 Marek Vasut
2026-08-12 0:55 ` Marek Vasut
2026-08-12 0:55 ` [PATCH 8/8] arm64: dts: st: Add USB nodes on stm32mp251 Marek Vasut
2026-08-12 0:55 ` Marek Vasut
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=20260812011241.2C7D41F00A3A@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=marex@nabladev.com \
--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.