Commit f2ebf2a6 authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents a5108878 881eadab
...@@ -819,6 +819,8 @@ static int init_phy(struct net_device *dev) ...@@ -819,6 +819,8 @@ static int init_phy(struct net_device *dev)
if (!phydev) { if (!phydev) {
netdev_err(dev, "Could not find the PHY\n"); netdev_err(dev, "Could not find the PHY\n");
if (fixed_link)
of_phy_deregister_fixed_link(priv->device->of_node);
return -ENODEV; return -ENODEV;
} }
...@@ -1545,10 +1547,15 @@ static int altera_tse_probe(struct platform_device *pdev) ...@@ -1545,10 +1547,15 @@ static int altera_tse_probe(struct platform_device *pdev)
static int altera_tse_remove(struct platform_device *pdev) static int altera_tse_remove(struct platform_device *pdev)
{ {
struct net_device *ndev = platform_get_drvdata(pdev); struct net_device *ndev = platform_get_drvdata(pdev);
struct altera_tse_private *priv = netdev_priv(ndev);
if (ndev->phydev) if (ndev->phydev) {
phy_disconnect(ndev->phydev); phy_disconnect(ndev->phydev);
if (of_phy_is_fixed_link(priv->device->of_node))
of_phy_deregister_fixed_link(priv->device->of_node);
}
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
altera_tse_mdio_destroy(ndev); altera_tse_mdio_destroy(ndev);
unregister_netdev(ndev); unregister_netdev(ndev);
......
...@@ -1466,12 +1466,12 @@ static int nb8800_probe(struct platform_device *pdev) ...@@ -1466,12 +1466,12 @@ static int nb8800_probe(struct platform_device *pdev)
ret = nb8800_hw_init(dev); ret = nb8800_hw_init(dev);
if (ret) if (ret)
goto err_free_bus; goto err_deregister_fixed_link;
if (ops && ops->init) { if (ops && ops->init) {
ret = ops->init(dev); ret = ops->init(dev);
if (ret) if (ret)
goto err_free_bus; goto err_deregister_fixed_link;
} }
dev->netdev_ops = &nb8800_netdev_ops; dev->netdev_ops = &nb8800_netdev_ops;
...@@ -1504,6 +1504,9 @@ static int nb8800_probe(struct platform_device *pdev) ...@@ -1504,6 +1504,9 @@ static int nb8800_probe(struct platform_device *pdev)
err_free_dma: err_free_dma:
nb8800_dma_free(dev); nb8800_dma_free(dev);
err_deregister_fixed_link:
if (of_phy_is_fixed_link(pdev->dev.of_node))
of_phy_deregister_fixed_link(pdev->dev.of_node);
err_free_bus: err_free_bus:
of_node_put(priv->phy_node); of_node_put(priv->phy_node);
mdiobus_unregister(bus); mdiobus_unregister(bus);
...@@ -1521,6 +1524,8 @@ static int nb8800_remove(struct platform_device *pdev) ...@@ -1521,6 +1524,8 @@ static int nb8800_remove(struct platform_device *pdev)
struct nb8800_priv *priv = netdev_priv(ndev); struct nb8800_priv *priv = netdev_priv(ndev);
unregister_netdev(ndev); unregister_netdev(ndev);
if (of_phy_is_fixed_link(pdev->dev.of_node))
of_phy_deregister_fixed_link(pdev->dev.of_node);
of_node_put(priv->phy_node); of_node_put(priv->phy_node);
mdiobus_unregister(priv->mii_bus); mdiobus_unregister(priv->mii_bus);
......
...@@ -1755,13 +1755,13 @@ static int bcm_sysport_probe(struct platform_device *pdev) ...@@ -1755,13 +1755,13 @@ static int bcm_sysport_probe(struct platform_device *pdev)
if (priv->irq0 <= 0 || priv->irq1 <= 0) { if (priv->irq0 <= 0 || priv->irq1 <= 0) {
dev_err(&pdev->dev, "invalid interrupts\n"); dev_err(&pdev->dev, "invalid interrupts\n");
ret = -EINVAL; ret = -EINVAL;
goto err; goto err_free_netdev;
} }
priv->base = devm_ioremap_resource(&pdev->dev, r); priv->base = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(priv->base)) { if (IS_ERR(priv->base)) {
ret = PTR_ERR(priv->base); ret = PTR_ERR(priv->base);
goto err; goto err_free_netdev;
} }
priv->netdev = dev; priv->netdev = dev;
...@@ -1779,7 +1779,7 @@ static int bcm_sysport_probe(struct platform_device *pdev) ...@@ -1779,7 +1779,7 @@ static int bcm_sysport_probe(struct platform_device *pdev)
ret = of_phy_register_fixed_link(dn); ret = of_phy_register_fixed_link(dn);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register fixed PHY\n"); dev_err(&pdev->dev, "failed to register fixed PHY\n");
goto err; goto err_free_netdev;
} }
priv->phy_dn = dn; priv->phy_dn = dn;
...@@ -1821,7 +1821,7 @@ static int bcm_sysport_probe(struct platform_device *pdev) ...@@ -1821,7 +1821,7 @@ static int bcm_sysport_probe(struct platform_device *pdev)
ret = register_netdev(dev); ret = register_netdev(dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register net_device\n"); dev_err(&pdev->dev, "failed to register net_device\n");
goto err; goto err_deregister_fixed_link;
} }
priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK; priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK;
...@@ -1832,7 +1832,11 @@ static int bcm_sysport_probe(struct platform_device *pdev) ...@@ -1832,7 +1832,11 @@ static int bcm_sysport_probe(struct platform_device *pdev)
priv->base, priv->irq0, priv->irq1, txq, rxq); priv->base, priv->irq0, priv->irq1, txq, rxq);
return 0; return 0;
err:
err_deregister_fixed_link:
if (of_phy_is_fixed_link(dn))
of_phy_deregister_fixed_link(dn);
err_free_netdev:
free_netdev(dev); free_netdev(dev);
return ret; return ret;
} }
...@@ -1840,11 +1844,14 @@ static int bcm_sysport_probe(struct platform_device *pdev) ...@@ -1840,11 +1844,14 @@ static int bcm_sysport_probe(struct platform_device *pdev)
static int bcm_sysport_remove(struct platform_device *pdev) static int bcm_sysport_remove(struct platform_device *pdev)
{ {
struct net_device *dev = dev_get_drvdata(&pdev->dev); struct net_device *dev = dev_get_drvdata(&pdev->dev);
struct device_node *dn = pdev->dev.of_node;
/* Not much to do, ndo_close has been called /* Not much to do, ndo_close has been called
* and we use managed allocations * and we use managed allocations
*/ */
unregister_netdev(dev); unregister_netdev(dev);
if (of_phy_is_fixed_link(dn))
of_phy_deregister_fixed_link(dn);
free_netdev(dev); free_netdev(dev);
dev_set_drvdata(&pdev->dev, NULL); dev_set_drvdata(&pdev->dev, NULL);
......
...@@ -627,6 +627,7 @@ static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv) ...@@ -627,6 +627,7 @@ static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv)
int bcmgenet_mii_init(struct net_device *dev) int bcmgenet_mii_init(struct net_device *dev)
{ {
struct bcmgenet_priv *priv = netdev_priv(dev); struct bcmgenet_priv *priv = netdev_priv(dev);
struct device_node *dn = priv->pdev->dev.of_node;
int ret; int ret;
ret = bcmgenet_mii_alloc(priv); ret = bcmgenet_mii_alloc(priv);
...@@ -640,6 +641,8 @@ int bcmgenet_mii_init(struct net_device *dev) ...@@ -640,6 +641,8 @@ int bcmgenet_mii_init(struct net_device *dev)
return 0; return 0;
out: out:
if (of_phy_is_fixed_link(dn))
of_phy_deregister_fixed_link(dn);
of_node_put(priv->phy_dn); of_node_put(priv->phy_dn);
mdiobus_unregister(priv->mii_bus); mdiobus_unregister(priv->mii_bus);
mdiobus_free(priv->mii_bus); mdiobus_free(priv->mii_bus);
...@@ -649,7 +652,10 @@ int bcmgenet_mii_init(struct net_device *dev) ...@@ -649,7 +652,10 @@ int bcmgenet_mii_init(struct net_device *dev)
void bcmgenet_mii_exit(struct net_device *dev) void bcmgenet_mii_exit(struct net_device *dev)
{ {
struct bcmgenet_priv *priv = netdev_priv(dev); struct bcmgenet_priv *priv = netdev_priv(dev);
struct device_node *dn = priv->pdev->dev.of_node;
if (of_phy_is_fixed_link(dn))
of_phy_deregister_fixed_link(dn);
of_node_put(priv->phy_dn); of_node_put(priv->phy_dn);
mdiobus_unregister(priv->mii_bus); mdiobus_unregister(priv->mii_bus);
mdiobus_free(priv->mii_bus); mdiobus_free(priv->mii_bus);
......
...@@ -3475,6 +3475,8 @@ fec_probe(struct platform_device *pdev) ...@@ -3475,6 +3475,8 @@ fec_probe(struct platform_device *pdev)
failed_clk_ipg: failed_clk_ipg:
fec_enet_clk_enable(ndev, false); fec_enet_clk_enable(ndev, false);
failed_clk: failed_clk:
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
failed_phy: failed_phy:
of_node_put(phy_node); of_node_put(phy_node);
failed_ioremap: failed_ioremap:
...@@ -3488,6 +3490,7 @@ fec_drv_remove(struct platform_device *pdev) ...@@ -3488,6 +3490,7 @@ fec_drv_remove(struct platform_device *pdev)
{ {
struct net_device *ndev = platform_get_drvdata(pdev); struct net_device *ndev = platform_get_drvdata(pdev);
struct fec_enet_private *fep = netdev_priv(ndev); struct fec_enet_private *fep = netdev_priv(ndev);
struct device_node *np = pdev->dev.of_node;
cancel_work_sync(&fep->tx_timeout_work); cancel_work_sync(&fep->tx_timeout_work);
fec_ptp_stop(pdev); fec_ptp_stop(pdev);
...@@ -3495,6 +3498,8 @@ fec_drv_remove(struct platform_device *pdev) ...@@ -3495,6 +3498,8 @@ fec_drv_remove(struct platform_device *pdev)
fec_enet_mii_remove(fep); fec_enet_mii_remove(fep);
if (fep->reg_phy) if (fep->reg_phy)
regulator_disable(fep->reg_phy); regulator_disable(fep->reg_phy);
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
of_node_put(fep->phy_node); of_node_put(fep->phy_node);
free_netdev(ndev); free_netdev(ndev);
......
...@@ -980,7 +980,7 @@ static int fs_enet_probe(struct platform_device *ofdev) ...@@ -980,7 +980,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
err = clk_prepare_enable(clk); err = clk_prepare_enable(clk);
if (err) { if (err) {
ret = err; ret = err;
goto out_free_fpi; goto out_deregister_fixed_link;
} }
fpi->clk_per = clk; fpi->clk_per = clk;
} }
...@@ -1061,6 +1061,9 @@ static int fs_enet_probe(struct platform_device *ofdev) ...@@ -1061,6 +1061,9 @@ static int fs_enet_probe(struct platform_device *ofdev)
of_node_put(fpi->phy_node); of_node_put(fpi->phy_node);
if (fpi->clk_per) if (fpi->clk_per)
clk_disable_unprepare(fpi->clk_per); clk_disable_unprepare(fpi->clk_per);
out_deregister_fixed_link:
if (of_phy_is_fixed_link(ofdev->dev.of_node))
of_phy_deregister_fixed_link(ofdev->dev.of_node);
out_free_fpi: out_free_fpi:
kfree(fpi); kfree(fpi);
return ret; return ret;
...@@ -1079,6 +1082,8 @@ static int fs_enet_remove(struct platform_device *ofdev) ...@@ -1079,6 +1082,8 @@ static int fs_enet_remove(struct platform_device *ofdev)
of_node_put(fep->fpi->phy_node); of_node_put(fep->fpi->phy_node);
if (fep->fpi->clk_per) if (fep->fpi->clk_per)
clk_disable_unprepare(fep->fpi->clk_per); clk_disable_unprepare(fep->fpi->clk_per);
if (of_phy_is_fixed_link(ofdev->dev.of_node))
of_phy_deregister_fixed_link(ofdev->dev.of_node);
free_netdev(ndev); free_netdev(ndev);
return 0; return 0;
} }
......
...@@ -1312,6 +1312,7 @@ static void gfar_init_addr_hash_table(struct gfar_private *priv) ...@@ -1312,6 +1312,7 @@ static void gfar_init_addr_hash_table(struct gfar_private *priv)
*/ */
static int gfar_probe(struct platform_device *ofdev) static int gfar_probe(struct platform_device *ofdev)
{ {
struct device_node *np = ofdev->dev.of_node;
struct net_device *dev = NULL; struct net_device *dev = NULL;
struct gfar_private *priv = NULL; struct gfar_private *priv = NULL;
int err = 0, i; int err = 0, i;
...@@ -1462,6 +1463,8 @@ static int gfar_probe(struct platform_device *ofdev) ...@@ -1462,6 +1463,8 @@ static int gfar_probe(struct platform_device *ofdev)
return 0; return 0;
register_fail: register_fail:
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
unmap_group_regs(priv); unmap_group_regs(priv);
gfar_free_rx_queues(priv); gfar_free_rx_queues(priv);
gfar_free_tx_queues(priv); gfar_free_tx_queues(priv);
...@@ -1474,11 +1477,16 @@ static int gfar_probe(struct platform_device *ofdev) ...@@ -1474,11 +1477,16 @@ static int gfar_probe(struct platform_device *ofdev)
static int gfar_remove(struct platform_device *ofdev) static int gfar_remove(struct platform_device *ofdev)
{ {
struct gfar_private *priv = platform_get_drvdata(ofdev); struct gfar_private *priv = platform_get_drvdata(ofdev);
struct device_node *np = ofdev->dev.of_node;
of_node_put(priv->phy_node); of_node_put(priv->phy_node);
of_node_put(priv->tbi_node); of_node_put(priv->tbi_node);
unregister_netdev(priv->ndev); unregister_netdev(priv->ndev);
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
unmap_group_regs(priv); unmap_group_regs(priv);
gfar_free_rx_queues(priv); gfar_free_rx_queues(priv);
gfar_free_tx_queues(priv); gfar_free_tx_queues(priv);
......
...@@ -3868,9 +3868,8 @@ static int ucc_geth_probe(struct platform_device* ofdev) ...@@ -3868,9 +3868,8 @@ static int ucc_geth_probe(struct platform_device* ofdev)
dev = alloc_etherdev(sizeof(*ugeth)); dev = alloc_etherdev(sizeof(*ugeth));
if (dev == NULL) { if (dev == NULL) {
of_node_put(ug_info->tbi_node); err = -ENOMEM;
of_node_put(ug_info->phy_node); goto err_deregister_fixed_link;
return -ENOMEM;
} }
ugeth = netdev_priv(dev); ugeth = netdev_priv(dev);
...@@ -3907,10 +3906,7 @@ static int ucc_geth_probe(struct platform_device* ofdev) ...@@ -3907,10 +3906,7 @@ static int ucc_geth_probe(struct platform_device* ofdev)
if (netif_msg_probe(ugeth)) if (netif_msg_probe(ugeth))
pr_err("%s: Cannot register net device, aborting\n", pr_err("%s: Cannot register net device, aborting\n",
dev->name); dev->name);
free_netdev(dev); goto err_free_netdev;
of_node_put(ug_info->tbi_node);
of_node_put(ug_info->phy_node);
return err;
} }
mac_addr = of_get_mac_address(np); mac_addr = of_get_mac_address(np);
...@@ -3923,16 +3919,29 @@ static int ucc_geth_probe(struct platform_device* ofdev) ...@@ -3923,16 +3919,29 @@ static int ucc_geth_probe(struct platform_device* ofdev)
ugeth->node = np; ugeth->node = np;
return 0; return 0;
err_free_netdev:
free_netdev(dev);
err_deregister_fixed_link:
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
of_node_put(ug_info->tbi_node);
of_node_put(ug_info->phy_node);
return err;
} }
static int ucc_geth_remove(struct platform_device* ofdev) static int ucc_geth_remove(struct platform_device* ofdev)
{ {
struct net_device *dev = platform_get_drvdata(ofdev); struct net_device *dev = platform_get_drvdata(ofdev);
struct ucc_geth_private *ugeth = netdev_priv(dev); struct ucc_geth_private *ugeth = netdev_priv(dev);
struct device_node *np = ofdev->dev.of_node;
unregister_netdev(dev); unregister_netdev(dev);
free_netdev(dev); free_netdev(dev);
ucc_geth_memclean(ugeth); ucc_geth_memclean(ugeth);
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
of_node_put(ugeth->ug_info->tbi_node); of_node_put(ugeth->ug_info->tbi_node);
of_node_put(ugeth->ug_info->phy_node); of_node_put(ugeth->ug_info->phy_node);
......
...@@ -4191,6 +4191,8 @@ static int mvneta_probe(struct platform_device *pdev) ...@@ -4191,6 +4191,8 @@ static int mvneta_probe(struct platform_device *pdev)
clk_disable_unprepare(pp->clk); clk_disable_unprepare(pp->clk);
err_put_phy_node: err_put_phy_node:
of_node_put(phy_node); of_node_put(phy_node);
if (of_phy_is_fixed_link(dn))
of_phy_deregister_fixed_link(dn);
err_free_irq: err_free_irq:
irq_dispose_mapping(dev->irq); irq_dispose_mapping(dev->irq);
err_free_netdev: err_free_netdev:
...@@ -4202,6 +4204,7 @@ static int mvneta_probe(struct platform_device *pdev) ...@@ -4202,6 +4204,7 @@ static int mvneta_probe(struct platform_device *pdev)
static int mvneta_remove(struct platform_device *pdev) static int mvneta_remove(struct platform_device *pdev)
{ {
struct net_device *dev = platform_get_drvdata(pdev); struct net_device *dev = platform_get_drvdata(pdev);
struct device_node *dn = pdev->dev.of_node;
struct mvneta_port *pp = netdev_priv(dev); struct mvneta_port *pp = netdev_priv(dev);
unregister_netdev(dev); unregister_netdev(dev);
...@@ -4209,6 +4212,8 @@ static int mvneta_remove(struct platform_device *pdev) ...@@ -4209,6 +4212,8 @@ static int mvneta_remove(struct platform_device *pdev)
clk_disable_unprepare(pp->clk); clk_disable_unprepare(pp->clk);
free_percpu(pp->ports); free_percpu(pp->ports);
free_percpu(pp->stats); free_percpu(pp->stats);
if (of_phy_is_fixed_link(dn))
of_phy_deregister_fixed_link(dn);
irq_dispose_mapping(dev->irq); irq_dispose_mapping(dev->irq);
of_node_put(pp->phy_node); of_node_put(pp->phy_node);
free_netdev(dev); free_netdev(dev);
......
...@@ -318,6 +318,8 @@ static int mtk_phy_connect(struct net_device *dev) ...@@ -318,6 +318,8 @@ static int mtk_phy_connect(struct net_device *dev)
return 0; return 0;
err_phy: err_phy:
if (of_phy_is_fixed_link(mac->of_node))
of_phy_deregister_fixed_link(mac->of_node);
of_node_put(np); of_node_put(np);
dev_err(eth->dev, "%s: invalid phy\n", __func__); dev_err(eth->dev, "%s: invalid phy\n", __func__);
return -EINVAL; return -EINVAL;
...@@ -1923,6 +1925,8 @@ static void mtk_uninit(struct net_device *dev) ...@@ -1923,6 +1925,8 @@ static void mtk_uninit(struct net_device *dev)
struct mtk_eth *eth = mac->hw; struct mtk_eth *eth = mac->hw;
phy_disconnect(dev->phydev); phy_disconnect(dev->phydev);
if (of_phy_is_fixed_link(mac->of_node))
of_phy_deregister_fixed_link(mac->of_node);
mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0); mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0);
mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0); mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0);
} }
......
...@@ -1008,7 +1008,8 @@ static int ravb_phy_init(struct net_device *ndev) ...@@ -1008,7 +1008,8 @@ static int ravb_phy_init(struct net_device *ndev)
of_node_put(pn); of_node_put(pn);
if (!phydev) { if (!phydev) {
netdev_err(ndev, "failed to connect PHY\n"); netdev_err(ndev, "failed to connect PHY\n");
return -ENOENT; err = -ENOENT;
goto err_deregister_fixed_link;
} }
/* This driver only support 10/100Mbit speeds on Gen3 /* This driver only support 10/100Mbit speeds on Gen3
...@@ -1020,8 +1021,7 @@ static int ravb_phy_init(struct net_device *ndev) ...@@ -1020,8 +1021,7 @@ static int ravb_phy_init(struct net_device *ndev)
err = phy_set_max_speed(phydev, SPEED_100); err = phy_set_max_speed(phydev, SPEED_100);
if (err) { if (err) {
netdev_err(ndev, "failed to limit PHY to 100Mbit/s\n"); netdev_err(ndev, "failed to limit PHY to 100Mbit/s\n");
phy_disconnect(phydev); goto err_phy_disconnect;
return err;
} }
netdev_info(ndev, "limited PHY to 100Mbit/s\n"); netdev_info(ndev, "limited PHY to 100Mbit/s\n");
...@@ -1033,6 +1033,14 @@ static int ravb_phy_init(struct net_device *ndev) ...@@ -1033,6 +1033,14 @@ static int ravb_phy_init(struct net_device *ndev)
phy_attached_info(phydev); phy_attached_info(phydev);
return 0; return 0;
err_phy_disconnect:
phy_disconnect(phydev);
err_deregister_fixed_link:
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
return err;
} }
/* PHY control start function */ /* PHY control start function */
...@@ -1634,6 +1642,7 @@ static void ravb_set_rx_mode(struct net_device *ndev) ...@@ -1634,6 +1642,7 @@ static void ravb_set_rx_mode(struct net_device *ndev)
/* Device close function for Ethernet AVB */ /* Device close function for Ethernet AVB */
static int ravb_close(struct net_device *ndev) static int ravb_close(struct net_device *ndev)
{ {
struct device_node *np = ndev->dev.parent->of_node;
struct ravb_private *priv = netdev_priv(ndev); struct ravb_private *priv = netdev_priv(ndev);
struct ravb_tstamp_skb *ts_skb, *ts_skb2; struct ravb_tstamp_skb *ts_skb, *ts_skb2;
...@@ -1663,6 +1672,8 @@ static int ravb_close(struct net_device *ndev) ...@@ -1663,6 +1672,8 @@ static int ravb_close(struct net_device *ndev)
if (ndev->phydev) { if (ndev->phydev) {
phy_stop(ndev->phydev); phy_stop(ndev->phydev);
phy_disconnect(ndev->phydev); phy_disconnect(ndev->phydev);
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
} }
if (priv->chip_id != RCAR_GEN2) { if (priv->chip_id != RCAR_GEN2) {
......
...@@ -2881,7 +2881,7 @@ static int dwceqos_probe(struct platform_device *pdev) ...@@ -2881,7 +2881,7 @@ static int dwceqos_probe(struct platform_device *pdev)
ret = of_get_phy_mode(lp->pdev->dev.of_node); ret = of_get_phy_mode(lp->pdev->dev.of_node);
if (ret < 0) { if (ret < 0) {
dev_err(&lp->pdev->dev, "error in getting phy i/f\n"); dev_err(&lp->pdev->dev, "error in getting phy i/f\n");
goto err_out_clk_dis_phy; goto err_out_deregister_fixed_link;
} }
lp->phy_interface = ret; lp->phy_interface = ret;
...@@ -2889,14 +2889,14 @@ static int dwceqos_probe(struct platform_device *pdev) ...@@ -2889,14 +2889,14 @@ static int dwceqos_probe(struct platform_device *pdev)
ret = dwceqos_mii_init(lp); ret = dwceqos_mii_init(lp);
if (ret) { if (ret) {
dev_err(&lp->pdev->dev, "error in dwceqos_mii_init\n"); dev_err(&lp->pdev->dev, "error in dwceqos_mii_init\n");
goto err_out_clk_dis_phy; goto err_out_deregister_fixed_link;
} }
ret = dwceqos_mii_probe(ndev); ret = dwceqos_mii_probe(ndev);
if (ret != 0) { if (ret != 0) {
netdev_err(ndev, "mii_probe fail.\n"); netdev_err(ndev, "mii_probe fail.\n");
ret = -ENXIO; ret = -ENXIO;
goto err_out_clk_dis_phy; goto err_out_deregister_fixed_link;
} }
dwceqos_set_umac_addr(lp, lp->ndev->dev_addr, 0); dwceqos_set_umac_addr(lp, lp->ndev->dev_addr, 0);
...@@ -2914,7 +2914,7 @@ static int dwceqos_probe(struct platform_device *pdev) ...@@ -2914,7 +2914,7 @@ static int dwceqos_probe(struct platform_device *pdev)
if (ret) { if (ret) {
dev_err(&lp->pdev->dev, "Unable to retrieve DT, error %d\n", dev_err(&lp->pdev->dev, "Unable to retrieve DT, error %d\n",
ret); ret);
goto err_out_clk_dis_phy; goto err_out_deregister_fixed_link;
} }
dev_info(&lp->pdev->dev, "pdev->id %d, baseaddr 0x%08lx, irq %d\n", dev_info(&lp->pdev->dev, "pdev->id %d, baseaddr 0x%08lx, irq %d\n",
pdev->id, ndev->base_addr, ndev->irq); pdev->id, ndev->base_addr, ndev->irq);
...@@ -2924,7 +2924,7 @@ static int dwceqos_probe(struct platform_device *pdev) ...@@ -2924,7 +2924,7 @@ static int dwceqos_probe(struct platform_device *pdev)
if (ret) { if (ret) {
dev_err(&lp->pdev->dev, "Unable to request IRQ %d, error %d\n", dev_err(&lp->pdev->dev, "Unable to request IRQ %d, error %d\n",
ndev->irq, ret); ndev->irq, ret);
goto err_out_clk_dis_phy; goto err_out_deregister_fixed_link;
} }
if (netif_msg_probe(lp)) if (netif_msg_probe(lp))
...@@ -2935,11 +2935,14 @@ static int dwceqos_probe(struct platform_device *pdev) ...@@ -2935,11 +2935,14 @@ static int dwceqos_probe(struct platform_device *pdev)
ret = register_netdev(ndev); ret = register_netdev(ndev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
goto err_out_clk_dis_phy; goto err_out_deregister_fixed_link;
} }
return 0; return 0;
err_out_deregister_fixed_link:
if (of_phy_is_fixed_link(pdev->dev.of_node))
of_phy_deregister_fixed_link(pdev->dev.of_node);
err_out_clk_dis_phy: err_out_clk_dis_phy:
clk_disable_unprepare(lp->phy_ref_clk); clk_disable_unprepare(lp->phy_ref_clk);
err_out_clk_dis_aper: err_out_clk_dis_aper:
...@@ -2959,8 +2962,11 @@ static int dwceqos_remove(struct platform_device *pdev) ...@@ -2959,8 +2962,11 @@ static int dwceqos_remove(struct platform_device *pdev)
if (ndev) { if (ndev) {
lp = netdev_priv(ndev); lp = netdev_priv(ndev);
if (ndev->phydev) if (ndev->phydev) {
phy_disconnect(ndev->phydev); phy_disconnect(ndev->phydev);
if (of_phy_is_fixed_link(pdev->dev.of_node))
of_phy_deregister_fixed_link(pdev->dev.of_node);
}
mdiobus_unregister(lp->mii_bus); mdiobus_unregister(lp->mii_bus);
mdiobus_free(lp->mii_bus); mdiobus_free(lp->mii_bus);
......
...@@ -2459,20 +2459,8 @@ static void cpsw_remove_dt(struct platform_device *pdev) ...@@ -2459,20 +2459,8 @@ static void cpsw_remove_dt(struct platform_device *pdev)
if (strcmp(slave_node->name, "slave")) if (strcmp(slave_node->name, "slave"))
continue; continue;
if (of_phy_is_fixed_link(slave_node)) { if (of_phy_is_fixed_link(slave_node))
struct phy_device *phydev; of_phy_deregister_fixed_link(slave_node);
phydev = of_phy_find_device(slave_node);
if (phydev) {
fixed_phy_unregister(phydev);
/* Put references taken by
* of_phy_find_device() and
* of_phy_register_fixed_link().
*/
phy_device_free(phydev);
phy_device_free(phydev);
}
}
of_node_put(slave_data->phy_node); of_node_put(slave_data->phy_node);
......
...@@ -1767,6 +1767,7 @@ static int davinci_emac_try_get_mac(struct platform_device *pdev, ...@@ -1767,6 +1767,7 @@ static int davinci_emac_try_get_mac(struct platform_device *pdev,
*/ */
static int davinci_emac_probe(struct platform_device *pdev) static int davinci_emac_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node;
int rc = 0; int rc = 0;
struct resource *res, *res_ctrl; struct resource *res, *res_ctrl;
struct net_device *ndev; struct net_device *ndev;
...@@ -1805,7 +1806,7 @@ static int davinci_emac_probe(struct platform_device *pdev) ...@@ -1805,7 +1806,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
if (!pdata) { if (!pdata) {
dev_err(&pdev->dev, "no platform data\n"); dev_err(&pdev->dev, "no platform data\n");
rc = -ENODEV; rc = -ENODEV;
goto no_pdata; goto err_free_netdev;
} }
/* MAC addr and PHY mask , RMII enable info from platform_data */ /* MAC addr and PHY mask , RMII enable info from platform_data */
...@@ -1941,6 +1942,10 @@ static int davinci_emac_probe(struct platform_device *pdev) ...@@ -1941,6 +1942,10 @@ static int davinci_emac_probe(struct platform_device *pdev)
cpdma_chan_destroy(priv->rxchan); cpdma_chan_destroy(priv->rxchan);
cpdma_ctlr_destroy(priv->dma); cpdma_ctlr_destroy(priv->dma);
no_pdata: no_pdata:
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
of_node_put(priv->phy_node);
err_free_netdev:
free_netdev(ndev); free_netdev(ndev);
return rc; return rc;
} }
...@@ -1956,6 +1961,7 @@ static int davinci_emac_remove(struct platform_device *pdev) ...@@ -1956,6 +1961,7 @@ static int davinci_emac_remove(struct platform_device *pdev)
{ {
struct net_device *ndev = platform_get_drvdata(pdev); struct net_device *ndev = platform_get_drvdata(pdev);
struct emac_priv *priv = netdev_priv(ndev); struct emac_priv *priv = netdev_priv(ndev);
struct device_node *np = pdev->dev.of_node;
dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n"); dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n");
...@@ -1968,6 +1974,8 @@ static int davinci_emac_remove(struct platform_device *pdev) ...@@ -1968,6 +1974,8 @@ static int davinci_emac_remove(struct platform_device *pdev)
unregister_netdev(ndev); unregister_netdev(ndev);
of_node_put(priv->phy_node); of_node_put(priv->phy_node);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
free_netdev(ndev); free_netdev(ndev);
return 0; return 0;
......
...@@ -490,3 +490,18 @@ int of_phy_register_fixed_link(struct device_node *np) ...@@ -490,3 +490,18 @@ int of_phy_register_fixed_link(struct device_node *np)
return -ENODEV; return -ENODEV;
} }
EXPORT_SYMBOL(of_phy_register_fixed_link); EXPORT_SYMBOL(of_phy_register_fixed_link);
void of_phy_deregister_fixed_link(struct device_node *np)
{
struct phy_device *phydev;
phydev = of_phy_find_device(np);
if (!phydev)
return;
fixed_phy_unregister(phydev);
put_device(&phydev->mdio.dev); /* of_phy_find_device() */
phy_device_free(phydev); /* fixed_phy_register() */
}
EXPORT_SYMBOL(of_phy_deregister_fixed_link);
...@@ -29,6 +29,7 @@ struct phy_device *of_phy_attach(struct net_device *dev, ...@@ -29,6 +29,7 @@ struct phy_device *of_phy_attach(struct net_device *dev,
extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np); extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np);
extern int of_mdio_parse_addr(struct device *dev, const struct device_node *np); extern int of_mdio_parse_addr(struct device *dev, const struct device_node *np);
extern int of_phy_register_fixed_link(struct device_node *np); extern int of_phy_register_fixed_link(struct device_node *np);
extern void of_phy_deregister_fixed_link(struct device_node *np);
extern bool of_phy_is_fixed_link(struct device_node *np); extern bool of_phy_is_fixed_link(struct device_node *np);
#else /* CONFIG_OF */ #else /* CONFIG_OF */
...@@ -83,6 +84,9 @@ static inline int of_phy_register_fixed_link(struct device_node *np) ...@@ -83,6 +84,9 @@ static inline int of_phy_register_fixed_link(struct device_node *np)
{ {
return -ENOSYS; return -ENOSYS;
} }
static inline void of_phy_deregister_fixed_link(struct device_node *np)
{
}
static inline bool of_phy_is_fixed_link(struct device_node *np) static inline bool of_phy_is_fixed_link(struct device_node *np)
{ {
return false; return false;
......
...@@ -506,16 +506,8 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, ...@@ -506,16 +506,8 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
void dsa_cpu_dsa_destroy(struct device_node *port_dn) void dsa_cpu_dsa_destroy(struct device_node *port_dn)
{ {
struct phy_device *phydev; if (of_phy_is_fixed_link(port_dn))
of_phy_deregister_fixed_link(port_dn);
if (of_phy_is_fixed_link(port_dn)) {
phydev = of_phy_find_device(port_dn);
if (phydev) {
fixed_phy_unregister(phydev);
put_device(&phydev->mdio.dev);
phy_device_free(phydev);
}
}
} }
static void dsa_switch_destroy(struct dsa_switch *ds) static void dsa_switch_destroy(struct dsa_switch *ds)
......
...@@ -1125,7 +1125,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, ...@@ -1125,7 +1125,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
p->phy_interface = mode; p->phy_interface = mode;
phy_dn = of_parse_phandle(port_dn, "phy-handle", 0); phy_dn = of_parse_phandle(port_dn, "phy-handle", 0);
if (of_phy_is_fixed_link(port_dn)) { if (!phy_dn && of_phy_is_fixed_link(port_dn)) {
/* In the case of a fixed PHY, the DT node associated /* In the case of a fixed PHY, the DT node associated
* to the fixed PHY is the Port DT node * to the fixed PHY is the Port DT node
*/ */
...@@ -1135,7 +1135,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, ...@@ -1135,7 +1135,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
return ret; return ret;
} }
phy_is_fixed = true; phy_is_fixed = true;
phy_dn = port_dn; phy_dn = of_node_get(port_dn);
} }
if (ds->ops->get_phy_flags) if (ds->ops->get_phy_flags)
...@@ -1154,6 +1154,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, ...@@ -1154,6 +1154,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
ret = dsa_slave_phy_connect(p, slave_dev, phy_id); ret = dsa_slave_phy_connect(p, slave_dev, phy_id);
if (ret) { if (ret) {
netdev_err(slave_dev, "failed to connect to phy%d: %d\n", phy_id, ret); netdev_err(slave_dev, "failed to connect to phy%d: %d\n", phy_id, ret);
of_node_put(phy_dn);
return ret; return ret;
} }
} else { } else {
...@@ -1162,6 +1163,8 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, ...@@ -1162,6 +1163,8 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
phy_flags, phy_flags,
p->phy_interface); p->phy_interface);
} }
of_node_put(phy_dn);
} }
if (p->phy && phy_is_fixed) if (p->phy && phy_is_fixed)
...@@ -1174,6 +1177,8 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, ...@@ -1174,6 +1177,8 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
ret = dsa_slave_phy_connect(p, slave_dev, p->port); ret = dsa_slave_phy_connect(p, slave_dev, p->port);
if (ret) { if (ret) {
netdev_err(slave_dev, "failed to connect to port %d: %d\n", p->port, ret); netdev_err(slave_dev, "failed to connect to port %d: %d\n", p->port, ret);
if (phy_is_fixed)
of_phy_deregister_fixed_link(port_dn);
return ret; return ret;
} }
} }
...@@ -1289,10 +1294,18 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent, ...@@ -1289,10 +1294,18 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
void dsa_slave_destroy(struct net_device *slave_dev) void dsa_slave_destroy(struct net_device *slave_dev)
{ {
struct dsa_slave_priv *p = netdev_priv(slave_dev); struct dsa_slave_priv *p = netdev_priv(slave_dev);
struct dsa_switch *ds = p->parent;
struct device_node *port_dn;
port_dn = ds->ports[p->port].dn;
netif_carrier_off(slave_dev); netif_carrier_off(slave_dev);
if (p->phy) if (p->phy) {
phy_disconnect(p->phy); phy_disconnect(p->phy);
if (of_phy_is_fixed_link(port_dn))
of_phy_deregister_fixed_link(port_dn);
}
unregister_netdev(slave_dev); unregister_netdev(slave_dev);
free_netdev(slave_dev); free_netdev(slave_dev);
} }
......
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