aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReece R. Pollack2015-02-16 13:35:36 -0600
committerReece R. Pollack2015-02-16 16:30:35 -0600
commit1cd9632166b2863dfe5bebe8f19ce085cf9fb754 (patch)
tree5e6478c40765c124b9bd3f73d702d7ae3a8e2867 /drivers/net/ethernet/ti/keystone_ethss2.c
parent760a81522f9b37745a9fde6afd21a727c8f3cbbd (diff)
downloadlinux-1cd9632166b2863dfe5bebe8f19ce085cf9fb754.tar.gz
linux-1cd9632166b2863dfe5bebe8f19ce085cf9fb754.tar.xz
linux-1cd9632166b2863dfe5bebe8f19ce085cf9fb754.zip
net: keystone: Fix memory leak in CPSW ALE configuration
Prior to this patch, the CPSW ALE context was created when the first interface on a device was opened, but it was not destroyed when the last interface was closed (it was stopped instead). This resulted in a memory leak. This patch corrects this. Also, the ALE Slaves were being shut down after the ALE context was being destroyed. This could result in a NULL pointer reference. This patch fixes this too. Finally, the ALE reference count in keystone_xgess.c was a non-atomic integer, while the other modules used an atomic. This patch fixes this and includes some minor restructuring so the code looks more like the other two modules. Signed-off-by: Reece R. Pollack <x0183204@ti.com>
Diffstat (limited to 'drivers/net/ethernet/ti/keystone_ethss2.c')
-rw-r--r--drivers/net/ethernet/ti/keystone_ethss2.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/drivers/net/ethernet/ti/keystone_ethss2.c b/drivers/net/ethernet/ti/keystone_ethss2.c
index f334bdb3ab5..5560d6e2c00 100644
--- a/drivers/net/ethernet/ti/keystone_ethss2.c
+++ b/drivers/net/ethernet/ti/keystone_ethss2.c
@@ -3510,11 +3510,13 @@ static int cpsw2_close(void *intf_priv, struct net_device *ndev)
3510 3510
3511 del_timer_sync(&cpsw_intf->timer); 3511 del_timer_sync(&cpsw_intf->timer);
3512 3512
3513 if (atomic_dec_return(&cpsw_dev->ale_refcnt) == 0)
3514 cpsw_ale_stop(cpsw_dev->ale);
3515
3516 for_each_slave(cpsw_intf, cpsw2_slave_stop, cpsw_intf); 3513 for_each_slave(cpsw_intf, cpsw2_slave_stop, cpsw_intf);
3517 3514
3515 if (atomic_dec_return(&cpsw_dev->ale_refcnt) == 0) {
3516 cpsw_ale_destroy(cpsw_dev->ale);
3517 cpsw_dev->ale = NULL;
3518 }
3519
3518 if (!cpsw_dev->force_no_hwtstamp) 3520 if (!cpsw_dev->force_no_hwtstamp)
3519 netcp_unregister_rxhook(netcp, CPSW2_RXHOOK_ORDER, 3521 netcp_unregister_rxhook(netcp, CPSW2_RXHOOK_ORDER,
3520 cpsw2_rx_hook, cpsw_intf); 3522 cpsw2_rx_hook, cpsw_intf);
@@ -3538,8 +3540,6 @@ static int cpsw2_remove(struct netcp_device *netcp_device, void *inst_priv)
3538 3540
3539 of_node_put(cpsw_dev->interfaces); 3541 of_node_put(cpsw_dev->interfaces);
3540 3542
3541 cpsw_ale_destroy(cpsw_dev->ale);
3542
3543 list_for_each_entry_safe(cpsw_intf, tmp, &cpsw_dev->cpsw_intf_head, 3543 list_for_each_entry_safe(cpsw_intf, tmp, &cpsw_dev->cpsw_intf_head,
3544 cpsw_intf_list) { 3544 cpsw_intf_list) {
3545 netcp_delete_interface(netcp_device, cpsw_intf->ndev); 3545 netcp_delete_interface(netcp_device, cpsw_intf->ndev);