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>
This commit is contained in:
Коммит
f2ebf2a6ca
|
@ -819,6 +819,8 @@ static int init_phy(struct net_device *dev)
|
|||
|
||||
if (!phydev) {
|
||||
netdev_err(dev, "Could not find the PHY\n");
|
||||
if (fixed_link)
|
||||
of_phy_deregister_fixed_link(priv->device->of_node);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -1545,10 +1547,15 @@ err_free_netdev:
|
|||
static int altera_tse_remove(struct platform_device *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);
|
||||
|
||||
if (of_phy_is_fixed_link(priv->device->of_node))
|
||||
of_phy_deregister_fixed_link(priv->device->of_node);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
altera_tse_mdio_destroy(ndev);
|
||||
unregister_netdev(ndev);
|
||||
|
|
|
@ -1466,12 +1466,12 @@ static int nb8800_probe(struct platform_device *pdev)
|
|||
|
||||
ret = nb8800_hw_init(dev);
|
||||
if (ret)
|
||||
goto err_free_bus;
|
||||
goto err_deregister_fixed_link;
|
||||
|
||||
if (ops && ops->init) {
|
||||
ret = ops->init(dev);
|
||||
if (ret)
|
||||
goto err_free_bus;
|
||||
goto err_deregister_fixed_link;
|
||||
}
|
||||
|
||||
dev->netdev_ops = &nb8800_netdev_ops;
|
||||
|
@ -1504,6 +1504,9 @@ static int nb8800_probe(struct platform_device *pdev)
|
|||
|
||||
err_free_dma:
|
||||
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:
|
||||
of_node_put(priv->phy_node);
|
||||
mdiobus_unregister(bus);
|
||||
|
@ -1521,6 +1524,8 @@ static int nb8800_remove(struct platform_device *pdev)
|
|||
struct nb8800_priv *priv = netdev_priv(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);
|
||||
|
||||
mdiobus_unregister(priv->mii_bus);
|
||||
|
|
|
@ -1755,13 +1755,13 @@ static int bcm_sysport_probe(struct platform_device *pdev)
|
|||
if (priv->irq0 <= 0 || priv->irq1 <= 0) {
|
||||
dev_err(&pdev->dev, "invalid interrupts\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
goto err_free_netdev;
|
||||
}
|
||||
|
||||
priv->base = devm_ioremap_resource(&pdev->dev, r);
|
||||
if (IS_ERR(priv->base)) {
|
||||
ret = PTR_ERR(priv->base);
|
||||
goto err;
|
||||
goto err_free_netdev;
|
||||
}
|
||||
|
||||
priv->netdev = dev;
|
||||
|
@ -1779,7 +1779,7 @@ static int bcm_sysport_probe(struct platform_device *pdev)
|
|||
ret = of_phy_register_fixed_link(dn);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register fixed PHY\n");
|
||||
goto err;
|
||||
goto err_free_netdev;
|
||||
}
|
||||
|
||||
priv->phy_dn = dn;
|
||||
|
@ -1821,7 +1821,7 @@ static int bcm_sysport_probe(struct platform_device *pdev)
|
|||
ret = register_netdev(dev);
|
||||
if (ret) {
|
||||
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;
|
||||
|
@ -1832,7 +1832,11 @@ static int bcm_sysport_probe(struct platform_device *pdev)
|
|||
priv->base, priv->irq0, priv->irq1, txq, rxq);
|
||||
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1840,11 +1844,14 @@ err:
|
|||
static int bcm_sysport_remove(struct platform_device *pdev)
|
||||
{
|
||||
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
|
||||
* and we use managed allocations
|
||||
*/
|
||||
unregister_netdev(dev);
|
||||
if (of_phy_is_fixed_link(dn))
|
||||
of_phy_deregister_fixed_link(dn);
|
||||
free_netdev(dev);
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
|
||||
|
|
|
@ -627,6 +627,7 @@ static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv)
|
|||
int bcmgenet_mii_init(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct device_node *dn = priv->pdev->dev.of_node;
|
||||
int ret;
|
||||
|
||||
ret = bcmgenet_mii_alloc(priv);
|
||||
|
@ -640,6 +641,8 @@ int bcmgenet_mii_init(struct net_device *dev)
|
|||
return 0;
|
||||
|
||||
out:
|
||||
if (of_phy_is_fixed_link(dn))
|
||||
of_phy_deregister_fixed_link(dn);
|
||||
of_node_put(priv->phy_dn);
|
||||
mdiobus_unregister(priv->mii_bus);
|
||||
mdiobus_free(priv->mii_bus);
|
||||
|
@ -649,7 +652,10 @@ out:
|
|||
void bcmgenet_mii_exit(struct net_device *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);
|
||||
mdiobus_unregister(priv->mii_bus);
|
||||
mdiobus_free(priv->mii_bus);
|
||||
|
|
|
@ -3475,6 +3475,8 @@ failed_regulator:
|
|||
failed_clk_ipg:
|
||||
fec_enet_clk_enable(ndev, false);
|
||||
failed_clk:
|
||||
if (of_phy_is_fixed_link(np))
|
||||
of_phy_deregister_fixed_link(np);
|
||||
failed_phy:
|
||||
of_node_put(phy_node);
|
||||
failed_ioremap:
|
||||
|
@ -3488,6 +3490,7 @@ fec_drv_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct net_device *ndev = platform_get_drvdata(pdev);
|
||||
struct fec_enet_private *fep = netdev_priv(ndev);
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
||||
cancel_work_sync(&fep->tx_timeout_work);
|
||||
fec_ptp_stop(pdev);
|
||||
|
@ -3495,6 +3498,8 @@ fec_drv_remove(struct platform_device *pdev)
|
|||
fec_enet_mii_remove(fep);
|
||||
if (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);
|
||||
free_netdev(ndev);
|
||||
|
||||
|
|
|
@ -980,7 +980,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
|
|||
err = clk_prepare_enable(clk);
|
||||
if (err) {
|
||||
ret = err;
|
||||
goto out_free_fpi;
|
||||
goto out_deregister_fixed_link;
|
||||
}
|
||||
fpi->clk_per = clk;
|
||||
}
|
||||
|
@ -1061,6 +1061,9 @@ out_put:
|
|||
of_node_put(fpi->phy_node);
|
||||
if (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:
|
||||
kfree(fpi);
|
||||
return ret;
|
||||
|
@ -1079,6 +1082,8 @@ static int fs_enet_remove(struct platform_device *ofdev)
|
|||
of_node_put(fep->fpi->phy_node);
|
||||
if (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);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1312,6 +1312,7 @@ static void gfar_init_addr_hash_table(struct gfar_private *priv)
|
|||
*/
|
||||
static int gfar_probe(struct platform_device *ofdev)
|
||||
{
|
||||
struct device_node *np = ofdev->dev.of_node;
|
||||
struct net_device *dev = NULL;
|
||||
struct gfar_private *priv = NULL;
|
||||
int err = 0, i;
|
||||
|
@ -1462,6 +1463,8 @@ static int gfar_probe(struct platform_device *ofdev)
|
|||
return 0;
|
||||
|
||||
register_fail:
|
||||
if (of_phy_is_fixed_link(np))
|
||||
of_phy_deregister_fixed_link(np);
|
||||
unmap_group_regs(priv);
|
||||
gfar_free_rx_queues(priv);
|
||||
gfar_free_tx_queues(priv);
|
||||
|
@ -1474,11 +1477,16 @@ register_fail:
|
|||
static int gfar_remove(struct platform_device *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->tbi_node);
|
||||
|
||||
unregister_netdev(priv->ndev);
|
||||
|
||||
if (of_phy_is_fixed_link(np))
|
||||
of_phy_deregister_fixed_link(np);
|
||||
|
||||
unmap_group_regs(priv);
|
||||
gfar_free_rx_queues(priv);
|
||||
gfar_free_tx_queues(priv);
|
||||
|
|
|
@ -3868,9 +3868,8 @@ static int ucc_geth_probe(struct platform_device* ofdev)
|
|||
dev = alloc_etherdev(sizeof(*ugeth));
|
||||
|
||||
if (dev == NULL) {
|
||||
of_node_put(ug_info->tbi_node);
|
||||
of_node_put(ug_info->phy_node);
|
||||
return -ENOMEM;
|
||||
err = -ENOMEM;
|
||||
goto err_deregister_fixed_link;
|
||||
}
|
||||
|
||||
ugeth = netdev_priv(dev);
|
||||
|
@ -3907,10 +3906,7 @@ static int ucc_geth_probe(struct platform_device* ofdev)
|
|||
if (netif_msg_probe(ugeth))
|
||||
pr_err("%s: Cannot register net device, aborting\n",
|
||||
dev->name);
|
||||
free_netdev(dev);
|
||||
of_node_put(ug_info->tbi_node);
|
||||
of_node_put(ug_info->phy_node);
|
||||
return err;
|
||||
goto err_free_netdev;
|
||||
}
|
||||
|
||||
mac_addr = of_get_mac_address(np);
|
||||
|
@ -3923,16 +3919,29 @@ static int ucc_geth_probe(struct platform_device* ofdev)
|
|||
ugeth->node = np;
|
||||
|
||||
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)
|
||||
{
|
||||
struct net_device *dev = platform_get_drvdata(ofdev);
|
||||
struct ucc_geth_private *ugeth = netdev_priv(dev);
|
||||
struct device_node *np = ofdev->dev.of_node;
|
||||
|
||||
unregister_netdev(dev);
|
||||
free_netdev(dev);
|
||||
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->phy_node);
|
||||
|
||||
|
|
|
@ -4191,6 +4191,8 @@ err_clk:
|
|||
clk_disable_unprepare(pp->clk);
|
||||
err_put_phy_node:
|
||||
of_node_put(phy_node);
|
||||
if (of_phy_is_fixed_link(dn))
|
||||
of_phy_deregister_fixed_link(dn);
|
||||
err_free_irq:
|
||||
irq_dispose_mapping(dev->irq);
|
||||
err_free_netdev:
|
||||
|
@ -4202,6 +4204,7 @@ err_free_netdev:
|
|||
static int mvneta_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct net_device *dev = platform_get_drvdata(pdev);
|
||||
struct device_node *dn = pdev->dev.of_node;
|
||||
struct mvneta_port *pp = netdev_priv(dev);
|
||||
|
||||
unregister_netdev(dev);
|
||||
|
@ -4209,6 +4212,8 @@ static int mvneta_remove(struct platform_device *pdev)
|
|||
clk_disable_unprepare(pp->clk);
|
||||
free_percpu(pp->ports);
|
||||
free_percpu(pp->stats);
|
||||
if (of_phy_is_fixed_link(dn))
|
||||
of_phy_deregister_fixed_link(dn);
|
||||
irq_dispose_mapping(dev->irq);
|
||||
of_node_put(pp->phy_node);
|
||||
free_netdev(dev);
|
||||
|
|
|
@ -318,6 +318,8 @@ static int mtk_phy_connect(struct net_device *dev)
|
|||
return 0;
|
||||
|
||||
err_phy:
|
||||
if (of_phy_is_fixed_link(mac->of_node))
|
||||
of_phy_deregister_fixed_link(mac->of_node);
|
||||
of_node_put(np);
|
||||
dev_err(eth->dev, "%s: invalid phy\n", __func__);
|
||||
return -EINVAL;
|
||||
|
@ -1923,6 +1925,8 @@ static void mtk_uninit(struct net_device *dev)
|
|||
struct mtk_eth *eth = mac->hw;
|
||||
|
||||
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_PDMA_INT_MASK, ~0);
|
||||
}
|
||||
|
|
|
@ -1008,7 +1008,8 @@ static int ravb_phy_init(struct net_device *ndev)
|
|||
of_node_put(pn);
|
||||
if (!phydev) {
|
||||
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
|
||||
|
@ -1020,8 +1021,7 @@ static int ravb_phy_init(struct net_device *ndev)
|
|||
err = phy_set_max_speed(phydev, SPEED_100);
|
||||
if (err) {
|
||||
netdev_err(ndev, "failed to limit PHY to 100Mbit/s\n");
|
||||
phy_disconnect(phydev);
|
||||
return err;
|
||||
goto err_phy_disconnect;
|
||||
}
|
||||
|
||||
netdev_info(ndev, "limited PHY to 100Mbit/s\n");
|
||||
|
@ -1033,6 +1033,14 @@ static int ravb_phy_init(struct net_device *ndev)
|
|||
phy_attached_info(phydev);
|
||||
|
||||
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 */
|
||||
|
@ -1634,6 +1642,7 @@ static void ravb_set_rx_mode(struct net_device *ndev)
|
|||
/* Device close function for Ethernet AVB */
|
||||
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_tstamp_skb *ts_skb, *ts_skb2;
|
||||
|
||||
|
@ -1663,6 +1672,8 @@ static int ravb_close(struct net_device *ndev)
|
|||
if (ndev->phydev) {
|
||||
phy_stop(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) {
|
||||
|
|
|
@ -2881,7 +2881,7 @@ static int dwceqos_probe(struct platform_device *pdev)
|
|||
ret = of_get_phy_mode(lp->pdev->dev.of_node);
|
||||
if (ret < 0) {
|
||||
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;
|
||||
|
@ -2889,14 +2889,14 @@ static int dwceqos_probe(struct platform_device *pdev)
|
|||
ret = dwceqos_mii_init(lp);
|
||||
if (ret) {
|
||||
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);
|
||||
if (ret != 0) {
|
||||
netdev_err(ndev, "mii_probe fail.\n");
|
||||
ret = -ENXIO;
|
||||
goto err_out_clk_dis_phy;
|
||||
goto err_out_deregister_fixed_link;
|
||||
}
|
||||
|
||||
dwceqos_set_umac_addr(lp, lp->ndev->dev_addr, 0);
|
||||
|
@ -2914,7 +2914,7 @@ static int dwceqos_probe(struct platform_device *pdev)
|
|||
if (ret) {
|
||||
dev_err(&lp->pdev->dev, "Unable to retrieve DT, error %d\n",
|
||||
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",
|
||||
pdev->id, ndev->base_addr, ndev->irq);
|
||||
|
@ -2924,7 +2924,7 @@ static int dwceqos_probe(struct platform_device *pdev)
|
|||
if (ret) {
|
||||
dev_err(&lp->pdev->dev, "Unable to request IRQ %d, error %d\n",
|
||||
ndev->irq, ret);
|
||||
goto err_out_clk_dis_phy;
|
||||
goto err_out_deregister_fixed_link;
|
||||
}
|
||||
|
||||
if (netif_msg_probe(lp))
|
||||
|
@ -2935,11 +2935,14 @@ static int dwceqos_probe(struct platform_device *pdev)
|
|||
ret = register_netdev(ndev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
|
||||
goto err_out_clk_dis_phy;
|
||||
goto err_out_deregister_fixed_link;
|
||||
}
|
||||
|
||||
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:
|
||||
clk_disable_unprepare(lp->phy_ref_clk);
|
||||
err_out_clk_dis_aper:
|
||||
|
@ -2959,8 +2962,11 @@ static int dwceqos_remove(struct platform_device *pdev)
|
|||
if (ndev) {
|
||||
lp = netdev_priv(ndev);
|
||||
|
||||
if (ndev->phydev)
|
||||
if (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_free(lp->mii_bus);
|
||||
|
||||
|
|
|
@ -2459,20 +2459,8 @@ static void cpsw_remove_dt(struct platform_device *pdev)
|
|||
if (strcmp(slave_node->name, "slave"))
|
||||
continue;
|
||||
|
||||
if (of_phy_is_fixed_link(slave_node)) {
|
||||
struct phy_device *phydev;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (of_phy_is_fixed_link(slave_node))
|
||||
of_phy_deregister_fixed_link(slave_node);
|
||||
|
||||
of_node_put(slave_data->phy_node);
|
||||
|
||||
|
|
|
@ -1767,6 +1767,7 @@ static int davinci_emac_try_get_mac(struct platform_device *pdev,
|
|||
*/
|
||||
static int davinci_emac_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
int rc = 0;
|
||||
struct resource *res, *res_ctrl;
|
||||
struct net_device *ndev;
|
||||
|
@ -1805,7 +1806,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
|
|||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "no platform data\n");
|
||||
rc = -ENODEV;
|
||||
goto no_pdata;
|
||||
goto err_free_netdev;
|
||||
}
|
||||
|
||||
/* MAC addr and PHY mask , RMII enable info from platform_data */
|
||||
|
@ -1941,6 +1942,10 @@ no_cpdma_chan:
|
|||
cpdma_chan_destroy(priv->rxchan);
|
||||
cpdma_ctlr_destroy(priv->dma);
|
||||
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);
|
||||
return rc;
|
||||
}
|
||||
|
@ -1956,6 +1961,7 @@ static int davinci_emac_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct net_device *ndev = platform_get_drvdata(pdev);
|
||||
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");
|
||||
|
||||
|
@ -1968,6 +1974,8 @@ static int davinci_emac_remove(struct platform_device *pdev)
|
|||
unregister_netdev(ndev);
|
||||
of_node_put(priv->phy_node);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
if (of_phy_is_fixed_link(np))
|
||||
of_phy_deregister_fixed_link(np);
|
||||
free_netdev(ndev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -490,3 +490,18 @@ int of_phy_register_fixed_link(struct device_node *np)
|
|||
return -ENODEV;
|
||||
}
|
||||
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,
|
|||
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_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);
|
||||
|
||||
#else /* CONFIG_OF */
|
||||
|
@ -83,6 +84,9 @@ static inline int of_phy_register_fixed_link(struct device_node *np)
|
|||
{
|
||||
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)
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -506,16 +506,8 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
|
|||
|
||||
void dsa_cpu_dsa_destroy(struct device_node *port_dn)
|
||||
{
|
||||
struct phy_device *phydev;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (of_phy_is_fixed_link(port_dn))
|
||||
of_phy_deregister_fixed_link(port_dn);
|
||||
}
|
||||
|
||||
static void dsa_switch_destroy(struct dsa_switch *ds)
|
||||
|
|
|
@ -1125,7 +1125,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
|
|||
p->phy_interface = mode;
|
||||
|
||||
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
|
||||
* to the fixed PHY is the Port DT node
|
||||
*/
|
||||
|
@ -1135,7 +1135,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
|
|||
return ret;
|
||||
}
|
||||
phy_is_fixed = true;
|
||||
phy_dn = port_dn;
|
||||
phy_dn = of_node_get(port_dn);
|
||||
}
|
||||
|
||||
if (ds->ops->get_phy_flags)
|
||||
|
@ -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);
|
||||
if (ret) {
|
||||
netdev_err(slave_dev, "failed to connect to phy%d: %d\n", phy_id, ret);
|
||||
of_node_put(phy_dn);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
|
@ -1162,6 +1163,8 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
|
|||
phy_flags,
|
||||
p->phy_interface);
|
||||
}
|
||||
|
||||
of_node_put(phy_dn);
|
||||
}
|
||||
|
||||
if (p->phy && phy_is_fixed)
|
||||
|
@ -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);
|
||||
if (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;
|
||||
}
|
||||
}
|
||||
|
@ -1289,10 +1294,18 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
|
|||
void dsa_slave_destroy(struct net_device *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);
|
||||
if (p->phy)
|
||||
if (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);
|
||||
free_netdev(slave_dev);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче