i2c: tegra: Properly disable runtime PM on driver's probe error
authorDmitry Osipenko <digetx@gmail.com>
Tue, 14 Jan 2020 01:34:36 +0000 (04:34 +0300)
committerWolfram Sang <wsa@the-dreams.de>
Wed, 15 Jan 2020 17:17:15 +0000 (18:17 +0100)
One of the recent Tegra I2C commits made a change that resumes runtime PM
during driver's probe, but it missed to put the RPM in a case of error.
Note that it's not correct to use pm_runtime_status_suspended because it
breaks RPM refcounting.

Fixes: 8ebf15e9c869 ("i2c: tegra: Move suspend handling to NOIRQ phase")
Cc: <stable@vger.kernel.org> # v5.4+
Tested-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
drivers/i2c/busses/i2c-tegra.c

index 79d19f6..61339c6 100644 (file)
@@ -1608,14 +1608,18 @@ static int tegra_i2c_probe(struct platform_device *pdev)
        }
 
        pm_runtime_enable(&pdev->dev);
-       if (!pm_runtime_enabled(&pdev->dev))
+       if (!pm_runtime_enabled(&pdev->dev)) {
                ret = tegra_i2c_runtime_resume(&pdev->dev);
-       else
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "runtime resume failed\n");
+                       goto unprepare_div_clk;
+               }
+       } else {
                ret = pm_runtime_get_sync(i2c_dev->dev);
-
-       if (ret < 0) {
-               dev_err(&pdev->dev, "runtime resume failed\n");
-               goto unprepare_div_clk;
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "runtime resume failed\n");
+                       goto disable_rpm;
+               }
        }
 
        if (i2c_dev->is_multimaster_mode) {
@@ -1623,7 +1627,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
                if (ret < 0) {
                        dev_err(i2c_dev->dev, "div_clk enable failed %d\n",
                                ret);
-                       goto disable_rpm;
+                       goto put_rpm;
                }
        }
 
@@ -1671,11 +1675,16 @@ disable_div_clk:
        if (i2c_dev->is_multimaster_mode)
                clk_disable(i2c_dev->div_clk);
 
-disable_rpm:
-       pm_runtime_disable(&pdev->dev);
-       if (!pm_runtime_status_suspended(&pdev->dev))
+put_rpm:
+       if (pm_runtime_enabled(&pdev->dev))
+               pm_runtime_put_sync(&pdev->dev);
+       else
                tegra_i2c_runtime_suspend(&pdev->dev);
 
+disable_rpm:
+       if (pm_runtime_enabled(&pdev->dev))
+               pm_runtime_disable(&pdev->dev);
+
 unprepare_div_clk:
        clk_unprepare(i2c_dev->div_clk);