diff options
author | David S. Miller <davem@davemloft.net> | 2016-11-29 23:17:04 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-11-29 23:17:04 -0500 |
commit | f2ebf2a6ca94e78be179e8c99d34c87efc5e8bfb (patch) | |
tree | d7a3fd6644f2f711212b7e7cc7cabb113747128b | |
parent | a510887824171ad260cc4a2603396c6247fdd091 (diff) | |
parent | 881eadabe71fa78c081eda3cd5701768f3778a21 (diff) |
Merge branch 'fixed-phy-phydev-leaks'
Johan Hovold says:
====================
net: fix fixed-link phydev leaks
This series fixes failures to deregister and free fixed-link phydevs
that have been registered using the of_phy_register_fixed_link()
interface.
All but two drivers currently fail to do this and this series fixes most
of them with the exception of a staging driver and the stmmac drivers
which will be fixed by follow-on patches.
Included are also a couple of fixes for related of-node leaks.
Note that all patches except the of_mdio one have been compile-tested
only.
Also note that the series is against net due to dependencies not yet in
net-next.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/altera/altera_tse_main.c | 9 | ||||
-rw-r--r-- | drivers/net/ethernet/aurora/nb8800.c | 9 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bcmsysport.c | 17 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/genet/bcmmii.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/ucc_geth.c | 23 | ||||
-rw-r--r-- | drivers/net/ethernet/marvell/mvneta.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/renesas/ravb_main.c | 17 | ||||
-rw-r--r-- | drivers/net/ethernet/synopsys/dwc_eth_qos.c | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/cpsw.c | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/davinci_emac.c | 10 | ||||
-rw-r--r-- | drivers/of/of_mdio.c | 15 | ||||
-rw-r--r-- | include/linux/of_mdio.h | 4 | ||||
-rw-r--r-- | net/dsa/dsa.c | 12 | ||||
-rw-r--r-- | net/dsa/slave.c | 19 |
18 files changed, 152 insertions, 54 deletions
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index bda31f308cc2..6532829b70d2 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c | |||
@@ -819,6 +819,8 @@ static int init_phy(struct net_device *dev) | |||
819 | 819 | ||
820 | if (!phydev) { | 820 | if (!phydev) { |
821 | netdev_err(dev, "Could not find the PHY\n"); | 821 | netdev_err(dev, "Could not find the PHY\n"); |
822 | if (fixed_link) | ||
823 | of_phy_deregister_fixed_link(priv->device->of_node); | ||
822 | return -ENODEV; | 824 | return -ENODEV; |
823 | } | 825 | } |
824 | 826 | ||
@@ -1545,10 +1547,15 @@ err_free_netdev: | |||
1545 | static int altera_tse_remove(struct platform_device *pdev) | 1547 | static int altera_tse_remove(struct platform_device *pdev) |
1546 | { | 1548 | { |
1547 | struct net_device *ndev = platform_get_drvdata(pdev); | 1549 | struct net_device *ndev = platform_get_drvdata(pdev); |
1550 | struct altera_tse_private *priv = netdev_priv(ndev); | ||
1548 | 1551 | ||
1549 | if (ndev->phydev) | 1552 | if (ndev->phydev) { |
1550 | phy_disconnect(ndev->phydev); | 1553 | phy_disconnect(ndev->phydev); |
1551 | 1554 | ||
1555 | if (of_phy_is_fixed_link(priv->device->of_node)) | ||
1556 | of_phy_deregister_fixed_link(priv->device->of_node); | ||
1557 | } | ||
1558 | |||
1552 | platform_set_drvdata(pdev, NULL); | 1559 | platform_set_drvdata(pdev, NULL); |
1553 | altera_tse_mdio_destroy(ndev); | 1560 | altera_tse_mdio_destroy(ndev); |
1554 | unregister_netdev(ndev); | 1561 | unregister_netdev(ndev); |
diff --git a/drivers/net/ethernet/aurora/nb8800.c b/drivers/net/ethernet/aurora/nb8800.c index 00c38bf151e6..e078d8da978c 100644 --- a/drivers/net/ethernet/aurora/nb8800.c +++ b/drivers/net/ethernet/aurora/nb8800.c | |||
@@ -1466,12 +1466,12 @@ static int nb8800_probe(struct platform_device *pdev) | |||
1466 | 1466 | ||
1467 | ret = nb8800_hw_init(dev); | 1467 | ret = nb8800_hw_init(dev); |
1468 | if (ret) | 1468 | if (ret) |
1469 | goto err_free_bus; | 1469 | goto err_deregister_fixed_link; |
1470 | 1470 | ||
1471 | if (ops && ops->init) { | 1471 | if (ops && ops->init) { |
1472 | ret = ops->init(dev); | 1472 | ret = ops->init(dev); |
1473 | if (ret) | 1473 | if (ret) |
1474 | goto err_free_bus; | 1474 | goto err_deregister_fixed_link; |
1475 | } | 1475 | } |
1476 | 1476 | ||
1477 | dev->netdev_ops = &nb8800_netdev_ops; | 1477 | dev->netdev_ops = &nb8800_netdev_ops; |
@@ -1504,6 +1504,9 @@ static int nb8800_probe(struct platform_device *pdev) | |||
1504 | 1504 | ||
1505 | err_free_dma: | 1505 | err_free_dma: |
1506 | nb8800_dma_free(dev); | 1506 | nb8800_dma_free(dev); |
1507 | err_deregister_fixed_link: | ||
1508 | if (of_phy_is_fixed_link(pdev->dev.of_node)) | ||
1509 | of_phy_deregister_fixed_link(pdev->dev.of_node); | ||
1507 | err_free_bus: | 1510 | err_free_bus: |
1508 | of_node_put(priv->phy_node); | 1511 | of_node_put(priv->phy_node); |
1509 | mdiobus_unregister(bus); | 1512 | mdiobus_unregister(bus); |
@@ -1521,6 +1524,8 @@ static int nb8800_remove(struct platform_device *pdev) | |||
1521 | struct nb8800_priv *priv = netdev_priv(ndev); | 1524 | struct nb8800_priv *priv = netdev_priv(ndev); |
1522 | 1525 | ||
1523 | unregister_netdev(ndev); | 1526 | unregister_netdev(ndev); |
1527 | if (of_phy_is_fixed_link(pdev->dev.of_node)) | ||
1528 | of_phy_deregister_fixed_link(pdev->dev.of_node); | ||
1524 | of_node_put(priv->phy_node); | 1529 | of_node_put(priv->phy_node); |
1525 | 1530 | ||
1526 | mdiobus_unregister(priv->mii_bus); | 1531 | mdiobus_unregister(priv->mii_bus); |
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index c3354b9941d1..25d1eb4933d0 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c | |||
@@ -1755,13 +1755,13 @@ static int bcm_sysport_probe(struct platform_device *pdev) | |||
1755 | if (priv->irq0 <= 0 || priv->irq1 <= 0) { | 1755 | if (priv->irq0 <= 0 || priv->irq1 <= 0) { |
1756 | dev_err(&pdev->dev, "invalid interrupts\n"); | 1756 | dev_err(&pdev->dev, "invalid interrupts\n"); |
1757 | ret = -EINVAL; | 1757 | ret = -EINVAL; |
1758 | goto err; | 1758 | goto err_free_netdev; |
1759 | } | 1759 | } |
1760 | 1760 | ||
1761 | priv->base = devm_ioremap_resource(&pdev->dev, r); | 1761 | priv->base = devm_ioremap_resource(&pdev->dev, r); |
1762 | if (IS_ERR(priv->base)) { | 1762 | if (IS_ERR(priv->base)) { |
1763 | ret = PTR_ERR(priv->base); | 1763 | ret = PTR_ERR(priv->base); |
1764 | goto err; | 1764 | goto err_free_netdev; |
1765 | } | 1765 | } |
1766 | 1766 | ||
1767 | priv->netdev = dev; | 1767 | priv->netdev = dev; |
@@ -1779,7 +1779,7 @@ static int bcm_sysport_probe(struct platform_device *pdev) | |||
1779 | ret = of_phy_register_fixed_link(dn); | 1779 | ret = of_phy_register_fixed_link(dn); |
1780 | if (ret) { | 1780 | if (ret) { |
1781 | dev_err(&pdev->dev, "failed to register fixed PHY\n"); | 1781 | dev_err(&pdev->dev, "failed to register fixed PHY\n"); |
1782 | goto err; | 1782 | goto err_free_netdev; |
1783 | } | 1783 | } |
1784 | 1784 | ||
1785 | priv->phy_dn = dn; | 1785 | priv->phy_dn = dn; |
@@ -1821,7 +1821,7 @@ static int bcm_sysport_probe(struct platform_device *pdev) | |||
1821 | ret = register_netdev(dev); | 1821 | ret = register_netdev(dev); |
1822 | if (ret) { | 1822 | if (ret) { |
1823 | dev_err(&pdev->dev, "failed to register net_device\n"); | 1823 | dev_err(&pdev->dev, "failed to register net_device\n"); |
1824 | goto err; | 1824 | goto err_deregister_fixed_link; |
1825 | } | 1825 | } |
1826 | 1826 | ||
1827 | priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK; | 1827 | priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK; |
@@ -1832,7 +1832,11 @@ static int bcm_sysport_probe(struct platform_device *pdev) | |||
1832 | priv->base, priv->irq0, priv->irq1, txq, rxq); | 1832 | priv->base, priv->irq0, priv->irq1, txq, rxq); |
1833 | 1833 | ||
1834 | return 0; | 1834 | return 0; |
1835 | err: | 1835 | |
1836 | err_deregister_fixed_link: | ||
1837 | if (of_phy_is_fixed_link(dn)) | ||
1838 | of_phy_deregister_fixed_link(dn); | ||
1839 | err_free_netdev: | ||
1836 | free_netdev(dev); | 1840 | free_netdev(dev); |
1837 | return ret; | 1841 | return ret; |
1838 | } | 1842 | } |
@@ -1840,11 +1844,14 @@ err: | |||
1840 | static int bcm_sysport_remove(struct platform_device *pdev) | 1844 | static int bcm_sysport_remove(struct platform_device *pdev) |
1841 | { | 1845 | { |
1842 | struct net_device *dev = dev_get_drvdata(&pdev->dev); | 1846 | struct net_device *dev = dev_get_drvdata(&pdev->dev); |
1847 | struct device_node *dn = pdev->dev.of_node; | ||
1843 | 1848 | ||
1844 | /* Not much to do, ndo_close has been called | 1849 | /* Not much to do, ndo_close has been called |
1845 | * and we use managed allocations | 1850 | * and we use managed allocations |
1846 | */ | 1851 | */ |
1847 | unregister_netdev(dev); | 1852 | unregister_netdev(dev); |
1853 | if (of_phy_is_fixed_link(dn)) | ||
1854 | of_phy_deregister_fixed_link(dn); | ||
1848 | free_netdev(dev); | 1855 | free_netdev(dev); |
1849 | dev_set_drvdata(&pdev->dev, NULL); | 1856 | dev_set_drvdata(&pdev->dev, NULL); |
1850 | 1857 | ||
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 2e745bd51df4..e87607621e62 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c | |||
@@ -627,6 +627,7 @@ static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv) | |||
627 | int bcmgenet_mii_init(struct net_device *dev) | 627 | int bcmgenet_mii_init(struct net_device *dev) |
628 | { | 628 | { |
629 | struct bcmgenet_priv *priv = netdev_priv(dev); | 629 | struct bcmgenet_priv *priv = netdev_priv(dev); |
630 | struct device_node *dn = priv->pdev->dev.of_node; | ||
630 | int ret; | 631 | int ret; |
631 | 632 | ||
632 | ret = bcmgenet_mii_alloc(priv); | 633 | ret = bcmgenet_mii_alloc(priv); |
@@ -640,6 +641,8 @@ int bcmgenet_mii_init(struct net_device *dev) | |||
640 | return 0; | 641 | return 0; |
641 | 642 | ||
642 | out: | 643 | out: |
644 | if (of_phy_is_fixed_link(dn)) | ||
645 | of_phy_deregister_fixed_link(dn); | ||
643 | of_node_put(priv->phy_dn); | 646 | of_node_put(priv->phy_dn); |
644 | mdiobus_unregister(priv->mii_bus); | 647 | mdiobus_unregister(priv->mii_bus); |
645 | mdiobus_free(priv->mii_bus); | 648 | mdiobus_free(priv->mii_bus); |
@@ -649,7 +652,10 @@ out: | |||
649 | void bcmgenet_mii_exit(struct net_device *dev) | 652 | void bcmgenet_mii_exit(struct net_device *dev) |
650 | { | 653 | { |
651 | struct bcmgenet_priv *priv = netdev_priv(dev); | 654 | struct bcmgenet_priv *priv = netdev_priv(dev); |
655 | struct device_node *dn = priv->pdev->dev.of_node; | ||
652 | 656 | ||
657 | if (of_phy_is_fixed_link(dn)) | ||
658 | of_phy_deregister_fixed_link(dn); | ||
653 | of_node_put(priv->phy_dn); | 659 | of_node_put(priv->phy_dn); |
654 | mdiobus_unregister(priv->mii_bus); | 660 | mdiobus_unregister(priv->mii_bus); |
655 | mdiobus_free(priv->mii_bus); | 661 | mdiobus_free(priv->mii_bus); |
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 5aa9d4ded214..74dcdf097348 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c | |||
@@ -3475,6 +3475,8 @@ failed_regulator: | |||
3475 | failed_clk_ipg: | 3475 | failed_clk_ipg: |
3476 | fec_enet_clk_enable(ndev, false); | 3476 | fec_enet_clk_enable(ndev, false); |
3477 | failed_clk: | 3477 | failed_clk: |
3478 | if (of_phy_is_fixed_link(np)) | ||
3479 | of_phy_deregister_fixed_link(np); | ||
3478 | failed_phy: | 3480 | failed_phy: |
3479 | of_node_put(phy_node); | 3481 | of_node_put(phy_node); |
3480 | failed_ioremap: | 3482 | failed_ioremap: |
@@ -3488,6 +3490,7 @@ fec_drv_remove(struct platform_device *pdev) | |||
3488 | { | 3490 | { |
3489 | struct net_device *ndev = platform_get_drvdata(pdev); | 3491 | struct net_device *ndev = platform_get_drvdata(pdev); |
3490 | struct fec_enet_private *fep = netdev_priv(ndev); | 3492 | struct fec_enet_private *fep = netdev_priv(ndev); |
3493 | struct device_node *np = pdev->dev.of_node; | ||
3491 | 3494 | ||
3492 | cancel_work_sync(&fep->tx_timeout_work); | 3495 | cancel_work_sync(&fep->tx_timeout_work); |
3493 | fec_ptp_stop(pdev); | 3496 | fec_ptp_stop(pdev); |
@@ -3495,6 +3498,8 @@ fec_drv_remove(struct platform_device *pdev) | |||
3495 | fec_enet_mii_remove(fep); | 3498 | fec_enet_mii_remove(fep); |
3496 | if (fep->reg_phy) | 3499 | if (fep->reg_phy) |
3497 | regulator_disable(fep->reg_phy); | 3500 | regulator_disable(fep->reg_phy); |
3501 | if (of_phy_is_fixed_link(np)) | ||
3502 | of_phy_deregister_fixed_link(np); | ||
3498 | of_node_put(fep->phy_node); | 3503 | of_node_put(fep->phy_node); |
3499 | free_netdev(ndev); | 3504 | free_netdev(ndev); |
3500 | 3505 | ||
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c index dc120c148d97..4b86260584a0 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c | |||
@@ -980,7 +980,7 @@ static int fs_enet_probe(struct platform_device *ofdev) | |||
980 | err = clk_prepare_enable(clk); | 980 | err = clk_prepare_enable(clk); |
981 | if (err) { | 981 | if (err) { |
982 | ret = err; | 982 | ret = err; |
983 | goto out_free_fpi; | 983 | goto out_deregister_fixed_link; |
984 | } | 984 | } |
985 | fpi->clk_per = clk; | 985 | fpi->clk_per = clk; |
986 | } | 986 | } |
@@ -1061,6 +1061,9 @@ out_put: | |||
1061 | of_node_put(fpi->phy_node); | 1061 | of_node_put(fpi->phy_node); |
1062 | if (fpi->clk_per) | 1062 | if (fpi->clk_per) |
1063 | clk_disable_unprepare(fpi->clk_per); | 1063 | clk_disable_unprepare(fpi->clk_per); |
1064 | out_deregister_fixed_link: | ||
1065 | if (of_phy_is_fixed_link(ofdev->dev.of_node)) | ||
1066 | of_phy_deregister_fixed_link(ofdev->dev.of_node); | ||
1064 | out_free_fpi: | 1067 | out_free_fpi: |
1065 | kfree(fpi); | 1068 | kfree(fpi); |
1066 | return ret; | 1069 | return ret; |
@@ -1079,6 +1082,8 @@ static int fs_enet_remove(struct platform_device *ofdev) | |||
1079 | of_node_put(fep->fpi->phy_node); | 1082 | of_node_put(fep->fpi->phy_node); |
1080 | if (fep->fpi->clk_per) | 1083 | if (fep->fpi->clk_per) |
1081 | clk_disable_unprepare(fep->fpi->clk_per); | 1084 | clk_disable_unprepare(fep->fpi->clk_per); |
1085 | if (of_phy_is_fixed_link(ofdev->dev.of_node)) | ||
1086 | of_phy_deregister_fixed_link(ofdev->dev.of_node); | ||
1082 | free_netdev(ndev); | 1087 | free_netdev(ndev); |
1083 | return 0; | 1088 | return 0; |
1084 | } | 1089 | } |
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 4b4f5bc0e279..9061c2f82b9c 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c | |||
@@ -1312,6 +1312,7 @@ static void gfar_init_addr_hash_table(struct gfar_private *priv) | |||
1312 | */ | 1312 | */ |
1313 | static int gfar_probe(struct platform_device *ofdev) | 1313 | static int gfar_probe(struct platform_device *ofdev) |
1314 | { | 1314 | { |
1315 | struct device_node *np = ofdev->dev.of_node; | ||
1315 | struct net_device *dev = NULL; | 1316 | struct net_device *dev = NULL; |
1316 | struct gfar_private *priv = NULL; | 1317 | struct gfar_private *priv = NULL; |
1317 | int err = 0, i; | 1318 | int err = 0, i; |
@@ -1462,6 +1463,8 @@ static int gfar_probe(struct platform_device *ofdev) | |||
1462 | return 0; | 1463 | return 0; |
1463 | 1464 | ||
1464 | register_fail: | 1465 | register_fail: |
1466 | if (of_phy_is_fixed_link(np)) | ||
1467 | of_phy_deregister_fixed_link(np); | ||
1465 | unmap_group_regs(priv); | 1468 | unmap_group_regs(priv); |
1466 | gfar_free_rx_queues(priv); | 1469 | gfar_free_rx_queues(priv); |
1467 | gfar_free_tx_queues(priv); | 1470 | gfar_free_tx_queues(priv); |
@@ -1474,11 +1477,16 @@ register_fail: | |||
1474 | static int gfar_remove(struct platform_device *ofdev) | 1477 | static int gfar_remove(struct platform_device *ofdev) |
1475 | { | 1478 | { |
1476 | struct gfar_private *priv = platform_get_drvdata(ofdev); | 1479 | struct gfar_private *priv = platform_get_drvdata(ofdev); |
1480 | struct device_node *np = ofdev->dev.of_node; | ||
1477 | 1481 | ||
1478 | of_node_put(priv->phy_node); | 1482 | of_node_put(priv->phy_node); |
1479 | of_node_put(priv->tbi_node); | 1483 | of_node_put(priv->tbi_node); |
1480 | 1484 | ||
1481 | unregister_netdev(priv->ndev); | 1485 | unregister_netdev(priv->ndev); |
1486 | |||
1487 | if (of_phy_is_fixed_link(np)) | ||
1488 | of_phy_deregister_fixed_link(np); | ||
1489 | |||
1482 | unmap_group_regs(priv); | 1490 | unmap_group_regs(priv); |
1483 | gfar_free_rx_queues(priv); | 1491 | gfar_free_rx_queues(priv); |
1484 | gfar_free_tx_queues(priv); | 1492 | gfar_free_tx_queues(priv); |
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index 186ef8f16c80..f76d33279454 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c | |||
@@ -3868,9 +3868,8 @@ static int ucc_geth_probe(struct platform_device* ofdev) | |||
3868 | dev = alloc_etherdev(sizeof(*ugeth)); | 3868 | dev = alloc_etherdev(sizeof(*ugeth)); |
3869 | 3869 | ||
3870 | if (dev == NULL) { | 3870 | if (dev == NULL) { |
3871 | of_node_put(ug_info->tbi_node); | 3871 | err = -ENOMEM; |
3872 | of_node_put(ug_info->phy_node); | 3872 | goto err_deregister_fixed_link; |
3873 | return -ENOMEM; | ||
3874 | } | 3873 | } |
3875 | 3874 | ||
3876 | ugeth = netdev_priv(dev); | 3875 | ugeth = netdev_priv(dev); |
@@ -3907,10 +3906,7 @@ static int ucc_geth_probe(struct platform_device* ofdev) | |||
3907 | if (netif_msg_probe(ugeth)) | 3906 | if (netif_msg_probe(ugeth)) |
3908 | pr_err("%s: Cannot register net device, aborting\n", | 3907 | pr_err("%s: Cannot register net device, aborting\n", |
3909 | dev->name); | 3908 | dev->name); |
3910 | free_netdev(dev); | 3909 | goto err_free_netdev; |
3911 | of_node_put(ug_info->tbi_node); | ||
3912 | of_node_put(ug_info->phy_node); | ||
3913 | return err; | ||
3914 | } | 3910 | } |
3915 | 3911 | ||
3916 | mac_addr = of_get_mac_address(np); | 3912 | mac_addr = of_get_mac_address(np); |
@@ -3923,16 +3919,29 @@ static int ucc_geth_probe(struct platform_device* ofdev) | |||
3923 | ugeth->node = np; | 3919 | ugeth->node = np; |
3924 | 3920 | ||
3925 | return 0; | 3921 | return 0; |
3922 | |||
3923 | err_free_netdev: | ||
3924 | free_netdev(dev); | ||
3925 | err_deregister_fixed_link: | ||
3926 | if (of_phy_is_fixed_link(np)) | ||
3927 | of_phy_deregister_fixed_link(np); | ||
3928 | of_node_put(ug_info->tbi_node); | ||
3929 | of_node_put(ug_info->phy_node); | ||
3930 | |||
3931 | return err; | ||
3926 | } | 3932 | } |
3927 | 3933 | ||
3928 | static int ucc_geth_remove(struct platform_device* ofdev) | 3934 | static int ucc_geth_remove(struct platform_device* ofdev) |
3929 | { | 3935 | { |
3930 | struct net_device *dev = platform_get_drvdata(ofdev); | 3936 | struct net_device *dev = platform_get_drvdata(ofdev); |
3931 | struct ucc_geth_private *ugeth = netdev_priv(dev); | 3937 | struct ucc_geth_private *ugeth = netdev_priv(dev); |
3938 | struct device_node *np = ofdev->dev.of_node; | ||
3932 | 3939 | ||
3933 | unregister_netdev(dev); | 3940 | unregister_netdev(dev); |
3934 | free_netdev(dev); | 3941 | free_netdev(dev); |
3935 | ucc_geth_memclean(ugeth); | 3942 | ucc_geth_memclean(ugeth); |
3943 | if (of_phy_is_fixed_link(np)) | ||
3944 | of_phy_deregister_fixed_link(np); | ||
3936 | of_node_put(ugeth->ug_info->tbi_node); | 3945 | of_node_put(ugeth->ug_info->tbi_node); |
3937 | of_node_put(ugeth->ug_info->phy_node); | 3946 | of_node_put(ugeth->ug_info->phy_node); |
3938 | 3947 | ||
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 0c0a45af950f..707bc4680b9b 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c | |||
@@ -4191,6 +4191,8 @@ err_clk: | |||
4191 | clk_disable_unprepare(pp->clk); | 4191 | clk_disable_unprepare(pp->clk); |
4192 | err_put_phy_node: | 4192 | err_put_phy_node: |
4193 | of_node_put(phy_node); | 4193 | of_node_put(phy_node); |
4194 | if (of_phy_is_fixed_link(dn)) | ||
4195 | of_phy_deregister_fixed_link(dn); | ||
4194 | err_free_irq: | 4196 | err_free_irq: |
4195 | irq_dispose_mapping(dev->irq); | 4197 | irq_dispose_mapping(dev->irq); |
4196 | err_free_netdev: | 4198 | err_free_netdev: |
@@ -4202,6 +4204,7 @@ err_free_netdev: | |||
4202 | static int mvneta_remove(struct platform_device *pdev) | 4204 | static int mvneta_remove(struct platform_device *pdev) |
4203 | { | 4205 | { |
4204 | struct net_device *dev = platform_get_drvdata(pdev); | 4206 | struct net_device *dev = platform_get_drvdata(pdev); |
4207 | struct device_node *dn = pdev->dev.of_node; | ||
4205 | struct mvneta_port *pp = netdev_priv(dev); | 4208 | struct mvneta_port *pp = netdev_priv(dev); |
4206 | 4209 | ||
4207 | unregister_netdev(dev); | 4210 | unregister_netdev(dev); |
@@ -4209,6 +4212,8 @@ static int mvneta_remove(struct platform_device *pdev) | |||
4209 | clk_disable_unprepare(pp->clk); | 4212 | clk_disable_unprepare(pp->clk); |
4210 | free_percpu(pp->ports); | 4213 | free_percpu(pp->ports); |
4211 | free_percpu(pp->stats); | 4214 | free_percpu(pp->stats); |
4215 | if (of_phy_is_fixed_link(dn)) | ||
4216 | of_phy_deregister_fixed_link(dn); | ||
4212 | irq_dispose_mapping(dev->irq); | 4217 | irq_dispose_mapping(dev->irq); |
4213 | of_node_put(pp->phy_node); | 4218 | of_node_put(pp->phy_node); |
4214 | free_netdev(dev); | 4219 | free_netdev(dev); |
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 4a62ffd7729d..86a89cbd3ec9 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c | |||
@@ -318,6 +318,8 @@ static int mtk_phy_connect(struct net_device *dev) | |||
318 | return 0; | 318 | return 0; |
319 | 319 | ||
320 | err_phy: | 320 | err_phy: |
321 | if (of_phy_is_fixed_link(mac->of_node)) | ||
322 | of_phy_deregister_fixed_link(mac->of_node); | ||
321 | of_node_put(np); | 323 | of_node_put(np); |
322 | dev_err(eth->dev, "%s: invalid phy\n", __func__); | 324 | dev_err(eth->dev, "%s: invalid phy\n", __func__); |
323 | return -EINVAL; | 325 | return -EINVAL; |
@@ -1923,6 +1925,8 @@ static void mtk_uninit(struct net_device *dev) | |||
1923 | struct mtk_eth *eth = mac->hw; | 1925 | struct mtk_eth *eth = mac->hw; |
1924 | 1926 | ||
1925 | phy_disconnect(dev->phydev); | 1927 | phy_disconnect(dev->phydev); |
1928 | if (of_phy_is_fixed_link(mac->of_node)) | ||
1929 | of_phy_deregister_fixed_link(mac->of_node); | ||
1926 | mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0); | 1930 | mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0); |
1927 | mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0); | 1931 | mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0); |
1928 | } | 1932 | } |
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 630536bc72f9..f1f3be2cfe21 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c | |||
@@ -1008,7 +1008,8 @@ static int ravb_phy_init(struct net_device *ndev) | |||
1008 | of_node_put(pn); | 1008 | of_node_put(pn); |
1009 | if (!phydev) { | 1009 | if (!phydev) { |
1010 | netdev_err(ndev, "failed to connect PHY\n"); | 1010 | netdev_err(ndev, "failed to connect PHY\n"); |
1011 | return -ENOENT; | 1011 | err = -ENOENT; |
1012 | goto err_deregister_fixed_link; | ||
1012 | } | 1013 | } |
1013 | 1014 | ||
1014 | /* This driver only support 10/100Mbit speeds on Gen3 | 1015 | /* This driver only support 10/100Mbit speeds on Gen3 |
@@ -1020,8 +1021,7 @@ static int ravb_phy_init(struct net_device *ndev) | |||
1020 | err = phy_set_max_speed(phydev, SPEED_100); | 1021 | err = phy_set_max_speed(phydev, SPEED_100); |
1021 | if (err) { | 1022 | if (err) { |
1022 | netdev_err(ndev, "failed to limit PHY to 100Mbit/s\n"); | 1023 | netdev_err(ndev, "failed to limit PHY to 100Mbit/s\n"); |
1023 | phy_disconnect(phydev); | 1024 | goto err_phy_disconnect; |
1024 | return err; | ||
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | netdev_info(ndev, "limited PHY to 100Mbit/s\n"); | 1027 | netdev_info(ndev, "limited PHY to 100Mbit/s\n"); |
@@ -1033,6 +1033,14 @@ static int ravb_phy_init(struct net_device *ndev) | |||
1033 | phy_attached_info(phydev); | 1033 | phy_attached_info(phydev); |
1034 | 1034 | ||
1035 | return 0; | 1035 | return 0; |
1036 | |||
1037 | err_phy_disconnect: | ||
1038 | phy_disconnect(phydev); | ||
1039 | err_deregister_fixed_link: | ||
1040 | if (of_phy_is_fixed_link(np)) | ||
1041 | of_phy_deregister_fixed_link(np); | ||
1042 | |||
1043 | return err; | ||
1036 | } | 1044 | } |
1037 | 1045 | ||
1038 | /* PHY control start function */ | 1046 | /* PHY control start function */ |
@@ -1634,6 +1642,7 @@ static void ravb_set_rx_mode(struct net_device *ndev) | |||
1634 | /* Device close function for Ethernet AVB */ | 1642 | /* Device close function for Ethernet AVB */ |
1635 | static int ravb_close(struct net_device *ndev) | 1643 | static int ravb_close(struct net_device *ndev) |
1636 | { | 1644 | { |
1645 | struct device_node *np = ndev->dev.parent->of_node; | ||
1637 | struct ravb_private *priv = netdev_priv(ndev); | 1646 | struct ravb_private *priv = netdev_priv(ndev); |
1638 | struct ravb_tstamp_skb *ts_skb, *ts_skb2; | 1647 | struct ravb_tstamp_skb *ts_skb, *ts_skb2; |
1639 | 1648 | ||
@@ -1663,6 +1672,8 @@ static int ravb_close(struct net_device *ndev) | |||
1663 | if (ndev->phydev) { | 1672 | if (ndev->phydev) { |
1664 | phy_stop(ndev->phydev); | 1673 | phy_stop(ndev->phydev); |
1665 | phy_disconnect(ndev->phydev); | 1674 | phy_disconnect(ndev->phydev); |
1675 | if (of_phy_is_fixed_link(np)) | ||
1676 | of_phy_deregister_fixed_link(np); | ||
1666 | } | 1677 | } |
1667 | 1678 | ||
1668 | if (priv->chip_id != RCAR_GEN2) { | 1679 | if (priv->chip_id != RCAR_GEN2) { |
diff --git a/drivers/net/ethernet/synopsys/dwc_eth_qos.c b/drivers/net/ethernet/synopsys/dwc_eth_qos.c index 4ba2421e625d..97d64bfed465 100644 --- a/drivers/net/ethernet/synopsys/dwc_eth_qos.c +++ b/drivers/net/ethernet/synopsys/dwc_eth_qos.c | |||
@@ -2881,7 +2881,7 @@ static int dwceqos_probe(struct platform_device *pdev) | |||
2881 | ret = of_get_phy_mode(lp->pdev->dev.of_node); | 2881 | ret = of_get_phy_mode(lp->pdev->dev.of_node); |
2882 | if (ret < 0) { | 2882 | if (ret < 0) { |
2883 | dev_err(&lp->pdev->dev, "error in getting phy i/f\n"); | 2883 | dev_err(&lp->pdev->dev, "error in getting phy i/f\n"); |
2884 | goto err_out_clk_dis_phy; | 2884 | goto err_out_deregister_fixed_link; |
2885 | } | 2885 | } |
2886 | 2886 | ||
2887 | lp->phy_interface = ret; | 2887 | lp->phy_interface = ret; |
@@ -2889,14 +2889,14 @@ static int dwceqos_probe(struct platform_device *pdev) | |||
2889 | ret = dwceqos_mii_init(lp); | 2889 | ret = dwceqos_mii_init(lp); |
2890 | if (ret) { | 2890 | if (ret) { |
2891 | dev_err(&lp->pdev->dev, "error in dwceqos_mii_init\n"); | 2891 | dev_err(&lp->pdev->dev, "error in dwceqos_mii_init\n"); |
2892 | goto err_out_clk_dis_phy; | 2892 | goto err_out_deregister_fixed_link; |
2893 | } | 2893 | } |
2894 | 2894 | ||
2895 | ret = dwceqos_mii_probe(ndev); | 2895 | ret = dwceqos_mii_probe(ndev); |
2896 | if (ret != 0) { | 2896 | if (ret != 0) { |
2897 | netdev_err(ndev, "mii_probe fail.\n"); | 2897 | netdev_err(ndev, "mii_probe fail.\n"); |
2898 | ret = -ENXIO; | 2898 | ret = -ENXIO; |
2899 | goto err_out_clk_dis_phy; | 2899 | goto err_out_deregister_fixed_link; |
2900 | } | 2900 | } |
2901 | 2901 | ||
2902 | dwceqos_set_umac_addr(lp, lp->ndev->dev_addr, 0); | 2902 | dwceqos_set_umac_addr(lp, lp->ndev->dev_addr, 0); |
@@ -2914,7 +2914,7 @@ static int dwceqos_probe(struct platform_device *pdev) | |||
2914 | if (ret) { | 2914 | if (ret) { |
2915 | dev_err(&lp->pdev->dev, "Unable to retrieve DT, error %d\n", | 2915 | dev_err(&lp->pdev->dev, "Unable to retrieve DT, error %d\n", |
2916 | ret); | 2916 | ret); |
2917 | goto err_out_clk_dis_phy; | 2917 | goto err_out_deregister_fixed_link; |
2918 | } | 2918 | } |
2919 | dev_info(&lp->pdev->dev, "pdev->id %d, baseaddr 0x%08lx, irq %d\n", | 2919 | dev_info(&lp->pdev->dev, "pdev->id %d, baseaddr 0x%08lx, irq %d\n", |
2920 | pdev->id, ndev->base_addr, ndev->irq); | 2920 | pdev->id, ndev->base_addr, ndev->irq); |
@@ -2924,7 +2924,7 @@ static int dwceqos_probe(struct platform_device *pdev) | |||
2924 | if (ret) { | 2924 | if (ret) { |
2925 | dev_err(&lp->pdev->dev, "Unable to request IRQ %d, error %d\n", | 2925 | dev_err(&lp->pdev->dev, "Unable to request IRQ %d, error %d\n", |
2926 | ndev->irq, ret); | 2926 | ndev->irq, ret); |
2927 | goto err_out_clk_dis_phy; | 2927 | goto err_out_deregister_fixed_link; |
2928 | } | 2928 | } |
2929 | 2929 | ||
2930 | if (netif_msg_probe(lp)) | 2930 | if (netif_msg_probe(lp)) |
@@ -2935,11 +2935,14 @@ static int dwceqos_probe(struct platform_device *pdev) | |||
2935 | ret = register_netdev(ndev); | 2935 | ret = register_netdev(ndev); |
2936 | if (ret) { | 2936 | if (ret) { |
2937 | dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); | 2937 | dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); |
2938 | goto err_out_clk_dis_phy; | 2938 | goto err_out_deregister_fixed_link; |
2939 | } | 2939 | } |
2940 | 2940 | ||
2941 | return 0; | 2941 | return 0; |
2942 | 2942 | ||
2943 | err_out_deregister_fixed_link: | ||
2944 | if (of_phy_is_fixed_link(pdev->dev.of_node)) | ||
2945 | of_phy_deregister_fixed_link(pdev->dev.of_node); | ||
2943 | err_out_clk_dis_phy: | 2946 | err_out_clk_dis_phy: |
2944 | clk_disable_unprepare(lp->phy_ref_clk); | 2947 | clk_disable_unprepare(lp->phy_ref_clk); |
2945 | err_out_clk_dis_aper: | 2948 | err_out_clk_dis_aper: |
@@ -2959,8 +2962,11 @@ static int dwceqos_remove(struct platform_device *pdev) | |||
2959 | if (ndev) { | 2962 | if (ndev) { |
2960 | lp = netdev_priv(ndev); | 2963 | lp = netdev_priv(ndev); |
2961 | 2964 | ||
2962 | if (ndev->phydev) | 2965 | if (ndev->phydev) { |
2963 | phy_disconnect(ndev->phydev); | 2966 | phy_disconnect(ndev->phydev); |
2967 | if (of_phy_is_fixed_link(pdev->dev.of_node)) | ||
2968 | of_phy_deregister_fixed_link(pdev->dev.of_node); | ||
2969 | } | ||
2964 | mdiobus_unregister(lp->mii_bus); | 2970 | mdiobus_unregister(lp->mii_bus); |
2965 | mdiobus_free(lp->mii_bus); | 2971 | mdiobus_free(lp->mii_bus); |
2966 | 2972 | ||
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 58947aae31c7..9f0646512624 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c | |||
@@ -2459,20 +2459,8 @@ static void cpsw_remove_dt(struct platform_device *pdev) | |||
2459 | if (strcmp(slave_node->name, "slave")) | 2459 | if (strcmp(slave_node->name, "slave")) |
2460 | continue; | 2460 | continue; |
2461 | 2461 | ||
2462 | if (of_phy_is_fixed_link(slave_node)) { | 2462 | if (of_phy_is_fixed_link(slave_node)) |
2463 | struct phy_device *phydev; | 2463 | of_phy_deregister_fixed_link(slave_node); |
2464 | |||
2465 | phydev = of_phy_find_device(slave_node); | ||
2466 | if (phydev) { | ||
2467 | fixed_phy_unregister(phydev); | ||
2468 | /* Put references taken by | ||
2469 | * of_phy_find_device() and | ||
2470 | * of_phy_register_fixed_link(). | ||
2471 | */ | ||
2472 | phy_device_free(phydev); | ||
2473 | phy_device_free(phydev); | ||
2474 | } | ||
2475 | } | ||
2476 | 2464 | ||
2477 | of_node_put(slave_data->phy_node); | 2465 | of_node_put(slave_data->phy_node); |
2478 | 2466 | ||
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 84fbe5714f8b..481c7bf0395b 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c | |||
@@ -1767,6 +1767,7 @@ static int davinci_emac_try_get_mac(struct platform_device *pdev, | |||
1767 | */ | 1767 | */ |
1768 | static int davinci_emac_probe(struct platform_device *pdev) | 1768 | static int davinci_emac_probe(struct platform_device *pdev) |
1769 | { | 1769 | { |
1770 | struct device_node *np = pdev->dev.of_node; | ||
1770 | int rc = 0; | 1771 | int rc = 0; |
1771 | struct resource *res, *res_ctrl; | 1772 | struct resource *res, *res_ctrl; |
1772 | struct net_device *ndev; | 1773 | struct net_device *ndev; |
@@ -1805,7 +1806,7 @@ static int davinci_emac_probe(struct platform_device *pdev) | |||
1805 | if (!pdata) { | 1806 | if (!pdata) { |
1806 | dev_err(&pdev->dev, "no platform data\n"); | 1807 | dev_err(&pdev->dev, "no platform data\n"); |
1807 | rc = -ENODEV; | 1808 | rc = -ENODEV; |
1808 | goto no_pdata; | 1809 | goto err_free_netdev; |
1809 | } | 1810 | } |
1810 | 1811 | ||
1811 | /* MAC addr and PHY mask , RMII enable info from platform_data */ | 1812 | /* MAC addr and PHY mask , RMII enable info from platform_data */ |
@@ -1941,6 +1942,10 @@ no_cpdma_chan: | |||
1941 | cpdma_chan_destroy(priv->rxchan); | 1942 | cpdma_chan_destroy(priv->rxchan); |
1942 | cpdma_ctlr_destroy(priv->dma); | 1943 | cpdma_ctlr_destroy(priv->dma); |
1943 | no_pdata: | 1944 | no_pdata: |
1945 | if (of_phy_is_fixed_link(np)) | ||
1946 | of_phy_deregister_fixed_link(np); | ||
1947 | of_node_put(priv->phy_node); | ||
1948 | err_free_netdev: | ||
1944 | free_netdev(ndev); | 1949 | free_netdev(ndev); |
1945 | return rc; | 1950 | return rc; |
1946 | } | 1951 | } |
@@ -1956,6 +1961,7 @@ static int davinci_emac_remove(struct platform_device *pdev) | |||
1956 | { | 1961 | { |
1957 | struct net_device *ndev = platform_get_drvdata(pdev); | 1962 | struct net_device *ndev = platform_get_drvdata(pdev); |
1958 | struct emac_priv *priv = netdev_priv(ndev); | 1963 | struct emac_priv *priv = netdev_priv(ndev); |
1964 | struct device_node *np = pdev->dev.of_node; | ||
1959 | 1965 | ||
1960 | dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n"); | 1966 | dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n"); |
1961 | 1967 | ||
@@ -1968,6 +1974,8 @@ static int davinci_emac_remove(struct platform_device *pdev) | |||
1968 | unregister_netdev(ndev); | 1974 | unregister_netdev(ndev); |
1969 | of_node_put(priv->phy_node); | 1975 | of_node_put(priv->phy_node); |
1970 | pm_runtime_disable(&pdev->dev); | 1976 | pm_runtime_disable(&pdev->dev); |
1977 | if (of_phy_is_fixed_link(np)) | ||
1978 | of_phy_deregister_fixed_link(np); | ||
1971 | free_netdev(ndev); | 1979 | free_netdev(ndev); |
1972 | 1980 | ||
1973 | return 0; | 1981 | return 0; |
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 5a3145a02547..262281bd68fa 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c | |||
@@ -490,3 +490,18 @@ int of_phy_register_fixed_link(struct device_node *np) | |||
490 | return -ENODEV; | 490 | return -ENODEV; |
491 | } | 491 | } |
492 | EXPORT_SYMBOL(of_phy_register_fixed_link); | 492 | EXPORT_SYMBOL(of_phy_register_fixed_link); |
493 | |||
494 | void of_phy_deregister_fixed_link(struct device_node *np) | ||
495 | { | ||
496 | struct phy_device *phydev; | ||
497 | |||
498 | phydev = of_phy_find_device(np); | ||
499 | if (!phydev) | ||
500 | return; | ||
501 | |||
502 | fixed_phy_unregister(phydev); | ||
503 | |||
504 | put_device(&phydev->mdio.dev); /* of_phy_find_device() */ | ||
505 | phy_device_free(phydev); /* fixed_phy_register() */ | ||
506 | } | ||
507 | EXPORT_SYMBOL(of_phy_deregister_fixed_link); | ||
diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h index 2ab233661ae5..a58cca8bcb29 100644 --- a/include/linux/of_mdio.h +++ b/include/linux/of_mdio.h | |||
@@ -29,6 +29,7 @@ struct phy_device *of_phy_attach(struct net_device *dev, | |||
29 | extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np); | 29 | extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np); |
30 | extern int of_mdio_parse_addr(struct device *dev, const struct device_node *np); | 30 | extern int of_mdio_parse_addr(struct device *dev, const struct device_node *np); |
31 | extern int of_phy_register_fixed_link(struct device_node *np); | 31 | extern int of_phy_register_fixed_link(struct device_node *np); |
32 | extern void of_phy_deregister_fixed_link(struct device_node *np); | ||
32 | extern bool of_phy_is_fixed_link(struct device_node *np); | 33 | extern bool of_phy_is_fixed_link(struct device_node *np); |
33 | 34 | ||
34 | #else /* CONFIG_OF */ | 35 | #else /* CONFIG_OF */ |
@@ -83,6 +84,9 @@ static inline int of_phy_register_fixed_link(struct device_node *np) | |||
83 | { | 84 | { |
84 | return -ENOSYS; | 85 | return -ENOSYS; |
85 | } | 86 | } |
87 | static inline void of_phy_deregister_fixed_link(struct device_node *np) | ||
88 | { | ||
89 | } | ||
86 | static inline bool of_phy_is_fixed_link(struct device_node *np) | 90 | static inline bool of_phy_is_fixed_link(struct device_node *np) |
87 | { | 91 | { |
88 | return false; | 92 | return false; |
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index cb0091b99592..7899919cd9f0 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c | |||
@@ -506,16 +506,8 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, | |||
506 | 506 | ||
507 | void dsa_cpu_dsa_destroy(struct device_node *port_dn) | 507 | void dsa_cpu_dsa_destroy(struct device_node *port_dn) |
508 | { | 508 | { |
509 | struct phy_device *phydev; | 509 | if (of_phy_is_fixed_link(port_dn)) |
510 | 510 | of_phy_deregister_fixed_link(port_dn); | |
511 | if (of_phy_is_fixed_link(port_dn)) { | ||
512 | phydev = of_phy_find_device(port_dn); | ||
513 | if (phydev) { | ||
514 | fixed_phy_unregister(phydev); | ||
515 | put_device(&phydev->mdio.dev); | ||
516 | phy_device_free(phydev); | ||
517 | } | ||
518 | } | ||
519 | } | 511 | } |
520 | 512 | ||
521 | static void dsa_switch_destroy(struct dsa_switch *ds) | 513 | static void dsa_switch_destroy(struct dsa_switch *ds) |
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 6b1282c006b1..30e2e21d7619 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
@@ -1125,7 +1125,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, | |||
1125 | p->phy_interface = mode; | 1125 | p->phy_interface = mode; |
1126 | 1126 | ||
1127 | phy_dn = of_parse_phandle(port_dn, "phy-handle", 0); | 1127 | phy_dn = of_parse_phandle(port_dn, "phy-handle", 0); |
1128 | if (of_phy_is_fixed_link(port_dn)) { | 1128 | if (!phy_dn && of_phy_is_fixed_link(port_dn)) { |
1129 | /* In the case of a fixed PHY, the DT node associated | 1129 | /* In the case of a fixed PHY, the DT node associated |
1130 | * to the fixed PHY is the Port DT node | 1130 | * to the fixed PHY is the Port DT node |
1131 | */ | 1131 | */ |
@@ -1135,7 +1135,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, | |||
1135 | return ret; | 1135 | return ret; |
1136 | } | 1136 | } |
1137 | phy_is_fixed = true; | 1137 | phy_is_fixed = true; |
1138 | phy_dn = port_dn; | 1138 | phy_dn = of_node_get(port_dn); |
1139 | } | 1139 | } |
1140 | 1140 | ||
1141 | if (ds->ops->get_phy_flags) | 1141 | if (ds->ops->get_phy_flags) |
@@ -1154,6 +1154,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, | |||
1154 | ret = dsa_slave_phy_connect(p, slave_dev, phy_id); | 1154 | ret = dsa_slave_phy_connect(p, slave_dev, phy_id); |
1155 | if (ret) { | 1155 | if (ret) { |
1156 | netdev_err(slave_dev, "failed to connect to phy%d: %d\n", phy_id, ret); | 1156 | netdev_err(slave_dev, "failed to connect to phy%d: %d\n", phy_id, ret); |
1157 | of_node_put(phy_dn); | ||
1157 | return ret; | 1158 | return ret; |
1158 | } | 1159 | } |
1159 | } else { | 1160 | } else { |
@@ -1162,6 +1163,8 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, | |||
1162 | phy_flags, | 1163 | phy_flags, |
1163 | p->phy_interface); | 1164 | p->phy_interface); |
1164 | } | 1165 | } |
1166 | |||
1167 | of_node_put(phy_dn); | ||
1165 | } | 1168 | } |
1166 | 1169 | ||
1167 | if (p->phy && phy_is_fixed) | 1170 | if (p->phy && phy_is_fixed) |
@@ -1174,6 +1177,8 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, | |||
1174 | ret = dsa_slave_phy_connect(p, slave_dev, p->port); | 1177 | ret = dsa_slave_phy_connect(p, slave_dev, p->port); |
1175 | if (ret) { | 1178 | if (ret) { |
1176 | netdev_err(slave_dev, "failed to connect to port %d: %d\n", p->port, ret); | 1179 | netdev_err(slave_dev, "failed to connect to port %d: %d\n", p->port, ret); |
1180 | if (phy_is_fixed) | ||
1181 | of_phy_deregister_fixed_link(port_dn); | ||
1177 | return ret; | 1182 | return ret; |
1178 | } | 1183 | } |
1179 | } | 1184 | } |
@@ -1289,10 +1294,18 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent, | |||
1289 | void dsa_slave_destroy(struct net_device *slave_dev) | 1294 | void dsa_slave_destroy(struct net_device *slave_dev) |
1290 | { | 1295 | { |
1291 | struct dsa_slave_priv *p = netdev_priv(slave_dev); | 1296 | struct dsa_slave_priv *p = netdev_priv(slave_dev); |
1297 | struct dsa_switch *ds = p->parent; | ||
1298 | struct device_node *port_dn; | ||
1299 | |||
1300 | port_dn = ds->ports[p->port].dn; | ||
1292 | 1301 | ||
1293 | netif_carrier_off(slave_dev); | 1302 | netif_carrier_off(slave_dev); |
1294 | if (p->phy) | 1303 | if (p->phy) { |
1295 | phy_disconnect(p->phy); | 1304 | phy_disconnect(p->phy); |
1305 | |||
1306 | if (of_phy_is_fixed_link(port_dn)) | ||
1307 | of_phy_deregister_fixed_link(port_dn); | ||
1308 | } | ||
1296 | unregister_netdev(slave_dev); | 1309 | unregister_netdev(slave_dev); |
1297 | free_netdev(slave_dev); | 1310 | free_netdev(slave_dev); |
1298 | } | 1311 | } |