Commit 122e9b71 authored by David S. Miller's avatar David S. Miller

Merge branch 'cpsw-fixes'

Grygorii Strashko says:

====================
drivers: net: cpsw: fix driver loading/unloading

This series fixes set of isssues observed when CPSW driver module is unloaded/loaded:
1) rmmod: deadlock in cpdma_ctlr_destroy
2) rmmod: L3 back-trace and crash if all net interfaces are down, because CPSW
can be powerred down by PM runtime in this case.
3) insmod: mdio device is not recreated on next insmod
 - need to use of_platform_depopulate() in cpsw_remove().
4) rmmod: system crash on omap_device removal

Tested on: am437x-idk, am57xx-beagle-x15

Changes in v2:
- build warning fixed
- added fix for correct omap_device removal

Link on v1:
 https://lkml.org/lkml/2016/7/22/240
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c882219a 213fa10d
......@@ -194,7 +194,7 @@ static int _omap_device_notifier_call(struct notifier_block *nb,
int err;
switch (event) {
case BUS_NOTIFY_DEL_DEVICE:
case BUS_NOTIFY_REMOVED_DEVICE:
if (pdev->archdata.od)
omap_device_delete(pdev->archdata.od);
break;
......
......@@ -2564,19 +2564,17 @@ static int cpsw_probe(struct platform_device *pdev)
return ret;
}
static int cpsw_remove_child_device(struct device *dev, void *c)
{
struct platform_device *pdev = to_platform_device(dev);
of_device_unregister(pdev);
return 0;
}
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 +2582,9 @@ static int cpsw_remove(struct platform_device *pdev)
cpsw_ale_destroy(priv->ale);
cpdma_ctlr_destroy(priv->dma);
of_platform_depopulate(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
device_for_each_child(&pdev->dev, NULL, cpsw_remove_child_device);
if (priv->data.dual_emac)
free_netdev(cpsw_get_slave_ndev(priv, 1));
free_netdev(ndev);
......
......@@ -357,13 +357,11 @@ EXPORT_SYMBOL_GPL(cpdma_ctlr_stop);
int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
{
unsigned long flags;
int ret = 0, i;
if (!ctlr)
return -EINVAL;
spin_lock_irqsave(&ctlr->lock, flags);
if (ctlr->state != CPDMA_STATE_IDLE)
cpdma_ctlr_stop(ctlr);
......@@ -371,7 +369,6 @@ int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
cpdma_chan_destroy(ctlr->channels[i]);
cpdma_desc_pool_destroy(ctlr->pool);
spin_unlock_irqrestore(&ctlr->lock, flags);
return ret;
}
EXPORT_SYMBOL_GPL(cpdma_ctlr_destroy);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment