summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Holland <samuel@sholland.org>2021-01-03 14:17:42 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-01-17 16:16:55 +0300
commit22e1ed2abc661b94c30511b64d6e521de57902b8 (patch)
treedd08e9a1898839c5caf27df36d74f8d60f733986
parent413a79ccb98e9bf1c9d4b25b26c92d7d16be5e72 (diff)
downloadlinux-22e1ed2abc661b94c30511b64d6e521de57902b8.tar.xz
net: stmmac: dwmac-sun8i: Balance internal PHY resource references
[ Upstream commit 529254216773acd5039c07aa18cf06fd1f9fccdd ] While stmmac_pltfr_remove calls sun8i_dwmac_exit, the sun8i_dwmac_init and sun8i_dwmac_exit functions are also called by the stmmac_platform suspend/resume callbacks. They may be called many times during the device's lifetime and should not release resources used by the driver. Furthermore, there was no error handling in case registering the MDIO mux failed during probe, and the EPHY clock was never released at all. Fix all of these issues by moving the deinitialization code to a driver removal callback. Also ensure the EPHY is powered down before removal. Fixes: 634db83b8265 ("net: stmmac: dwmac-sun8i: Handle integrated/external MDIOs") Signed-off-by: Samuel Holland <samuel@sholland.org> Reviewed-by: Chen-Yu Tsai <wens@csie.org> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index b20f261fce5b..a05dee5d4584 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -1004,17 +1004,12 @@ static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv)
struct sunxi_priv_data *gmac = priv;
if (gmac->variant->soc_has_internal_phy) {
- /* sun8i_dwmac_exit could be called with mdiomux uninit */
- if (gmac->mux_handle)
- mdio_mux_uninit(gmac->mux_handle);
if (gmac->internal_phy_powered)
sun8i_dwmac_unpower_internal_phy(gmac);
}
sun8i_dwmac_unset_syscon(gmac);
- reset_control_put(gmac->rst_ephy);
-
clk_disable_unprepare(gmac->tx_clk);
if (gmac->regulator)
@@ -1244,6 +1239,8 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
return ret;
dwmac_mux:
+ reset_control_put(gmac->rst_ephy);
+ clk_put(gmac->ephy_clk);
sun8i_dwmac_unset_syscon(gmac);
dwmac_remove:
stmmac_dvr_remove(&pdev->dev);
@@ -1255,6 +1252,24 @@ dwmac_deconfig:
return ret;
}
+static int sun8i_dwmac_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ struct sunxi_priv_data *gmac = priv->plat->bsp_priv;
+
+ if (gmac->variant->soc_has_internal_phy) {
+ mdio_mux_uninit(gmac->mux_handle);
+ sun8i_dwmac_unpower_internal_phy(gmac);
+ reset_control_put(gmac->rst_ephy);
+ clk_put(gmac->ephy_clk);
+ }
+
+ stmmac_pltfr_remove(pdev);
+
+ return 0;
+}
+
static const struct of_device_id sun8i_dwmac_match[] = {
{ .compatible = "allwinner,sun8i-h3-emac",
.data = &emac_variant_h3 },
@@ -1274,7 +1289,7 @@ MODULE_DEVICE_TABLE(of, sun8i_dwmac_match);
static struct platform_driver sun8i_dwmac_driver = {
.probe = sun8i_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove = sun8i_dwmac_remove,
.driver = {
.name = "dwmac-sun8i",
.pm = &stmmac_pltfr_pm_ops,