Re: [PATCH] usb: dwc3: meson-g12a: fix refcount leak in dwc3_meson_g12a_resume()

From: Thinh Nguyen

Date: Fri Jun 26 2026 - 21:50:02 EST


On Thu, Jun 11, 2026, WenTao Liang wrote:
> If dwc3_meson_g12a_resume() succeeds in calling
> reset_control_reset(), an internal triggered_count reference is
> acquired. If any later step fails (usb_init, phy_init,
> phy_power_on, regulator_enable, or usb_post_init), the function
> returns the error without rearming the reset control. This leaks
> the reference and leaves the reset control in a triggered state,
> causing future reset_control_reset() calls to incorrectly return
> early as if already reset.
>
> Add an error path that calls reset_control_rearm() to balance
> the reference before returning the error.
>
> Cc: stable@xxxxxxxxxxxxxxx
> Fixes: 5b0ba0caaf3a ("usb: dwc3: meson-g12a: refactor usb init")
> Signed-off-by: WenTao Liang <vulab@xxxxxxxxxxx>
> ---
> drivers/usb/dwc3/dwc3-meson-g12a.c | 14 +++++++++-----
> 1 file changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
> index 55e144ba8cfc..4d611c08e8a4 100644
> --- a/drivers/usb/dwc3/dwc3-meson-g12a.c
> +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
> @@ -907,35 +907,39 @@ static int __maybe_unused dwc3_meson_g12a_resume(struct device *dev)
>
> ret = priv->drvdata->usb_init(priv);
> if (ret)
> - return ret;
> + goto err_rearm;
>
> /* Init PHYs */
> for (i = 0 ; i < PHY_COUNT ; ++i) {
> ret = phy_init(priv->phys[i]);
> if (ret)
> - return ret;
> + goto err_rearm;

Should we unwind here and below instead of just reset_control_rearm? I
see we do that in probe() error path.

BR,
Thinh

> }
>
> /* Set PHY Power */
> for (i = 0 ; i < PHY_COUNT ; ++i) {
> ret = phy_power_on(priv->phys[i]);
> if (ret)
> - return ret;
> + goto err_rearm;
> }
>
> if (priv->vbus && priv->otg_phy_mode == PHY_MODE_USB_HOST) {
> ret = regulator_enable(priv->vbus);
> if (ret)
> - return ret;
> + goto err_rearm;
> }
>
> if (priv->drvdata->usb_post_init) {
> ret = priv->drvdata->usb_post_init(priv);
> if (ret)
> - return ret;
> + goto err_rearm;
> }
>
> return 0;
> +
> +err_rearm:
> + reset_control_rearm(priv->reset);
> + return ret;
> }
>
> static const struct dev_pm_ops dwc3_meson_g12a_dev_pm_ops = {
> --
> 2.50.1 (Apple Git-155)
>