i2c: rcar: fix PM ref counts in probe error paths
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Fri, 20 May 2022 09:54:21 +0000 (11:54 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jun 2022 08:23:16 +0000 (10:23 +0200)
[ Upstream commit 3fe2ec59db1a7569e18594b9c0cf1f4f1afd498e ]

We have to take care of ID_P_PM_BLOCKED when bailing out during probe.

Fixes: 7ee24eb508d6 ("i2c: rcar: disable PM in multi-master mode")
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/i2c/busses/i2c-rcar.c

index bff9913..2c016f0 100644 (file)
@@ -1070,8 +1070,10 @@ static int rcar_i2c_probe(struct platform_device *pdev)
        pm_runtime_enable(dev);
        pm_runtime_get_sync(dev);
        ret = rcar_i2c_clock_calculate(priv);
-       if (ret < 0)
-               goto out_pm_put;
+       if (ret < 0) {
+               pm_runtime_put(dev);
+               goto out_pm_disable;
+       }
 
        rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
 
@@ -1100,19 +1102,19 @@ static int rcar_i2c_probe(struct platform_device *pdev)
 
        ret = platform_get_irq(pdev, 0);
        if (ret < 0)
-               goto out_pm_disable;
+               goto out_pm_put;
        priv->irq = ret;
        ret = devm_request_irq(dev, priv->irq, irqhandler, irqflags, dev_name(dev), priv);
        if (ret < 0) {
                dev_err(dev, "cannot get irq %d\n", priv->irq);
-               goto out_pm_disable;
+               goto out_pm_put;
        }
 
        platform_set_drvdata(pdev, priv);
 
        ret = i2c_add_numbered_adapter(adap);
        if (ret < 0)
-               goto out_pm_disable;
+               goto out_pm_put;
 
        if (priv->flags & ID_P_HOST_NOTIFY) {
                priv->host_notify_client = i2c_new_slave_host_notify_device(adap);
@@ -1129,7 +1131,8 @@ static int rcar_i2c_probe(struct platform_device *pdev)
  out_del_device:
        i2c_del_adapter(&priv->adap);
  out_pm_put:
-       pm_runtime_put(dev);
+       if (priv->flags & ID_P_PM_BLOCKED)
+               pm_runtime_put(dev);
  out_pm_disable:
        pm_runtime_disable(dev);
        return ret;