summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrygorii Strashko <grygorii.strashko@ti.com>2016-07-28 20:50:35 +0300
committerDavid S. Miller <davem@davemloft.net>2016-07-30 21:00:33 -0700
commit8a0b6dc958fd1037931b0e01ebf266fbe3c09e92 (patch)
treefcce5b52c32c476cc583c10b89d03052ae1e6243
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>
-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)
{
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);