brcm_usb_phy_dvr_init() obtains usb_20_clk with of_clk_get_by_name(), which takes a reference on the clock, but several later error returns -- a failed clk_prepare_enable(), a failed devm_phy_create(), the -EPROBE_DEFER paths of usb_30_clk and suspend_clk, and a failed devm_request_irq() -- return without calling clk_put(). No other code in the driver releases it either. Add an err_put_clks label that drops the reference before returning. Fixes: 49859e55e364 ("phy: usb: phy-brcm-usb: Add Broadcom STB USB phy driver") Cc: stable@vger.kernel.org Signed-off-by: Wentao Liang --- drivers/phy/broadcom/phy-brcm-usb.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/phy/broadcom/phy-brcm-usb.c b/drivers/phy/broadcom/phy-brcm-usb.c index 59d756a10d6c..8ef8aa025789 100644 --- a/drivers/phy/broadcom/phy-brcm-usb.c +++ b/drivers/phy/broadcom/phy-brcm-usb.c @@ -415,13 +415,14 @@ static int brcm_usb_phy_dvr_init(struct platform_device *pdev, } err = clk_prepare_enable(priv->usb_20_clk); if (err) - return err; + goto err_put_clks; if (priv->has_eohci) { gphy = devm_phy_create(dev, NULL, &brcm_usb_phy_ops); if (IS_ERR(gphy)) { dev_err(dev, "failed to create EHCI/OHCI PHY\n"); - return PTR_ERR(gphy); + err = PTR_ERR(gphy); + goto err_put_clks; } priv->phys[BRCM_USB_PHY_2_0].phy = gphy; priv->phys[BRCM_USB_PHY_2_0].id = BRCM_USB_PHY_2_0; @@ -432,7 +433,8 @@ static int brcm_usb_phy_dvr_init(struct platform_device *pdev, gphy = devm_phy_create(dev, NULL, &brcm_usb_phy_ops); if (IS_ERR(gphy)) { dev_err(dev, "failed to create XHCI PHY\n"); - return PTR_ERR(gphy); + err = PTR_ERR(gphy); + goto err_put_clks; } priv->phys[BRCM_USB_PHY_3_0].phy = gphy; priv->phys[BRCM_USB_PHY_3_0].id = BRCM_USB_PHY_3_0; @@ -440,21 +442,25 @@ static int brcm_usb_phy_dvr_init(struct platform_device *pdev, priv->usb_30_clk = of_clk_get_by_name(dn, "sw_usb3"); if (IS_ERR(priv->usb_30_clk)) { - if (PTR_ERR(priv->usb_30_clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; + if (PTR_ERR(priv->usb_30_clk) == -EPROBE_DEFER) { + err = -EPROBE_DEFER; + goto err_put_clks; + } dev_info(dev, "USB3.0 clock not found in Device Tree\n"); priv->usb_30_clk = NULL; } err = clk_prepare_enable(priv->usb_30_clk); if (err) - return err; + goto err_put_clks; } priv->suspend_clk = clk_get(dev, "usb0_freerun"); if (IS_ERR(priv->suspend_clk)) { - if (PTR_ERR(priv->suspend_clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; + if (PTR_ERR(priv->suspend_clk) == -EPROBE_DEFER) { + err = -EPROBE_DEFER; + goto err_put_clks; + } dev_err(dev, "Suspend Clock not found in Device Tree\n"); priv->suspend_clk = NULL; } @@ -467,7 +473,7 @@ static int brcm_usb_phy_dvr_init(struct platform_device *pdev, brcm_usb_phy_wake_isr, 0, dev_name(dev), dev); if (err < 0) - return err; + goto err_put_clks; device_set_wakeup_capable(dev, 1); } else { dev_info(dev, @@ -475,6 +481,10 @@ static int brcm_usb_phy_dvr_init(struct platform_device *pdev, } return 0; + +err_put_clks: + clk_put(priv->usb_20_clk); + return err; } static int brcm_usb_phy_probe(struct platform_device *pdev) -- 2.34.1