History

Merge branch 'stmmac-probe-error-handling-and-phydev-leaks'

Johan Hovold says: ==================== net: stmmac: fix probe error handling and phydev leaks This series fixes a number of issues with the stmmac-driver probe error handling, which for example left clocks enabled after probe failures. The final patch fixes a failure to deregister and free any fixed-link PHYs that were registered during probe on probe errors and on driver unbind. It also fixes a related of-node leak on late probe errors. This series depends on the of_phy_deregister_fixed_link() helper that was just merged to net. As mentioned earlier, one staging driver also suffers from a similar leak and can be fixed up once the above mentioned helper hits mainline. Note that these patches have only been compile tested. ====================

David S. Miller committed 9 years ago

Commit d262fd12 parents 6919756 d2ed0a713 files · +215 −63Browse files

Unified · Split

13 files
  1. drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c +15 −2
  2. drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c +19 −6
  3. drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c +14 −3
  4. drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c +18 −5
  5. drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c +24 −8
  6. drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +17 −4
  7. drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +26 −13
  8. drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +18 −5
  9. drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c +14 −5
  10. drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c +19 −7
  11. drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0 −1
  12. drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +29 −4
  13. drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h +2 −0
drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c+15−2
@@ -50,10 +50,23 @@ static int dwmac_generic_probe(struct platform_device *pdev) · 49 unmodified lines
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 return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);56 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
57 if (ret)
58 goto err_exit;
59
60 return 0;
61
62err_exit:
63 if (plat_dat->exit)
64 plat_dat->exit(pdev, plat_dat->bsp_priv);
65err_remove_config_dt:
66 if (pdev->dev.of_node)
67 stmmac_remove_config_dt(pdev, plat_dat);
68
69 return ret;
57}70}
58 71
59static const struct of_device_id dwmac_generic_match[] = {72static const struct of_device_id dwmac_generic_match[] = {
drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c+19−6
@@ -271,15 +271,17 @@ static int ipq806x_gmac_probe(struct platform_device *pdev) · 270 unmodified lines
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) · 14 unmodified lines
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) · 12 unmodified lines
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) · 20 unmodified lines
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
359err_remove_config_dt:
360 stmmac_remove_config_dt(pdev, plat_dat);
361
362 return err;
350}363}
351 364
352static const struct of_device_id ipq806x_gmac_dwmac_match[] = {365static const struct of_device_id ipq806x_gmac_dwmac_match[] = {
drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c+14−3
@@ -46,7 +46,8 @@ static int lpc18xx_dwmac_probe(struct platform_device *pdev) · 45 unmodified lines
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) · 2 unmodified lines
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
72err_remove_config_dt:
73 stmmac_remove_config_dt(pdev, plat_dat);
74
75 return ret;
65}76}
66 77
67static const struct of_device_id lpc18xx_dwmac_match[] = {78static const struct of_device_id lpc18xx_dwmac_match[] = {
drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c+18−5
@@ -64,18 +64,31 @@ static int meson6_dwmac_probe(struct platform_device *pdev) · 63 unmodified lines
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
88err_remove_config_dt:
89 stmmac_remove_config_dt(pdev, plat_dat);
90
91 return ret;
79}92}
80 93
81static const struct of_device_id meson6_dwmac_match[] = {94static const struct of_device_id meson6_dwmac_match[] = {
drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c+24−8
@@ -264,32 +264,48 @@ static int meson8b_dwmac_probe(struct platform_device *pdev) · 263 unmodified lines
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
292 return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);297 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
298 if (ret)
299 goto err_clk_disable;
300
301 return 0;
302
303err_clk_disable:
304 clk_disable_unprepare(dwmac->m25_div_clk);
305err_remove_config_dt:
306 stmmac_remove_config_dt(pdev, plat_dat);
307
308 return ret;
293}309}
294 310
295static int meson8b_dwmac_remove(struct platform_device *pdev)311static int meson8b_dwmac_remove(struct platform_device *pdev)
drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c+17−4
@@ -981,14 +981,27 @@ static int rk_gmac_probe(struct platform_device *pdev) · 980 unmodified lines
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;
992
993 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
994 if (ret)
995 goto err_gmac_exit;
996
997 return 0;
998
999err_gmac_exit:
1000 rk_gmac_exit(pdev, plat_dat->bsp_priv);
1001err_remove_config_dt:
1002 stmmac_remove_config_dt(pdev, plat_dat);
990 1003
991 return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);1004 return ret;
992}1005}
993 1006
994static const struct of_device_id rk_gmac_dwmac_match[] = {1007static const struct of_device_id rk_gmac_dwmac_match[] = {
drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c+26−13
@@ -304,6 +304,8 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) · 303 unmodified lines
304 struct device *dev = &pdev->dev;304 struct device *dev = &pdev->dev;
305 int ret;305 int ret;
306 struct socfpga_dwmac *dwmac;306 struct socfpga_dwmac *dwmac;
307 struct net_device *ndev;
308 struct stmmac_priv *stpriv;
307 309
308 ret = stmmac_get_platform_resources(pdev, &stmmac_res);310 ret = stmmac_get_platform_resources(pdev, &stmmac_res);
309 if (ret)311 if (ret)
@@ -314,32 +316,43 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) · 4 unmodified lines
314 return PTR_ERR(plat_dat);316 return PTR_ERR(plat_dat);
315 317
316 dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);318 dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);
317 if (!dwmac)319 if (!dwmac) {
318 return -ENOMEM;320 ret = -ENOMEM;
321 goto err_remove_config_dt;
322 }
319 323
320 ret = socfpga_dwmac_parse_data(dwmac, dev);324 ret = socfpga_dwmac_parse_data(dwmac, dev);
321 if (ret) {325 if (ret) {
322 dev_err(dev, "Unable to parse OF data\n");326 dev_err(dev, "Unable to parse OF data\n");
323 return ret;327 goto err_remove_config_dt;
324 }328 }
325 329
326 plat_dat->bsp_priv = dwmac;330 plat_dat->bsp_priv = dwmac;
327 plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed;331 plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed;
328 332
329 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);333 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
334 if (ret)
335 goto err_remove_config_dt;
330 336
331 if (!ret) {337 ndev = platform_get_drvdata(pdev);
332 struct net_device *ndev = platform_get_drvdata(pdev);338 stpriv = netdev_priv(ndev);
333 struct stmmac_priv *stpriv = netdev_priv(ndev);
334 339
335 /* The socfpga driver needs to control the stmmac reset to340 /* The socfpga driver needs to control the stmmac reset to set the phy
336 * set the phy mode. Create a copy of the core reset handel341 * mode. Create a copy of the core reset handle so it can be used by
337 * so it can be used by the driver later.342 * the driver later.
338 */343 */
339 dwmac->stmmac_rst = stpriv->stmmac_rst;344 dwmac->stmmac_rst = stpriv->stmmac_rst;
340 345
341 ret = socfpga_dwmac_set_phy_mode(dwmac);346 ret = socfpga_dwmac_set_phy_mode(dwmac);
342 }347 if (ret)
348 goto err_dvr_remove;
349
350 return 0;
351
352err_dvr_remove:
353 stmmac_dvr_remove(&pdev->dev);
354err_remove_config_dt:
355 stmmac_remove_config_dt(pdev, plat_dat);
343 356
344 return ret;357 return ret;
345}358}
drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c+18−5
@@ -345,13 +345,15 @@ static int sti_dwmac_probe(struct platform_device *pdev) · 344 unmodified lines
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,9 +365,20 @@ static int sti_dwmac_probe(struct platform_device *pdev) · 5 unmodified lines
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;
369
370 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
371 if (ret)
372 goto err_dwmac_exit;
373
374 return 0;
375
376err_dwmac_exit:
377 sti_dwmac_exit(pdev, plat_dat->bsp_priv);
378err_remove_config_dt:
379 stmmac_remove_config_dt(pdev, plat_dat);
367 380
368 return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);381 return ret;
369}382}
370 383
371static const struct sti_dwmac_of_data stih4xx_dwmac_data = {384static const struct sti_dwmac_of_data stih4xx_dwmac_data = {
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c+14−5
@@ -107,24 +107,33 @@ static int stm32_dwmac_probe(struct platform_device *pdev) · 106 unmodified lines
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
133err_clk_disable:
134 stm32_dwmac_clk_disable(dwmac);
135err_remove_config_dt:
136 stmmac_remove_config_dt(pdev, plat_dat);
128 137
129 return ret;138 return ret;
130}139}
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c+19−7
@@ -120,22 +120,27 @@ static int sun7i_gmac_probe(struct platform_device *pdev) · 119 unmodified lines
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) · 9 unmodified lines
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
167err_gmac_exit:
168 sun7i_gmac_exit(pdev, plat_dat->bsp_priv);
169err_remove_config_dt:
170 stmmac_remove_config_dt(pdev, plat_dat);
159 171
160 return ret;172 return ret;
161}173}
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c+0−1
@@ -3416,7 +3416,6 @@ int stmmac_dvr_remove(struct device *dev) · 3415 unmodified lines
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);
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c+29−4
@@ -200,7 +200,6 @@ static int stmmac_dt_phy(struct plat_stmmacenet_data *plat, · 199 unmodified lines
200/**200/**
201 * stmmac_probe_config_dt - parse device-tree driver parameters201 * stmmac_probe_config_dt - parse device-tree driver parameters
202 * @pdev: platform_device structure202 * @pdev: platform_device structure
203 * @plat: driver data platform structure
204 * @mac: MAC address to use203 * @mac: MAC address to use
205 * Description:204 * Description:
206 * this function is to read the driver parameters from device-tree and205 * this function is to read the driver parameters from device-tree and
@@ -306,7 +305,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) · 99 unmodified lines
306 dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),305 dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
307 GFP_KERNEL);306 GFP_KERNEL);
308 if (!dma_cfg) {307 if (!dma_cfg) {
309 of_node_put(plat->phy_node);308 stmmac_remove_config_dt(pdev, plat);
310 return ERR_PTR(-ENOMEM);309 return ERR_PTR(-ENOMEM);
311 }310 }
312 plat->dma_cfg = dma_cfg;311 plat->dma_cfg = dma_cfg;
@@ -329,14 +328,37 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) · 16 unmodified lines
329 328
330 return plat;329 return plat;
331}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 */
339void 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}
332#else348#else
333struct plat_stmmacenet_data *349struct plat_stmmacenet_data *
334stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)350stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
335{351{
336 return ERR_PTR(-ENOSYS);352 return ERR_PTR(-ENOSYS);
337}353}
354
355void stmmac_remove_config_dt(struct platform_device *pdev,
356 struct plat_stmmacenet_data *plat)
357{
358}
338#endif /* CONFIG_OF */359#endif /* CONFIG_OF */
339EXPORT_SYMBOL_GPL(stmmac_probe_config_dt);360EXPORT_SYMBOL_GPL(stmmac_probe_config_dt);
361EXPORT_SYMBOL_GPL(stmmac_remove_config_dt);
340 362
341int stmmac_get_platform_resources(struct platform_device *pdev,363int stmmac_get_platform_resources(struct platform_device *pdev,
342 struct stmmac_resources *stmmac_res)364 struct stmmac_resources *stmmac_res)
@@ -392,10 +414,13 @@ int stmmac_pltfr_remove(struct platform_device *pdev) · 49 unmodified lines
392{414{
393 struct net_device *ndev = platform_get_drvdata(pdev);415 struct net_device *ndev = platform_get_drvdata(pdev);
394 struct stmmac_priv *priv = netdev_priv(ndev);416 struct stmmac_priv *priv = netdev_priv(ndev);
417 struct plat_stmmacenet_data *plat = priv->plat;
395 int ret = stmmac_dvr_remove(&pdev->dev);418 int ret = stmmac_dvr_remove(&pdev->dev);
396 419
397 if (priv->plat->exit)420 if (plat->exit)
398 priv->plat->exit(pdev, priv->plat->bsp_priv);421 plat->exit(pdev, plat->bsp_priv);
422
423 stmmac_remove_config_dt(pdev, plat);
399 424
400 return ret;425 return ret;
401}426}
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h+2−0
@@ -23,6 +23,8 @@ · 22 unmodified lines
23 23
24struct plat_stmmacenet_data *24struct plat_stmmacenet_data *
25stmmac_probe_config_dt(struct platform_device *pdev, const char **mac);25stmmac_probe_config_dt(struct platform_device *pdev, const char **mac);
26void stmmac_remove_config_dt(struct platform_device *pdev,
27 struct plat_stmmacenet_data *plat);
26 28
27int stmmac_get_platform_resources(struct platform_device *pdev,29int stmmac_get_platform_resources(struct platform_device *pdev,
28 struct stmmac_resources *stmmac_res);30 struct stmmac_resources *stmmac_res);