aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/ti
diff options
context:
space:
mode:
authorGrygorii Strashko <grygorii.strashko@ti.com>2016-07-28 13:50:35 -0400
committerDavid S. Miller <davem@davemloft.net>2016-07-31 00:00:33 -0400
commit8a0b6dc958fd1037931b0e01ebf266fbe3c09e92 (patch)
treefcce5b52c32c476cc583c10b89d03052ae1e6243 /drivers/net/ethernet/ti
parentfccd5badb84de03fef9b072e7ae72fe0ea8348e3 (diff)
drivers: net: cpsw: fix wrong regs access in cpsw_remove
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>
Diffstat (limited to 'drivers/net/ethernet/ti')
-rw-r--r--drivers/net/ethernet/ti/cpsw.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 1a93a1f28433..47d05242b8c4 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -2577,6 +2577,13 @@ static int cpsw_remove(struct platform_device *pdev)
2577{ 2577{
2578 struct net_device *ndev = platform_get_drvdata(pdev); 2578 struct net_device *ndev = platform_get_drvdata(pdev);
2579 struct cpsw_priv *priv = netdev_priv(ndev); 2579 struct cpsw_priv *priv = netdev_priv(ndev);
2580 int ret;
2581
2582 ret = pm_runtime_get_sync(&pdev->dev);
2583 if (ret < 0) {
2584 pm_runtime_put_noidle(&pdev->dev);
2585 return ret;
2586 }
2580 2587
2581 if (priv->data.dual_emac) 2588 if (priv->data.dual_emac)
2582 unregister_netdev(cpsw_get_slave_ndev(priv, 1)); 2589 unregister_netdev(cpsw_get_slave_ndev(priv, 1));
@@ -2584,8 +2591,9 @@ static int cpsw_remove(struct platform_device *pdev)
2584 2591
2585 cpsw_ale_destroy(priv->ale); 2592 cpsw_ale_destroy(priv->ale);
2586 cpdma_ctlr_destroy(priv->dma); 2593 cpdma_ctlr_destroy(priv->dma);
2587 pm_runtime_disable(&pdev->dev);
2588 device_for_each_child(&pdev->dev, NULL, cpsw_remove_child_device); 2594 device_for_each_child(&pdev->dev, NULL, cpsw_remove_child_device);
2595 pm_runtime_put_sync(&pdev->dev);
2596 pm_runtime_disable(&pdev->dev);
2589 if (priv->data.dual_emac) 2597 if (priv->data.dual_emac)
2590 free_netdev(cpsw_get_slave_ndev(priv, 1)); 2598 free_netdev(cpsw_get_slave_ndev(priv, 1));
2591 free_netdev(ndev); 2599 free_netdev(ndev);