media: platform: stm32: unprepare clocks at handling errors in probe
authorEvgeny Novikov <novikov@ispras.ru>
Sat, 10 Jul 2021 12:04:32 +0000 (14:04 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 18 Sep 2021 11:40:20 +0000 (13:40 +0200)
[ Upstream commit 055d2db28ec2fa3ab5c527c5604f1b32b89fa13a ]

stm32_cec_probe() did not unprepare clocks on error handling paths. The
patch fixes that.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Evgeny Novikov <novikov@ispras.ru>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/media/cec/platform/stm32/stm32-cec.c

index ea4b1eb..0ffd897 100644 (file)
@@ -305,14 +305,16 @@ static int stm32_cec_probe(struct platform_device *pdev)
 
        cec->clk_hdmi_cec = devm_clk_get(&pdev->dev, "hdmi-cec");
        if (IS_ERR(cec->clk_hdmi_cec) &&
-           PTR_ERR(cec->clk_hdmi_cec) == -EPROBE_DEFER)
-               return -EPROBE_DEFER;
+           PTR_ERR(cec->clk_hdmi_cec) == -EPROBE_DEFER) {
+               ret = -EPROBE_DEFER;
+               goto err_unprepare_cec_clk;
+       }
 
        if (!IS_ERR(cec->clk_hdmi_cec)) {
                ret = clk_prepare(cec->clk_hdmi_cec);
                if (ret) {
                        dev_err(&pdev->dev, "Can't prepare hdmi-cec clock\n");
-                       return ret;
+                       goto err_unprepare_cec_clk;
                }
        }
 
@@ -324,19 +326,27 @@ static int stm32_cec_probe(struct platform_device *pdev)
                        CEC_NAME, caps, CEC_MAX_LOG_ADDRS);
        ret = PTR_ERR_OR_ZERO(cec->adap);
        if (ret)
-               return ret;
+               goto err_unprepare_hdmi_cec_clk;
 
        ret = cec_register_adapter(cec->adap, &pdev->dev);
-       if (ret) {
-               cec_delete_adapter(cec->adap);
-               return ret;
-       }
+       if (ret)
+               goto err_delete_adapter;
 
        cec_hw_init(cec);
 
        platform_set_drvdata(pdev, cec);
 
        return 0;
+
+err_delete_adapter:
+       cec_delete_adapter(cec->adap);
+
+err_unprepare_hdmi_cec_clk:
+       clk_unprepare(cec->clk_hdmi_cec);
+
+err_unprepare_cec_clk:
+       clk_unprepare(cec->clk_cec);
+       return ret;
 }
 
 static int stm32_cec_remove(struct platform_device *pdev)