drivers: net: cpsw: fix wrong regs access in cpsw_remove
authorGrygorii Strashko <grygorii.strashko@ti.com>
Thu, 28 Jul 2016 17:50:35 +0000 (20:50 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sun, 31 Jul 2016 04:00:33 +0000 (21:00 -0700)
The L3 error will be generated and system will crash during unloading
of CPSW driver if CPSW is used as module and ethX devices are down.
This happens because CPSW can be power off by PM runtime now when ethX
devices are down.

Hence, ensure that CPSW powered up by PM runtime before performing any
deinitialization actions which require CPSW registers access. In case
of PM runtime error just leave cpsw_remove() as we can't do anything
anymore.

Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Reviewed-by: Mugunthan V N <mugunthanvnm@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/ti/cpsw.c

index 1a93a1f28433f128db36c10a3a15a7e3900c4182..47d05242b8c4ef4225a2a2af3ea608124127b7d4 100644 (file)
@@ -2577,6 +2577,13 @@ static int cpsw_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct cpsw_priv *priv = netdev_priv(ndev);
+       int ret;
+
+       ret = pm_runtime_get_sync(&pdev->dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(&pdev->dev);
+               return ret;
+       }
 
        if (priv->data.dual_emac)
                unregister_netdev(cpsw_get_slave_ndev(priv, 1));
@@ -2584,8 +2591,9 @@ static int cpsw_remove(struct platform_device *pdev)
 
        cpsw_ale_destroy(priv->ale);
        cpdma_ctlr_destroy(priv->dma);
-       pm_runtime_disable(&pdev->dev);
        device_for_each_child(&pdev->dev, NULL, cpsw_remove_child_device);
+       pm_runtime_put_sync(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
        if (priv->data.dual_emac)
                free_netdev(cpsw_get_slave_ndev(priv, 1));
        free_netdev(ndev);