diff options
author | Johan Hovold <johan@kernel.org> | 2016-11-17 11:40:01 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-11-18 13:48:53 -0500 |
commit | 8cbcc466fd4abd38a14b9d9b76c63a2cb7006554 (patch) | |
tree | 68075bfa1f37f62b88fe4482c043889c21d38535 /drivers/net/ethernet/ti | |
parent | a4e32b0d0a26ba2f2ba1c65bd403d06ccc1df29c (diff) |
net: ethernet: ti: cpsw: fix of_node and phydev leaks
Make sure to drop references taken and deregister devices registered
during probe on probe errors (including deferred probe) and driver
unbind.
Specifically, PHY of-node references were never released and fixed-link
PHY devices were never deregistered.
Fixes: 9e42f715264f ("drivers: net: cpsw: add phy-handle parsing")
Fixes: 1f71e8c96fc6 ("drivers: net: cpsw: Add support for fixed-link
PHY")
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/ti')
-rw-r--r-- | drivers/net/ethernet/ti/cpsw.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 5d14abb06486..c3b78bc4fe58 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c | |||
@@ -2443,6 +2443,41 @@ no_phy_slave: | |||
2443 | 2443 | ||
2444 | static void cpsw_remove_dt(struct platform_device *pdev) | 2444 | static void cpsw_remove_dt(struct platform_device *pdev) |
2445 | { | 2445 | { |
2446 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
2447 | struct cpsw_common *cpsw = ndev_to_cpsw(ndev); | ||
2448 | struct cpsw_platform_data *data = &cpsw->data; | ||
2449 | struct device_node *node = pdev->dev.of_node; | ||
2450 | struct device_node *slave_node; | ||
2451 | int i = 0; | ||
2452 | |||
2453 | for_each_available_child_of_node(node, slave_node) { | ||
2454 | struct cpsw_slave_data *slave_data = &data->slave_data[i]; | ||
2455 | |||
2456 | if (strcmp(slave_node->name, "slave")) | ||
2457 | continue; | ||
2458 | |||
2459 | if (of_phy_is_fixed_link(slave_node)) { | ||
2460 | struct phy_device *phydev; | ||
2461 | |||
2462 | phydev = of_phy_find_device(slave_node); | ||
2463 | if (phydev) { | ||
2464 | fixed_phy_unregister(phydev); | ||
2465 | /* Put references taken by | ||
2466 | * of_phy_find_device() and | ||
2467 | * of_phy_register_fixed_link(). | ||
2468 | */ | ||
2469 | phy_device_free(phydev); | ||
2470 | phy_device_free(phydev); | ||
2471 | } | ||
2472 | } | ||
2473 | |||
2474 | of_node_put(slave_data->phy_node); | ||
2475 | |||
2476 | i++; | ||
2477 | if (i == data->slaves) | ||
2478 | break; | ||
2479 | } | ||
2480 | |||
2446 | of_platform_depopulate(&pdev->dev); | 2481 | of_platform_depopulate(&pdev->dev); |
2447 | } | 2482 | } |
2448 | 2483 | ||