diff options
author | Johan Hovold <johan@kernel.org> | 2016-11-30 09:29:55 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-12-02 10:42:47 -0500 |
commit | d2ed0a7755fe14c790f398ae55088d00492ef168 (patch) | |
tree | 38bf52c2e8c80c7ff2b09ebf6943734a9d01336e | |
parent | 661f049be17a3894cb438d46ba5af8e3643aac28 (diff) |
net: ethernet: stmmac: fix of-node and fixed-link-phydev leaks
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: 277323814e49 ("stmmac: add fixed-link device-tree support")
Fixes: 4613b279bee7 ("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>
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 25 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c | 17 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c | 23 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 21 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 19 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 26 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 32 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h | 2 |
13 files changed, 156 insertions, 49 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c index 05e46a82cdb1..e6e6c2fcc4b7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c | |||
@@ -50,7 +50,7 @@ static int dwmac_generic_probe(struct platform_device *pdev) | |||
50 | if (plat_dat->init) { | 50 | if (plat_dat->init) { |
51 | ret = plat_dat->init(pdev, plat_dat->bsp_priv); | 51 | ret = plat_dat->init(pdev, plat_dat->bsp_priv); |
52 | if (ret) | 52 | if (ret) |
53 | return ret; | 53 | goto err_remove_config_dt; |
54 | } | 54 | } |
55 | 55 | ||
56 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); | 56 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); |
@@ -62,6 +62,9 @@ static int dwmac_generic_probe(struct platform_device *pdev) | |||
62 | err_exit: | 62 | err_exit: |
63 | if (plat_dat->exit) | 63 | if (plat_dat->exit) |
64 | plat_dat->exit(pdev, plat_dat->bsp_priv); | 64 | plat_dat->exit(pdev, plat_dat->bsp_priv); |
65 | err_remove_config_dt: | ||
66 | if (pdev->dev.of_node) | ||
67 | stmmac_remove_config_dt(pdev, plat_dat); | ||
65 | 68 | ||
66 | return ret; | 69 | return ret; |
67 | } | 70 | } |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c index 36d3355f2fb0..866444b6c82f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | |||
@@ -271,15 +271,17 @@ static int ipq806x_gmac_probe(struct platform_device *pdev) | |||
271 | return PTR_ERR(plat_dat); | 271 | return PTR_ERR(plat_dat); |
272 | 272 | ||
273 | gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); | 273 | gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); |
274 | if (!gmac) | 274 | if (!gmac) { |
275 | return -ENOMEM; | 275 | err = -ENOMEM; |
276 | goto err_remove_config_dt; | ||
277 | } | ||
276 | 278 | ||
277 | gmac->pdev = pdev; | 279 | gmac->pdev = pdev; |
278 | 280 | ||
279 | err = ipq806x_gmac_of_parse(gmac); | 281 | err = ipq806x_gmac_of_parse(gmac); |
280 | if (err) { | 282 | if (err) { |
281 | dev_err(dev, "device tree parsing error\n"); | 283 | dev_err(dev, "device tree parsing error\n"); |
282 | return err; | 284 | goto err_remove_config_dt; |
283 | } | 285 | } |
284 | 286 | ||
285 | regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL, | 287 | regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL, |
@@ -300,7 +302,8 @@ static int ipq806x_gmac_probe(struct platform_device *pdev) | |||
300 | default: | 302 | default: |
301 | dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n", | 303 | dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n", |
302 | phy_modes(gmac->phy_mode)); | 304 | phy_modes(gmac->phy_mode)); |
303 | return -EINVAL; | 305 | err = -EINVAL; |
306 | goto err_remove_config_dt; | ||
304 | } | 307 | } |
305 | regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val); | 308 | regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val); |
306 | 309 | ||
@@ -319,7 +322,8 @@ static int ipq806x_gmac_probe(struct platform_device *pdev) | |||
319 | default: | 322 | default: |
320 | dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n", | 323 | dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n", |
321 | phy_modes(gmac->phy_mode)); | 324 | phy_modes(gmac->phy_mode)); |
322 | return -EINVAL; | 325 | err = -EINVAL; |
326 | goto err_remove_config_dt; | ||
323 | } | 327 | } |
324 | regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val); | 328 | regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val); |
325 | 329 | ||
@@ -346,7 +350,16 @@ static int ipq806x_gmac_probe(struct platform_device *pdev) | |||
346 | plat_dat->bsp_priv = gmac; | 350 | plat_dat->bsp_priv = gmac; |
347 | plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed; | 351 | plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed; |
348 | 352 | ||
349 | return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); | 353 | err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); |
354 | if (err) | ||
355 | goto err_remove_config_dt; | ||
356 | |||
357 | return 0; | ||
358 | |||
359 | err_remove_config_dt: | ||
360 | stmmac_remove_config_dt(pdev, plat_dat); | ||
361 | |||
362 | return err; | ||
350 | } | 363 | } |
351 | 364 | ||
352 | static const struct of_device_id ipq806x_gmac_dwmac_match[] = { | 365 | static const struct of_device_id ipq806x_gmac_dwmac_match[] = { |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c index 78e9d1861896..3d3f43d91b98 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c | |||
@@ -46,7 +46,8 @@ static int lpc18xx_dwmac_probe(struct platform_device *pdev) | |||
46 | reg = syscon_regmap_lookup_by_compatible("nxp,lpc1850-creg"); | 46 | reg = syscon_regmap_lookup_by_compatible("nxp,lpc1850-creg"); |
47 | if (IS_ERR(reg)) { | 47 | if (IS_ERR(reg)) { |
48 | dev_err(&pdev->dev, "syscon lookup failed\n"); | 48 | dev_err(&pdev->dev, "syscon lookup failed\n"); |
49 | return PTR_ERR(reg); | 49 | ret = PTR_ERR(reg); |
50 | goto err_remove_config_dt; | ||
50 | } | 51 | } |
51 | 52 | ||
52 | if (plat_dat->interface == PHY_INTERFACE_MODE_MII) { | 53 | if (plat_dat->interface == PHY_INTERFACE_MODE_MII) { |
@@ -55,13 +56,23 @@ static int lpc18xx_dwmac_probe(struct platform_device *pdev) | |||
55 | ethmode = LPC18XX_CREG_CREG6_ETHMODE_RMII; | 56 | ethmode = LPC18XX_CREG_CREG6_ETHMODE_RMII; |
56 | } else { | 57 | } else { |
57 | dev_err(&pdev->dev, "Only MII and RMII mode supported\n"); | 58 | dev_err(&pdev->dev, "Only MII and RMII mode supported\n"); |
58 | return -EINVAL; | 59 | ret = -EINVAL; |
60 | goto err_remove_config_dt; | ||
59 | } | 61 | } |
60 | 62 | ||
61 | regmap_update_bits(reg, LPC18XX_CREG_CREG6, | 63 | regmap_update_bits(reg, LPC18XX_CREG_CREG6, |
62 | LPC18XX_CREG_CREG6_ETHMODE_MASK, ethmode); | 64 | LPC18XX_CREG_CREG6_ETHMODE_MASK, ethmode); |
63 | 65 | ||
64 | return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); | 66 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); |
67 | if (ret) | ||
68 | goto err_remove_config_dt; | ||
69 | |||
70 | return 0; | ||
71 | |||
72 | err_remove_config_dt: | ||
73 | stmmac_remove_config_dt(pdev, plat_dat); | ||
74 | |||
75 | return ret; | ||
65 | } | 76 | } |
66 | 77 | ||
67 | static const struct of_device_id lpc18xx_dwmac_match[] = { | 78 | static const struct of_device_id lpc18xx_dwmac_match[] = { |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c index 309d99536a2c..7fdd1760a74c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c | |||
@@ -64,18 +64,31 @@ static int meson6_dwmac_probe(struct platform_device *pdev) | |||
64 | return PTR_ERR(plat_dat); | 64 | return PTR_ERR(plat_dat); |
65 | 65 | ||
66 | dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); | 66 | dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); |
67 | if (!dwmac) | 67 | if (!dwmac) { |
68 | return -ENOMEM; | 68 | ret = -ENOMEM; |
69 | goto err_remove_config_dt; | ||
70 | } | ||
69 | 71 | ||
70 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 72 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
71 | dwmac->reg = devm_ioremap_resource(&pdev->dev, res); | 73 | dwmac->reg = devm_ioremap_resource(&pdev->dev, res); |
72 | if (IS_ERR(dwmac->reg)) | 74 | if (IS_ERR(dwmac->reg)) { |
73 | return PTR_ERR(dwmac->reg); | 75 | ret = PTR_ERR(dwmac->reg); |
76 | goto err_remove_config_dt; | ||
77 | } | ||
74 | 78 | ||
75 | plat_dat->bsp_priv = dwmac; | 79 | plat_dat->bsp_priv = dwmac; |
76 | plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed; | 80 | plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed; |
77 | 81 | ||
78 | return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); | 82 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); |
83 | if (ret) | ||
84 | goto err_remove_config_dt; | ||
85 | |||
86 | return 0; | ||
87 | |||
88 | err_remove_config_dt: | ||
89 | stmmac_remove_config_dt(pdev, plat_dat); | ||
90 | |||
91 | return ret; | ||
79 | } | 92 | } |
80 | 93 | ||
81 | static const struct of_device_id meson6_dwmac_match[] = { | 94 | static const struct of_device_id meson6_dwmac_match[] = { |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c index 45e7aaf0170d..ffaed1f35efe 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | |||
@@ -264,28 +264,33 @@ static int meson8b_dwmac_probe(struct platform_device *pdev) | |||
264 | return PTR_ERR(plat_dat); | 264 | return PTR_ERR(plat_dat); |
265 | 265 | ||
266 | dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); | 266 | dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); |
267 | if (!dwmac) | 267 | if (!dwmac) { |
268 | return -ENOMEM; | 268 | ret = -ENOMEM; |
269 | goto err_remove_config_dt; | ||
270 | } | ||
269 | 271 | ||
270 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 272 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
271 | dwmac->regs = devm_ioremap_resource(&pdev->dev, res); | 273 | dwmac->regs = devm_ioremap_resource(&pdev->dev, res); |
272 | if (IS_ERR(dwmac->regs)) | 274 | if (IS_ERR(dwmac->regs)) { |
273 | return PTR_ERR(dwmac->regs); | 275 | ret = PTR_ERR(dwmac->regs); |
276 | goto err_remove_config_dt; | ||
277 | } | ||
274 | 278 | ||
275 | dwmac->pdev = pdev; | 279 | dwmac->pdev = pdev; |
276 | dwmac->phy_mode = of_get_phy_mode(pdev->dev.of_node); | 280 | dwmac->phy_mode = of_get_phy_mode(pdev->dev.of_node); |
277 | if (dwmac->phy_mode < 0) { | 281 | if (dwmac->phy_mode < 0) { |
278 | dev_err(&pdev->dev, "missing phy-mode property\n"); | 282 | dev_err(&pdev->dev, "missing phy-mode property\n"); |
279 | return -EINVAL; | 283 | ret = -EINVAL; |
284 | goto err_remove_config_dt; | ||
280 | } | 285 | } |
281 | 286 | ||
282 | ret = meson8b_init_clk(dwmac); | 287 | ret = meson8b_init_clk(dwmac); |
283 | if (ret) | 288 | if (ret) |
284 | return ret; | 289 | goto err_remove_config_dt; |
285 | 290 | ||
286 | ret = meson8b_init_prg_eth(dwmac); | 291 | ret = meson8b_init_prg_eth(dwmac); |
287 | if (ret) | 292 | if (ret) |
288 | return ret; | 293 | goto err_remove_config_dt; |
289 | 294 | ||
290 | plat_dat->bsp_priv = dwmac; | 295 | plat_dat->bsp_priv = dwmac; |
291 | 296 | ||
@@ -297,6 +302,8 @@ static int meson8b_dwmac_probe(struct platform_device *pdev) | |||
297 | 302 | ||
298 | err_clk_disable: | 303 | err_clk_disable: |
299 | clk_disable_unprepare(dwmac->m25_div_clk); | 304 | clk_disable_unprepare(dwmac->m25_div_clk); |
305 | err_remove_config_dt: | ||
306 | stmmac_remove_config_dt(pdev, plat_dat); | ||
300 | 307 | ||
301 | return ret; | 308 | return ret; |
302 | } | 309 | } |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index e7aabe56c15a..d80c88bd2bba 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | |||
@@ -981,12 +981,14 @@ static int rk_gmac_probe(struct platform_device *pdev) | |||
981 | plat_dat->resume = rk_gmac_resume; | 981 | plat_dat->resume = rk_gmac_resume; |
982 | 982 | ||
983 | plat_dat->bsp_priv = rk_gmac_setup(pdev, data); | 983 | plat_dat->bsp_priv = rk_gmac_setup(pdev, data); |
984 | if (IS_ERR(plat_dat->bsp_priv)) | 984 | if (IS_ERR(plat_dat->bsp_priv)) { |
985 | return PTR_ERR(plat_dat->bsp_priv); | 985 | ret = PTR_ERR(plat_dat->bsp_priv); |
986 | goto err_remove_config_dt; | ||
987 | } | ||
986 | 988 | ||
987 | ret = rk_gmac_init(pdev, plat_dat->bsp_priv); | 989 | ret = rk_gmac_init(pdev, plat_dat->bsp_priv); |
988 | if (ret) | 990 | if (ret) |
989 | return ret; | 991 | goto err_remove_config_dt; |
990 | 992 | ||
991 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); | 993 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); |
992 | if (ret) | 994 | if (ret) |
@@ -996,6 +998,8 @@ static int rk_gmac_probe(struct platform_device *pdev) | |||
996 | 998 | ||
997 | err_gmac_exit: | 999 | err_gmac_exit: |
998 | rk_gmac_exit(pdev, plat_dat->bsp_priv); | 1000 | rk_gmac_exit(pdev, plat_dat->bsp_priv); |
1001 | err_remove_config_dt: | ||
1002 | stmmac_remove_config_dt(pdev, plat_dat); | ||
999 | 1003 | ||
1000 | return ret; | 1004 | return ret; |
1001 | } | 1005 | } |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index 47db157da3e8..0c420e97de1e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c | |||
@@ -316,13 +316,15 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) | |||
316 | return PTR_ERR(plat_dat); | 316 | return PTR_ERR(plat_dat); |
317 | 317 | ||
318 | dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL); | 318 | dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL); |
319 | if (!dwmac) | 319 | if (!dwmac) { |
320 | return -ENOMEM; | 320 | ret = -ENOMEM; |
321 | goto err_remove_config_dt; | ||
322 | } | ||
321 | 323 | ||
322 | ret = socfpga_dwmac_parse_data(dwmac, dev); | 324 | ret = socfpga_dwmac_parse_data(dwmac, dev); |
323 | if (ret) { | 325 | if (ret) { |
324 | dev_err(dev, "Unable to parse OF data\n"); | 326 | dev_err(dev, "Unable to parse OF data\n"); |
325 | return ret; | 327 | goto err_remove_config_dt; |
326 | } | 328 | } |
327 | 329 | ||
328 | plat_dat->bsp_priv = dwmac; | 330 | plat_dat->bsp_priv = dwmac; |
@@ -330,7 +332,7 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) | |||
330 | 332 | ||
331 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); | 333 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); |
332 | if (ret) | 334 | if (ret) |
333 | return ret; | 335 | goto err_remove_config_dt; |
334 | 336 | ||
335 | ndev = platform_get_drvdata(pdev); | 337 | ndev = platform_get_drvdata(pdev); |
336 | stpriv = netdev_priv(ndev); | 338 | stpriv = netdev_priv(ndev); |
@@ -349,6 +351,8 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) | |||
349 | 351 | ||
350 | err_dvr_remove: | 352 | err_dvr_remove: |
351 | stmmac_dvr_remove(&pdev->dev); | 353 | stmmac_dvr_remove(&pdev->dev); |
354 | err_remove_config_dt: | ||
355 | stmmac_remove_config_dt(pdev, plat_dat); | ||
352 | 356 | ||
353 | return ret; | 357 | return ret; |
354 | } | 358 | } |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c index a1ce018bf844..060b98c37a85 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | |||
@@ -345,13 +345,15 @@ static int sti_dwmac_probe(struct platform_device *pdev) | |||
345 | return PTR_ERR(plat_dat); | 345 | return PTR_ERR(plat_dat); |
346 | 346 | ||
347 | dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); | 347 | dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); |
348 | if (!dwmac) | 348 | if (!dwmac) { |
349 | return -ENOMEM; | 349 | ret = -ENOMEM; |
350 | goto err_remove_config_dt; | ||
351 | } | ||
350 | 352 | ||
351 | ret = sti_dwmac_parse_data(dwmac, pdev); | 353 | ret = sti_dwmac_parse_data(dwmac, pdev); |
352 | if (ret) { | 354 | if (ret) { |
353 | dev_err(&pdev->dev, "Unable to parse OF data\n"); | 355 | dev_err(&pdev->dev, "Unable to parse OF data\n"); |
354 | return ret; | 356 | goto err_remove_config_dt; |
355 | } | 357 | } |
356 | 358 | ||
357 | dwmac->fix_retime_src = data->fix_retime_src; | 359 | dwmac->fix_retime_src = data->fix_retime_src; |
@@ -363,7 +365,7 @@ static int sti_dwmac_probe(struct platform_device *pdev) | |||
363 | 365 | ||
364 | ret = sti_dwmac_init(pdev, plat_dat->bsp_priv); | 366 | ret = sti_dwmac_init(pdev, plat_dat->bsp_priv); |
365 | if (ret) | 367 | if (ret) |
366 | return ret; | 368 | goto err_remove_config_dt; |
367 | 369 | ||
368 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); | 370 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); |
369 | if (ret) | 371 | if (ret) |
@@ -373,6 +375,8 @@ static int sti_dwmac_probe(struct platform_device *pdev) | |||
373 | 375 | ||
374 | err_dwmac_exit: | 376 | err_dwmac_exit: |
375 | sti_dwmac_exit(pdev, plat_dat->bsp_priv); | 377 | sti_dwmac_exit(pdev, plat_dat->bsp_priv); |
378 | err_remove_config_dt: | ||
379 | stmmac_remove_config_dt(pdev, plat_dat); | ||
376 | 380 | ||
377 | return ret; | 381 | return ret; |
378 | } | 382 | } |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c index e5a926b8bee7..61cb24810d10 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | |||
@@ -107,24 +107,33 @@ static int stm32_dwmac_probe(struct platform_device *pdev) | |||
107 | return PTR_ERR(plat_dat); | 107 | return PTR_ERR(plat_dat); |
108 | 108 | ||
109 | dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); | 109 | dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); |
110 | if (!dwmac) | 110 | if (!dwmac) { |
111 | return -ENOMEM; | 111 | ret = -ENOMEM; |
112 | goto err_remove_config_dt; | ||
113 | } | ||
112 | 114 | ||
113 | ret = stm32_dwmac_parse_data(dwmac, &pdev->dev); | 115 | ret = stm32_dwmac_parse_data(dwmac, &pdev->dev); |
114 | if (ret) { | 116 | if (ret) { |
115 | dev_err(&pdev->dev, "Unable to parse OF data\n"); | 117 | dev_err(&pdev->dev, "Unable to parse OF data\n"); |
116 | return ret; | 118 | goto err_remove_config_dt; |
117 | } | 119 | } |
118 | 120 | ||
119 | plat_dat->bsp_priv = dwmac; | 121 | plat_dat->bsp_priv = dwmac; |
120 | 122 | ||
121 | ret = stm32_dwmac_init(plat_dat); | 123 | ret = stm32_dwmac_init(plat_dat); |
122 | if (ret) | 124 | if (ret) |
123 | return ret; | 125 | goto err_remove_config_dt; |
124 | 126 | ||
125 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); | 127 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); |
126 | if (ret) | 128 | if (ret) |
127 | stm32_dwmac_clk_disable(dwmac); | 129 | goto err_clk_disable; |
130 | |||
131 | return 0; | ||
132 | |||
133 | err_clk_disable: | ||
134 | stm32_dwmac_clk_disable(dwmac); | ||
135 | err_remove_config_dt: | ||
136 | stmmac_remove_config_dt(pdev, plat_dat); | ||
128 | 137 | ||
129 | return ret; | 138 | return ret; |
130 | } | 139 | } |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c index adff46375a32..d07520fb969e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | |||
@@ -120,22 +120,27 @@ static int sun7i_gmac_probe(struct platform_device *pdev) | |||
120 | return PTR_ERR(plat_dat); | 120 | return PTR_ERR(plat_dat); |
121 | 121 | ||
122 | gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); | 122 | gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); |
123 | if (!gmac) | 123 | if (!gmac) { |
124 | return -ENOMEM; | 124 | ret = -ENOMEM; |
125 | goto err_remove_config_dt; | ||
126 | } | ||
125 | 127 | ||
126 | gmac->interface = of_get_phy_mode(dev->of_node); | 128 | gmac->interface = of_get_phy_mode(dev->of_node); |
127 | 129 | ||
128 | gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx"); | 130 | gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx"); |
129 | if (IS_ERR(gmac->tx_clk)) { | 131 | if (IS_ERR(gmac->tx_clk)) { |
130 | dev_err(dev, "could not get tx clock\n"); | 132 | dev_err(dev, "could not get tx clock\n"); |
131 | return PTR_ERR(gmac->tx_clk); | 133 | ret = PTR_ERR(gmac->tx_clk); |
134 | goto err_remove_config_dt; | ||
132 | } | 135 | } |
133 | 136 | ||
134 | /* Optional regulator for PHY */ | 137 | /* Optional regulator for PHY */ |
135 | gmac->regulator = devm_regulator_get_optional(dev, "phy"); | 138 | gmac->regulator = devm_regulator_get_optional(dev, "phy"); |
136 | if (IS_ERR(gmac->regulator)) { | 139 | if (IS_ERR(gmac->regulator)) { |
137 | if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) | 140 | if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) { |
138 | return -EPROBE_DEFER; | 141 | ret = -EPROBE_DEFER; |
142 | goto err_remove_config_dt; | ||
143 | } | ||
139 | dev_info(dev, "no regulator found\n"); | 144 | dev_info(dev, "no regulator found\n"); |
140 | gmac->regulator = NULL; | 145 | gmac->regulator = NULL; |
141 | } | 146 | } |
@@ -151,11 +156,18 @@ static int sun7i_gmac_probe(struct platform_device *pdev) | |||
151 | 156 | ||
152 | ret = sun7i_gmac_init(pdev, plat_dat->bsp_priv); | 157 | ret = sun7i_gmac_init(pdev, plat_dat->bsp_priv); |
153 | if (ret) | 158 | if (ret) |
154 | return ret; | 159 | goto err_remove_config_dt; |
155 | 160 | ||
156 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); | 161 | ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); |
157 | if (ret) | 162 | if (ret) |
158 | sun7i_gmac_exit(pdev, plat_dat->bsp_priv); | 163 | goto err_gmac_exit; |
164 | |||
165 | return 0; | ||
166 | |||
167 | err_gmac_exit: | ||
168 | sun7i_gmac_exit(pdev, plat_dat->bsp_priv); | ||
169 | err_remove_config_dt: | ||
170 | stmmac_remove_config_dt(pdev, plat_dat); | ||
159 | 171 | ||
160 | return ret; | 172 | return ret; |
161 | } | 173 | } |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 1f9ec02fa7f8..caf069a465f2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | |||
@@ -3416,7 +3416,6 @@ int stmmac_dvr_remove(struct device *dev) | |||
3416 | stmmac_set_mac(priv->ioaddr, false); | 3416 | stmmac_set_mac(priv->ioaddr, false); |
3417 | netif_carrier_off(ndev); | 3417 | netif_carrier_off(ndev); |
3418 | unregister_netdev(ndev); | 3418 | unregister_netdev(ndev); |
3419 | of_node_put(priv->plat->phy_node); | ||
3420 | if (priv->stmmac_rst) | 3419 | if (priv->stmmac_rst) |
3421 | reset_control_assert(priv->stmmac_rst); | 3420 | reset_control_assert(priv->stmmac_rst); |
3422 | clk_disable_unprepare(priv->pclk); | 3421 | clk_disable_unprepare(priv->pclk); |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index bcbf123d5ba2..a840818bf4df 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | |||
@@ -305,7 +305,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) | |||
305 | dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), | 305 | dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), |
306 | GFP_KERNEL); | 306 | GFP_KERNEL); |
307 | if (!dma_cfg) { | 307 | if (!dma_cfg) { |
308 | of_node_put(plat->phy_node); | 308 | stmmac_remove_config_dt(pdev, plat); |
309 | return ERR_PTR(-ENOMEM); | 309 | return ERR_PTR(-ENOMEM); |
310 | } | 310 | } |
311 | plat->dma_cfg = dma_cfg; | 311 | plat->dma_cfg = dma_cfg; |
@@ -328,14 +328,37 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) | |||
328 | 328 | ||
329 | return plat; | 329 | return plat; |
330 | } | 330 | } |
331 | |||
332 | /** | ||
333 | * stmmac_remove_config_dt - undo the effects of stmmac_probe_config_dt() | ||
334 | * @pdev: platform_device structure | ||
335 | * @plat: driver data platform structure | ||
336 | * | ||
337 | * Release resources claimed by stmmac_probe_config_dt(). | ||
338 | */ | ||
339 | void stmmac_remove_config_dt(struct platform_device *pdev, | ||
340 | struct plat_stmmacenet_data *plat) | ||
341 | { | ||
342 | struct device_node *np = pdev->dev.of_node; | ||
343 | |||
344 | if (of_phy_is_fixed_link(np)) | ||
345 | of_phy_deregister_fixed_link(np); | ||
346 | of_node_put(plat->phy_node); | ||
347 | } | ||
331 | #else | 348 | #else |
332 | struct plat_stmmacenet_data * | 349 | struct plat_stmmacenet_data * |
333 | stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) | 350 | stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) |
334 | { | 351 | { |
335 | return ERR_PTR(-ENOSYS); | 352 | return ERR_PTR(-ENOSYS); |
336 | } | 353 | } |
354 | |||
355 | void stmmac_remove_config_dt(struct platform_device *pdev, | ||
356 | struct plat_stmmacenet_data *plat) | ||
357 | { | ||
358 | } | ||
337 | #endif /* CONFIG_OF */ | 359 | #endif /* CONFIG_OF */ |
338 | EXPORT_SYMBOL_GPL(stmmac_probe_config_dt); | 360 | EXPORT_SYMBOL_GPL(stmmac_probe_config_dt); |
361 | EXPORT_SYMBOL_GPL(stmmac_remove_config_dt); | ||
339 | 362 | ||
340 | int stmmac_get_platform_resources(struct platform_device *pdev, | 363 | int stmmac_get_platform_resources(struct platform_device *pdev, |
341 | struct stmmac_resources *stmmac_res) | 364 | struct stmmac_resources *stmmac_res) |
@@ -391,10 +414,13 @@ int stmmac_pltfr_remove(struct platform_device *pdev) | |||
391 | { | 414 | { |
392 | struct net_device *ndev = platform_get_drvdata(pdev); | 415 | struct net_device *ndev = platform_get_drvdata(pdev); |
393 | struct stmmac_priv *priv = netdev_priv(ndev); | 416 | struct stmmac_priv *priv = netdev_priv(ndev); |
417 | struct plat_stmmacenet_data *plat = priv->plat; | ||
394 | int ret = stmmac_dvr_remove(&pdev->dev); | 418 | int ret = stmmac_dvr_remove(&pdev->dev); |
395 | 419 | ||
396 | if (priv->plat->exit) | 420 | if (plat->exit) |
397 | priv->plat->exit(pdev, priv->plat->bsp_priv); | 421 | plat->exit(pdev, plat->bsp_priv); |
422 | |||
423 | stmmac_remove_config_dt(pdev, plat); | ||
398 | 424 | ||
399 | return ret; | 425 | return ret; |
400 | } | 426 | } |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h index 64e147f53a9c..b72eb0de57b7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h | |||
@@ -23,6 +23,8 @@ | |||
23 | 23 | ||
24 | struct plat_stmmacenet_data * | 24 | struct plat_stmmacenet_data * |
25 | stmmac_probe_config_dt(struct platform_device *pdev, const char **mac); | 25 | stmmac_probe_config_dt(struct platform_device *pdev, const char **mac); |
26 | void stmmac_remove_config_dt(struct platform_device *pdev, | ||
27 | struct plat_stmmacenet_data *plat); | ||
26 | 28 | ||
27 | int stmmac_get_platform_resources(struct platform_device *pdev, | 29 | int stmmac_get_platform_resources(struct platform_device *pdev, |
28 | struct stmmac_resources *stmmac_res); | 30 | struct stmmac_resources *stmmac_res); |