From: Tong Zhang <ztong0...@gmail.com>

[ Upstream commit 6e2fe01dd6f98da6cae8b07cd5cfa67abc70d97d ]

Currently doing modprobe c_can_pci will make the kernel complain:

    Unbalanced pm_runtime_enable!

this is caused by pm_runtime_enable() called before pm is initialized.

This fix is similar to 227619c3ff7c, move those pm_enable/disable code
to c_can_platform.

Fixes: 4cdd34b26826 ("can: c_can: Add runtime PM support to Bosch C_CAN/D_CAN 
controller")
Link: http://lore.kernel.org/r/20210302025542.987600-1-ztong0...@gmail.com
Signed-off-by: Tong Zhang <ztong0...@gmail.com>
Tested-by: Uwe Kleine-König <u.kleine-koe...@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <m...@pengutronix.de>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 drivers/net/can/c_can/c_can.c          | 24 +-----------------------
 drivers/net/can/c_can/c_can_platform.c |  6 +++++-
 2 files changed, 6 insertions(+), 24 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 8e9f5620c9a2..f14e739ba3f4 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -212,18 +212,6 @@ static const struct can_bittiming_const 
c_can_bittiming_const = {
        .brp_inc = 1,
 };
 
-static inline void c_can_pm_runtime_enable(const struct c_can_priv *priv)
-{
-       if (priv->device)
-               pm_runtime_enable(priv->device);
-}
-
-static inline void c_can_pm_runtime_disable(const struct c_can_priv *priv)
-{
-       if (priv->device)
-               pm_runtime_disable(priv->device);
-}
-
 static inline void c_can_pm_runtime_get_sync(const struct c_can_priv *priv)
 {
        if (priv->device)
@@ -1334,7 +1322,6 @@ static const struct net_device_ops c_can_netdev_ops = {
 
 int register_c_can_dev(struct net_device *dev)
 {
-       struct c_can_priv *priv = netdev_priv(dev);
        int err;
 
        /* Deactivate pins to prevent DRA7 DCAN IP from being
@@ -1344,28 +1331,19 @@ int register_c_can_dev(struct net_device *dev)
         */
        pinctrl_pm_select_sleep_state(dev->dev.parent);
 
-       c_can_pm_runtime_enable(priv);
-
        dev->flags |= IFF_ECHO; /* we support local echo */
        dev->netdev_ops = &c_can_netdev_ops;
 
        err = register_candev(dev);
-       if (err)
-               c_can_pm_runtime_disable(priv);
-       else
+       if (!err)
                devm_can_led_init(dev);
-
        return err;
 }
 EXPORT_SYMBOL_GPL(register_c_can_dev);
 
 void unregister_c_can_dev(struct net_device *dev)
 {
-       struct c_can_priv *priv = netdev_priv(dev);
-
        unregister_candev(dev);
-
-       c_can_pm_runtime_disable(priv);
 }
 EXPORT_SYMBOL_GPL(unregister_c_can_dev);
 
diff --git a/drivers/net/can/c_can/c_can_platform.c 
b/drivers/net/can/c_can/c_can_platform.c
index b5145a7f874c..f2b0408ce87d 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -29,6 +29,7 @@
 #include <linux/list.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/clk.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -385,6 +386,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
+       pm_runtime_enable(priv->device);
        ret = register_c_can_dev(dev);
        if (ret) {
                dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
@@ -397,6 +399,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
        return 0;
 
 exit_free_device:
+       pm_runtime_disable(priv->device);
        free_c_can_dev(dev);
 exit:
        dev_err(&pdev->dev, "probe failed\n");
@@ -407,9 +410,10 @@ exit:
 static int c_can_plat_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
+       struct c_can_priv *priv = netdev_priv(dev);
 
        unregister_c_can_dev(dev);
-
+       pm_runtime_disable(priv->device);
        free_c_can_dev(dev);
 
        return 0;
-- 
2.30.1



Reply via email to