]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
usb: dwc3: meson-g12a: fix refcount leak in dwc3_meson_g12a_resume()
authorWenTao Liang <vulab@iscas.ac.cn>
Thu, 11 Jun 2026 13:11:21 +0000 (21:11 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Jun 2026 15:04:11 +0000 (16:04 +0100)
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 <stable@kernel.org>
Fixes: 5b0ba0caaf3a ("usb: dwc3: meson-g12a: refactor usb init")
Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
Link: https://patch.msgid.link/20260611131121.81784-1-vulab@iscas.ac.cn
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/dwc3/dwc3-meson-g12a.c

index 55e144ba8cfc6c30dc28b4e808a3a23d7291c33c..4d611c08e8a4cf09d51fb5b6255f0c5624600e25 100644 (file)
@@ -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;
        }
 
        /* 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 = {