net: fix phy refcounting in a bunch of drivers
of_phy_find_device() increments the phy struct device refcount, which
we need to properly balance. Add code to network drivers using this
function to ensure that the struct device refcount is correctly
balanced.
For xgene, looking back in the history, we should be able to use
of_phy_connect() with a zero flags argument for the DT case as this is
how the driver used to operate prior to de7b5b3d79
("net: eth: xgene:
change APM X-Gene SoC platform ethernet to support ACPI").
This leaves the Cavium Thunder BGX unfixed; fixing this driver is a
complicated task, one which the maintainers need to be involved with.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f018ae7a8c
commit
04d53b20fe
|
@ -689,16 +689,24 @@ static int xgene_enet_phy_connect(struct net_device *ndev)
|
||||||
netdev_dbg(ndev, "No phy-handle found in DT\n");
|
netdev_dbg(ndev, "No phy-handle found in DT\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
pdata->phy_dev = of_phy_find_device(phy_np);
|
|
||||||
}
|
|
||||||
|
|
||||||
phy_dev = pdata->phy_dev;
|
phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link,
|
||||||
|
0, pdata->phy_mode);
|
||||||
|
if (!phy_dev) {
|
||||||
|
netdev_err(ndev, "Could not connect to PHY\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
if (!phy_dev ||
|
pdata->phy_dev = phy_dev;
|
||||||
phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
|
} else {
|
||||||
pdata->phy_mode)) {
|
phy_dev = pdata->phy_dev;
|
||||||
netdev_err(ndev, "Could not connect to PHY\n");
|
|
||||||
return -ENODEV;
|
if (!phy_dev ||
|
||||||
|
phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
|
||||||
|
pdata->phy_mode)) {
|
||||||
|
netdev_err(ndev, "Could not connect to PHY\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pdata->phy_speed = SPEED_UNKNOWN;
|
pdata->phy_speed = SPEED_UNKNOWN;
|
||||||
|
|
|
@ -1702,6 +1702,7 @@ static void gfar_configure_serdes(struct net_device *dev)
|
||||||
tbiphy = of_phy_find_device(priv->tbi_node);
|
tbiphy = of_phy_find_device(priv->tbi_node);
|
||||||
if (!tbiphy) {
|
if (!tbiphy) {
|
||||||
dev_err(&dev->dev, "error: Could not get TBI device\n");
|
dev_err(&dev->dev, "error: Could not get TBI device\n");
|
||||||
|
put_device(&tbiphy->dev);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1723,6 +1724,8 @@ static void gfar_configure_serdes(struct net_device *dev)
|
||||||
phy_write(tbiphy, MII_BMCR,
|
phy_write(tbiphy, MII_BMCR,
|
||||||
BMCR_ANENABLE | BMCR_ANRESTART | BMCR_FULLDPLX |
|
BMCR_ANENABLE | BMCR_ANRESTART | BMCR_FULLDPLX |
|
||||||
BMCR_SPEED1000);
|
BMCR_SPEED1000);
|
||||||
|
|
||||||
|
put_device(&tbiphy->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __gfar_is_rx_idle(struct gfar_private *priv)
|
static int __gfar_is_rx_idle(struct gfar_private *priv)
|
||||||
|
|
|
@ -1384,6 +1384,8 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
|
||||||
value = phy_read(tbiphy, ENET_TBI_MII_CR);
|
value = phy_read(tbiphy, ENET_TBI_MII_CR);
|
||||||
value &= ~0x1000; /* Turn off autonegotiation */
|
value &= ~0x1000; /* Turn off autonegotiation */
|
||||||
phy_write(tbiphy, ENET_TBI_MII_CR, value);
|
phy_write(tbiphy, ENET_TBI_MII_CR, value);
|
||||||
|
|
||||||
|
put_device(&tbiphy->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2);
|
init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2);
|
||||||
|
@ -1702,8 +1704,10 @@ static void uec_configure_serdes(struct net_device *dev)
|
||||||
* everything for us? Resetting it takes the link down and requires
|
* everything for us? Resetting it takes the link down and requires
|
||||||
* several seconds for it to come back.
|
* several seconds for it to come back.
|
||||||
*/
|
*/
|
||||||
if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS)
|
if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS) {
|
||||||
|
put_device(&tbiphy->dev);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Single clk mode, mii mode off(for serdes communication) */
|
/* Single clk mode, mii mode off(for serdes communication) */
|
||||||
phy_write(tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS);
|
phy_write(tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS);
|
||||||
|
@ -1711,6 +1715,8 @@ static void uec_configure_serdes(struct net_device *dev)
|
||||||
phy_write(tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT);
|
phy_write(tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT);
|
||||||
|
|
||||||
phy_write(tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS);
|
phy_write(tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS);
|
||||||
|
|
||||||
|
put_device(&tbiphy->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure the PHY for dev.
|
/* Configure the PHY for dev.
|
||||||
|
|
|
@ -3175,6 +3175,8 @@ static int mvneta_probe(struct platform_device *pdev)
|
||||||
struct phy_device *phy = of_phy_find_device(dn);
|
struct phy_device *phy = of_phy_find_device(dn);
|
||||||
|
|
||||||
mvneta_fixed_link_update(pp, phy);
|
mvneta_fixed_link_update(pp, phy);
|
||||||
|
|
||||||
|
put_device(&phy->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -828,6 +828,8 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
|
||||||
if (!phydev)
|
if (!phydev)
|
||||||
dev_info(dev,
|
dev_info(dev,
|
||||||
"MDIO of the phy is not registered yet\n");
|
"MDIO of the phy is not registered yet\n");
|
||||||
|
else
|
||||||
|
put_device(&phydev->dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue