Skip to content

Commit

Permalink
net: ethernet: stmmac: fix of-node and fixed-link-phydev leaks
Browse files Browse the repository at this point in the history
Make sure to deregister and free any fixed-link phy registered during
probe on probe errors and on driver unbind by adding a new glue helper
function.

Drop the of-node reference taken in the same path also on late probe
errors (and not just on driver unbind) by moving the put from
stmmac_dvr_remove() to the new helper.

Fixes: 2773238 ("stmmac: add fixed-link device-tree support")
Fixes: 4613b27 ("ethernet: stmicro: stmmac: add missing of_node_put
after calling of_parse_phandle")
Signed-off-by: Johan Hovold <johan@kernel.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Johan Hovold authored and David S. Miller committed Dec 2, 2016
1 parent 661f049 commit d2ed0a7
Show file tree
Hide file tree
Showing 13 changed files with 156 additions and 49 deletions.
5 changes: 4 additions & 1 deletion drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static int dwmac_generic_probe(struct platform_device *pdev)
if (plat_dat->init) {
ret = plat_dat->init(pdev, plat_dat->bsp_priv);
if (ret)
return ret;
goto err_remove_config_dt;
}

ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
Expand All @@ -62,6 +62,9 @@ static int dwmac_generic_probe(struct platform_device *pdev)
err_exit:
if (plat_dat->exit)
plat_dat->exit(pdev, plat_dat->bsp_priv);
err_remove_config_dt:
if (pdev->dev.of_node)
stmmac_remove_config_dt(pdev, plat_dat);

return ret;
}
Expand Down
25 changes: 19 additions & 6 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,15 +271,17 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
return PTR_ERR(plat_dat);

gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
if (!gmac)
return -ENOMEM;
if (!gmac) {
err = -ENOMEM;
goto err_remove_config_dt;
}

gmac->pdev = pdev;

err = ipq806x_gmac_of_parse(gmac);
if (err) {
dev_err(dev, "device tree parsing error\n");
return err;
goto err_remove_config_dt;
}

regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL,
Expand All @@ -300,7 +302,8 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
default:
dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
phy_modes(gmac->phy_mode));
return -EINVAL;
err = -EINVAL;
goto err_remove_config_dt;
}
regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val);

Expand All @@ -319,7 +322,8 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
default:
dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
phy_modes(gmac->phy_mode));
return -EINVAL;
err = -EINVAL;
goto err_remove_config_dt;
}
regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val);

Expand All @@ -346,7 +350,16 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
plat_dat->bsp_priv = gmac;
plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed;

return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (err)
goto err_remove_config_dt;

return 0;

err_remove_config_dt:
stmmac_remove_config_dt(pdev, plat_dat);

return err;
}

static const struct of_device_id ipq806x_gmac_dwmac_match[] = {
Expand Down
17 changes: 14 additions & 3 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ static int lpc18xx_dwmac_probe(struct platform_device *pdev)
reg = syscon_regmap_lookup_by_compatible("nxp,lpc1850-creg");
if (IS_ERR(reg)) {
dev_err(&pdev->dev, "syscon lookup failed\n");
return PTR_ERR(reg);
ret = PTR_ERR(reg);
goto err_remove_config_dt;
}

if (plat_dat->interface == PHY_INTERFACE_MODE_MII) {
Expand All @@ -55,13 +56,23 @@ static int lpc18xx_dwmac_probe(struct platform_device *pdev)
ethmode = LPC18XX_CREG_CREG6_ETHMODE_RMII;
} else {
dev_err(&pdev->dev, "Only MII and RMII mode supported\n");
return -EINVAL;
ret = -EINVAL;
goto err_remove_config_dt;
}

regmap_update_bits(reg, LPC18XX_CREG_CREG6,
LPC18XX_CREG_CREG6_ETHMODE_MASK, ethmode);

return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
goto err_remove_config_dt;

return 0;

err_remove_config_dt:
stmmac_remove_config_dt(pdev, plat_dat);

return ret;
}

static const struct of_device_id lpc18xx_dwmac_match[] = {
Expand Down
23 changes: 18 additions & 5 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,31 @@ static int meson6_dwmac_probe(struct platform_device *pdev)
return PTR_ERR(plat_dat);

dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
if (!dwmac)
return -ENOMEM;
if (!dwmac) {
ret = -ENOMEM;
goto err_remove_config_dt;
}

res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
dwmac->reg = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dwmac->reg))
return PTR_ERR(dwmac->reg);
if (IS_ERR(dwmac->reg)) {
ret = PTR_ERR(dwmac->reg);
goto err_remove_config_dt;
}

plat_dat->bsp_priv = dwmac;
plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed;

return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
goto err_remove_config_dt;

return 0;

err_remove_config_dt:
stmmac_remove_config_dt(pdev, plat_dat);

return ret;
}

static const struct of_device_id meson6_dwmac_match[] = {
Expand Down
21 changes: 14 additions & 7 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,28 +264,33 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
return PTR_ERR(plat_dat);

dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
if (!dwmac)
return -ENOMEM;
if (!dwmac) {
ret = -ENOMEM;
goto err_remove_config_dt;
}

res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
dwmac->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dwmac->regs))
return PTR_ERR(dwmac->regs);
if (IS_ERR(dwmac->regs)) {
ret = PTR_ERR(dwmac->regs);
goto err_remove_config_dt;
}

dwmac->pdev = pdev;
dwmac->phy_mode = of_get_phy_mode(pdev->dev.of_node);
if (dwmac->phy_mode < 0) {
dev_err(&pdev->dev, "missing phy-mode property\n");
return -EINVAL;
ret = -EINVAL;
goto err_remove_config_dt;
}

ret = meson8b_init_clk(dwmac);
if (ret)
return ret;
goto err_remove_config_dt;

ret = meson8b_init_prg_eth(dwmac);
if (ret)
return ret;
goto err_remove_config_dt;

plat_dat->bsp_priv = dwmac;

Expand All @@ -297,6 +302,8 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)

err_clk_disable:
clk_disable_unprepare(dwmac->m25_div_clk);
err_remove_config_dt:
stmmac_remove_config_dt(pdev, plat_dat);

return ret;
}
Expand Down
10 changes: 7 additions & 3 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
Original file line number Diff line number Diff line change
Expand Up @@ -981,12 +981,14 @@ static int rk_gmac_probe(struct platform_device *pdev)
plat_dat->resume = rk_gmac_resume;

plat_dat->bsp_priv = rk_gmac_setup(pdev, data);
if (IS_ERR(plat_dat->bsp_priv))
return PTR_ERR(plat_dat->bsp_priv);
if (IS_ERR(plat_dat->bsp_priv)) {
ret = PTR_ERR(plat_dat->bsp_priv);
goto err_remove_config_dt;
}

ret = rk_gmac_init(pdev, plat_dat->bsp_priv);
if (ret)
return ret;
goto err_remove_config_dt;

ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
Expand All @@ -996,6 +998,8 @@ static int rk_gmac_probe(struct platform_device *pdev)

err_gmac_exit:
rk_gmac_exit(pdev, plat_dat->bsp_priv);
err_remove_config_dt:
stmmac_remove_config_dt(pdev, plat_dat);

return ret;
}
Expand Down
12 changes: 8 additions & 4 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,21 +316,23 @@ static int socfpga_dwmac_probe(struct platform_device *pdev)
return PTR_ERR(plat_dat);

dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);
if (!dwmac)
return -ENOMEM;
if (!dwmac) {
ret = -ENOMEM;
goto err_remove_config_dt;
}

ret = socfpga_dwmac_parse_data(dwmac, dev);
if (ret) {
dev_err(dev, "Unable to parse OF data\n");
return ret;
goto err_remove_config_dt;
}

plat_dat->bsp_priv = dwmac;
plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed;

ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
return ret;
goto err_remove_config_dt;

ndev = platform_get_drvdata(pdev);
stpriv = netdev_priv(ndev);
Expand All @@ -349,6 +351,8 @@ static int socfpga_dwmac_probe(struct platform_device *pdev)

err_dvr_remove:
stmmac_dvr_remove(&pdev->dev);
err_remove_config_dt:
stmmac_remove_config_dt(pdev, plat_dat);

return ret;
}
Expand Down
12 changes: 8 additions & 4 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,13 +345,15 @@ static int sti_dwmac_probe(struct platform_device *pdev)
return PTR_ERR(plat_dat);

dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
if (!dwmac)
return -ENOMEM;
if (!dwmac) {
ret = -ENOMEM;
goto err_remove_config_dt;
}

ret = sti_dwmac_parse_data(dwmac, pdev);
if (ret) {
dev_err(&pdev->dev, "Unable to parse OF data\n");
return ret;
goto err_remove_config_dt;
}

dwmac->fix_retime_src = data->fix_retime_src;
Expand All @@ -363,7 +365,7 @@ static int sti_dwmac_probe(struct platform_device *pdev)

ret = sti_dwmac_init(pdev, plat_dat->bsp_priv);
if (ret)
return ret;
goto err_remove_config_dt;

ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
Expand All @@ -373,6 +375,8 @@ static int sti_dwmac_probe(struct platform_device *pdev)

err_dwmac_exit:
sti_dwmac_exit(pdev, plat_dat->bsp_priv);
err_remove_config_dt:
stmmac_remove_config_dt(pdev, plat_dat);

return ret;
}
Expand Down
19 changes: 14 additions & 5 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,24 +107,33 @@ static int stm32_dwmac_probe(struct platform_device *pdev)
return PTR_ERR(plat_dat);

dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
if (!dwmac)
return -ENOMEM;
if (!dwmac) {
ret = -ENOMEM;
goto err_remove_config_dt;
}

ret = stm32_dwmac_parse_data(dwmac, &pdev->dev);
if (ret) {
dev_err(&pdev->dev, "Unable to parse OF data\n");
return ret;
goto err_remove_config_dt;
}

plat_dat->bsp_priv = dwmac;

ret = stm32_dwmac_init(plat_dat);
if (ret)
return ret;
goto err_remove_config_dt;

ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
stm32_dwmac_clk_disable(dwmac);
goto err_clk_disable;

return 0;

err_clk_disable:
stm32_dwmac_clk_disable(dwmac);
err_remove_config_dt:
stmmac_remove_config_dt(pdev, plat_dat);

return ret;
}
Expand Down
26 changes: 19 additions & 7 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,22 +120,27 @@ static int sun7i_gmac_probe(struct platform_device *pdev)
return PTR_ERR(plat_dat);

gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
if (!gmac)
return -ENOMEM;
if (!gmac) {
ret = -ENOMEM;
goto err_remove_config_dt;
}

gmac->interface = of_get_phy_mode(dev->of_node);

gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
if (IS_ERR(gmac->tx_clk)) {
dev_err(dev, "could not get tx clock\n");
return PTR_ERR(gmac->tx_clk);
ret = PTR_ERR(gmac->tx_clk);
goto err_remove_config_dt;
}

/* Optional regulator for PHY */
gmac->regulator = devm_regulator_get_optional(dev, "phy");
if (IS_ERR(gmac->regulator)) {
if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto err_remove_config_dt;
}
dev_info(dev, "no regulator found\n");
gmac->regulator = NULL;
}
Expand All @@ -151,11 +156,18 @@ static int sun7i_gmac_probe(struct platform_device *pdev)

ret = sun7i_gmac_init(pdev, plat_dat->bsp_priv);
if (ret)
return ret;
goto err_remove_config_dt;

ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
sun7i_gmac_exit(pdev, plat_dat->bsp_priv);
goto err_gmac_exit;

return 0;

err_gmac_exit:
sun7i_gmac_exit(pdev, plat_dat->bsp_priv);
err_remove_config_dt:
stmmac_remove_config_dt(pdev, plat_dat);

return ret;
}
Expand Down
Loading

0 comments on commit d2ed0a7

Please sign in to comment.