Skip to content

Commit

Permalink
net/cpsw: make sure modules remove does not leak any ressources
Browse files Browse the repository at this point in the history
This driver does not clean up properly after leaving. Here is a list:
- Use unregister_netdev(). free_netdev() is good but not enough
- Use the above also on the other ndev in case of dual mac
- Free data.slave_data. The name of the strucre makes it look like
  it is platform_data but it is not. It is just a trick!
- Free all irqs. Again: freeing one irq is good start, but freeing all
  of them is better.

With this rmmod & modprobe of cpsw seems to work. The remaining issue
is:
|WARNING: at fs/sysfs/dir.c:536 sysfs_add_one+0x9c/0xd4()
|sysfs: cannot create duplicate filename '/devices/ocp.2/4a100000.ethernet/4a101000.mdio'
|WARNING: at lib/kobject.c:196 kobject_add_internal+0x1a4/0x1c8()

comming from of_platform_populate() and I am not sure that this belongs
here.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Sebastian Siewior authored and David S. Miller committed Apr 25, 2013
1 parent 4bc21d4 commit d1bd9ac
Showing 1 changed file with 16 additions and 7 deletions.
23 changes: 16 additions & 7 deletions drivers/net/ethernet/ti/cpsw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1632,7 +1632,7 @@ static int cpsw_probe_dual_emac(struct platform_device *pdev,

static int cpsw_probe(struct platform_device *pdev)
{
struct cpsw_platform_data *data = pdev->dev.platform_data;
struct cpsw_platform_data *data;
struct net_device *ndev;
struct cpsw_priv *priv;
struct cpdma_params dma_params;
Expand Down Expand Up @@ -1845,7 +1845,7 @@ static int cpsw_probe(struct platform_device *pdev)
goto clean_ale_ret;
}
priv->irqs_table[k] = i;
priv->num_irqs = k;
priv->num_irqs = k + 1;
}
k++;
}
Expand Down Expand Up @@ -1883,7 +1883,8 @@ static int cpsw_probe(struct platform_device *pdev)
return 0;

clean_irq_ret:
free_irq(ndev->irq, priv);
for (i = 0; i < priv->num_irqs; i++)
free_irq(priv->irqs_table[i], priv);
clean_ale_ret:
cpsw_ale_destroy(priv->ale);
clean_dma_ret:
Expand All @@ -1906,20 +1907,26 @@ static int cpsw_probe(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
kfree(priv->slaves);
clean_ndev_ret:
free_netdev(ndev);
kfree(priv->data.slave_data);
free_netdev(priv->ndev);
return ret;
}

static int cpsw_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct cpsw_priv *priv = netdev_priv(ndev);
int i;

pr_info("removing device");
platform_set_drvdata(pdev, NULL);
if (priv->data.dual_emac)
unregister_netdev(cpsw_get_slave_ndev(priv, 1));
unregister_netdev(ndev);

cpts_unregister(priv->cpts);
free_irq(ndev->irq, priv);
for (i = 0; i < priv->num_irqs; i++)
free_irq(priv->irqs_table[i], priv);

cpsw_ale_destroy(priv->ale);
cpdma_chan_destroy(priv->txch);
cpdma_chan_destroy(priv->rxch);
Expand All @@ -1933,8 +1940,10 @@ static int cpsw_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
clk_put(priv->clk);
kfree(priv->slaves);
kfree(priv->data.slave_data);
if (priv->data.dual_emac)
free_netdev(cpsw_get_slave_ndev(priv, 1));
free_netdev(ndev);

return 0;
}

Expand Down

0 comments on commit d1bd9ac

Please sign in to comment.