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
5050 if (plat_dat->init) {
5151 ret = plat_dat->init(pdev, plat_dat->bsp_priv);
5252 if (ret)
53− return ret;
53+ goto err_remove_config_dt;
5454 }
5555
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+
62+err_exit:
63+ if (plat_dat->exit)
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);
68+
69+ return ret;
5770 }
5871
5972 static 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
271271 return PTR_ERR(plat_dat);
272272
273273 gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
274− if (!gmac)
275− return -ENOMEM;
274+ if (!gmac) {
275+ err = -ENOMEM;
276+ goto err_remove_config_dt;
277+ }
276278
277279 gmac->pdev = pdev;
278280
279281 err = ipq806x_gmac_of_parse(gmac);
280282 if (err) {
281283 dev_err(dev, "device tree parsing error\n");
282− return err;
284+ goto err_remove_config_dt;
283285 }
284286
285287 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
300302 default:
301303 dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
302304 phy_modes(gmac->phy_mode));
303− return -EINVAL;
305+ err = -EINVAL;
306+ goto err_remove_config_dt;
304307 }
305308 regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val);
306309
@@ -319,7 +322,8 @@ static int ipq806x_gmac_probe(struct platform_device *pdev) · 12 unmodified lines
319322 default:
320323 dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
321324 phy_modes(gmac->phy_mode));
322− return -EINVAL;
325+ err = -EINVAL;
326+ goto err_remove_config_dt;
323327 }
324328 regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val);
325329
@@ -346,7 +350,16 @@ static int ipq806x_gmac_probe(struct platform_device *pdev) · 20 unmodified lines
346350 plat_dat->bsp_priv = gmac;
347351 plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed;
348352
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;
350363 }
351364
352365 static 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
4646 reg = syscon_regmap_lookup_by_compatible("nxp,lpc1850-creg");
4747 if (IS_ERR(reg)) {
4848 dev_err(&pdev->dev, "syscon lookup failed\n");
49− return PTR_ERR(reg);
49+ ret = PTR_ERR(reg);
50+ goto err_remove_config_dt;
5051 }
5152
5253 if (plat_dat->interface == PHY_INTERFACE_MODE_MII) {
@@ -55,13 +56,23 @@ static int lpc18xx_dwmac_probe(struct platform_device *pdev) · 2 unmodified lines
5556 ethmode = LPC18XX_CREG_CREG6_ETHMODE_RMII;
5657 } else {
5758 dev_err(&pdev->dev, "Only MII and RMII mode supported\n");
58− return -EINVAL;
59+ ret = -EINVAL;
60+ goto err_remove_config_dt;
5961 }
6062
6163 regmap_update_bits(reg, LPC18XX_CREG_CREG6,
6264 LPC18XX_CREG_CREG6_ETHMODE_MASK, ethmode);
6365
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;
6576 }
6677
6778 static 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
6464 return PTR_ERR(plat_dat);
6565
6666 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
67− if (!dwmac)
68− return -ENOMEM;
67+ if (!dwmac) {
68+ ret = -ENOMEM;
69+ goto err_remove_config_dt;
70+ }
6971
7072 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
7173 dwmac->reg = devm_ioremap_resource(&pdev->dev, res);
72− if (IS_ERR(dwmac->reg))
73− return PTR_ERR(dwmac->reg);
74+ if (IS_ERR(dwmac->reg)) {
75+ ret = PTR_ERR(dwmac->reg);
76+ goto err_remove_config_dt;
77+ }
7478
7579 plat_dat->bsp_priv = dwmac;
7680 plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed;
7781
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;
7992 }
8093
8194 static 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
264264 return PTR_ERR(plat_dat);
265265
266266 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
267− if (!dwmac)
268− return -ENOMEM;
267+ if (!dwmac) {
268+ ret = -ENOMEM;
269+ goto err_remove_config_dt;
270+ }
269271
270272 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
271273 dwmac->regs = devm_ioremap_resource(&pdev->dev, res);
272− if (IS_ERR(dwmac->regs))
273− return PTR_ERR(dwmac->regs);
274+ if (IS_ERR(dwmac->regs)) {
275+ ret = PTR_ERR(dwmac->regs);
276+ goto err_remove_config_dt;
277+ }
274278
275279 dwmac->pdev = pdev;
276280 dwmac->phy_mode = of_get_phy_mode(pdev->dev.of_node);
277281 if (dwmac->phy_mode < 0) {
278282 dev_err(&pdev->dev, "missing phy-mode property\n");
279− return -EINVAL;
283+ ret = -EINVAL;
284+ goto err_remove_config_dt;
280285 }
281286
282287 ret = meson8b_init_clk(dwmac);
283288 if (ret)
284− return ret;
289+ goto err_remove_config_dt;
285290
286291 ret = meson8b_init_prg_eth(dwmac);
287292 if (ret)
288− return ret;
293+ goto err_remove_config_dt;
289294
290295 plat_dat->bsp_priv = dwmac;
291296
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+
303+err_clk_disable:
304+ clk_disable_unprepare(dwmac->m25_div_clk);
305+err_remove_config_dt:
306+ stmmac_remove_config_dt(pdev, plat_dat);
307+
308+ return ret;
293309 }
294310
295311 static 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
981981 plat_dat->resume = rk_gmac_resume;
982982
983983 plat_dat->bsp_priv = rk_gmac_setup(pdev, data);
984− if (IS_ERR(plat_dat->bsp_priv))
985− return PTR_ERR(plat_dat->bsp_priv);
984+ if (IS_ERR(plat_dat->bsp_priv)) {
985+ ret = PTR_ERR(plat_dat->bsp_priv);
986+ goto err_remove_config_dt;
987+ }
986988
987989 ret = rk_gmac_init(pdev, plat_dat->bsp_priv);
988990 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+
999+err_gmac_exit:
1000+ rk_gmac_exit(pdev, plat_dat->bsp_priv);
1001+err_remove_config_dt:
1002+ stmmac_remove_config_dt(pdev, plat_dat);
9901003
991− return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
1004+ return ret;
9921005 }
9931006
9941007 static 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
304304 struct device *dev = &pdev->dev;
305305 int ret;
306306 struct socfpga_dwmac *dwmac;
307+ struct net_device *ndev;
308+ struct stmmac_priv *stpriv;
307309
308310 ret = stmmac_get_platform_resources(pdev, &stmmac_res);
309311 if (ret)
@@ -314,32 +316,43 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) · 4 unmodified lines
314316 return PTR_ERR(plat_dat);
315317
316318 dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);
317− if (!dwmac)
318− return -ENOMEM;
319+ if (!dwmac) {
320+ ret = -ENOMEM;
321+ goto err_remove_config_dt;
322+ }
319323
320324 ret = socfpga_dwmac_parse_data(dwmac, dev);
321325 if (ret) {
322326 dev_err(dev, "Unable to parse OF data\n");
323− return ret;
327+ goto err_remove_config_dt;
324328 }
325329
326330 plat_dat->bsp_priv = dwmac;
327331 plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed;
328332
329333 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
334+ if (ret)
335+ goto err_remove_config_dt;
330336
331− if (!ret) {
332− struct net_device *ndev = platform_get_drvdata(pdev);
333− struct stmmac_priv *stpriv = netdev_priv(ndev);
337+ ndev = platform_get_drvdata(pdev);
338+ stpriv = netdev_priv(ndev);
334339
335− /* The socfpga driver needs to control the stmmac reset to
336− * set the phy mode. Create a copy of the core reset handel
337− * so it can be used by the driver later.
338− */
339− dwmac->stmmac_rst = stpriv->stmmac_rst;
340+ /* The socfpga driver needs to control the stmmac reset to set the phy
341+ * mode. Create a copy of the core reset handle so it can be used by
342+ * the driver later.
343+ */
344+ dwmac->stmmac_rst = stpriv->stmmac_rst;
340345
341− ret = socfpga_dwmac_set_phy_mode(dwmac);
342− }
346+ ret = socfpga_dwmac_set_phy_mode(dwmac);
347+ if (ret)
348+ goto err_dvr_remove;
349+
350+ return 0;
351+
352+err_dvr_remove:
353+ stmmac_dvr_remove(&pdev->dev);
354+err_remove_config_dt:
355+ stmmac_remove_config_dt(pdev, plat_dat);
343356
344357 return ret;
345358 }
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
345345 return PTR_ERR(plat_dat);
346346
347347 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
348− if (!dwmac)
349− return -ENOMEM;
348+ if (!dwmac) {
349+ ret = -ENOMEM;
350+ goto err_remove_config_dt;
351+ }
350352
351353 ret = sti_dwmac_parse_data(dwmac, pdev);
352354 if (ret) {
353355 dev_err(&pdev->dev, "Unable to parse OF data\n");
354− return ret;
356+ goto err_remove_config_dt;
355357 }
356358
357359 dwmac->fix_retime_src = data->fix_retime_src;
@@ -363,9 +365,20 @@ static int sti_dwmac_probe(struct platform_device *pdev) · 5 unmodified lines
363365
364366 ret = sti_dwmac_init(pdev, plat_dat->bsp_priv);
365367 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+
376+err_dwmac_exit:
377+ sti_dwmac_exit(pdev, plat_dat->bsp_priv);
378+err_remove_config_dt:
379+ stmmac_remove_config_dt(pdev, plat_dat);
367380
368− return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
381+ return ret;
369382 }
370383
371384 static 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
107107 return PTR_ERR(plat_dat);
108108
109109 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
110− if (!dwmac)
111− return -ENOMEM;
110+ if (!dwmac) {
111+ ret = -ENOMEM;
112+ goto err_remove_config_dt;
113+ }
112114
113115 ret = stm32_dwmac_parse_data(dwmac, &pdev->dev);
114116 if (ret) {
115117 dev_err(&pdev->dev, "Unable to parse OF data\n");
116− return ret;
118+ goto err_remove_config_dt;
117119 }
118120
119121 plat_dat->bsp_priv = dwmac;
120122
121123 ret = stm32_dwmac_init(plat_dat);
122124 if (ret)
123− return ret;
125+ goto err_remove_config_dt;
124126
125127 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
126128 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);
128137
129138 return ret;
130139 }
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
120120 return PTR_ERR(plat_dat);
121121
122122 gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
123− if (!gmac)
124− return -ENOMEM;
123+ if (!gmac) {
124+ ret = -ENOMEM;
125+ goto err_remove_config_dt;
126+ }
125127
126128 gmac->interface = of_get_phy_mode(dev->of_node);
127129
128130 gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
129131 if (IS_ERR(gmac->tx_clk)) {
130132 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;
132135 }
133136
134137 /* Optional regulator for PHY */
135138 gmac->regulator = devm_regulator_get_optional(dev, "phy");
136139 if (IS_ERR(gmac->regulator)) {
137− if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER)
138− return -EPROBE_DEFER;
140+ if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) {
141+ ret = -EPROBE_DEFER;
142+ goto err_remove_config_dt;
143+ }
139144 dev_info(dev, "no regulator found\n");
140145 gmac->regulator = NULL;
141146 }
@@ -151,11 +156,18 @@ static int sun7i_gmac_probe(struct platform_device *pdev) · 9 unmodified lines
151156
152157 ret = sun7i_gmac_init(pdev, plat_dat->bsp_priv);
153158 if (ret)
154− return ret;
159+ goto err_remove_config_dt;
155160
156161 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
157162 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);
159171
160172 return ret;
161173 }
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c+0−1
@@ -3416,7 +3416,6 @@ int stmmac_dvr_remove(struct device *dev) · 3415 unmodified lines
34163416 stmmac_set_mac(priv->ioaddr, false);
34173417 netif_carrier_off(ndev);
34183418 unregister_netdev(ndev);
3419− of_node_put(priv->plat->phy_node);
34203419 if (priv->stmmac_rst)
34213420 reset_control_assert(priv->stmmac_rst);
34223421 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
200200 /**
201201 * stmmac_probe_config_dt - parse device-tree driver parameters
202202 * @pdev: platform_device structure
203− * @plat: driver data platform structure
204203 * @mac: MAC address to use
205204 * Description:
206205 * 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
306305 dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
307306 GFP_KERNEL);
308307 if (!dma_cfg) {
309− of_node_put(plat->phy_node);
308+ stmmac_remove_config_dt(pdev, plat);
310309 return ERR_PTR(-ENOMEM);
311310 }
312311 plat->dma_cfg = dma_cfg;
@@ -329,14 +328,37 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) · 16 unmodified lines
329328
330329 return plat;
331330 }
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+}
332348 #else
333349 struct plat_stmmacenet_data *
334350 stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
335351 {
336352 return ERR_PTR(-ENOSYS);
337353 }
354+
355+void stmmac_remove_config_dt(struct platform_device *pdev,
356+ struct plat_stmmacenet_data *plat)
357+{
358+}
338359 #endif /* CONFIG_OF */
339360 EXPORT_SYMBOL_GPL(stmmac_probe_config_dt);
361+EXPORT_SYMBOL_GPL(stmmac_remove_config_dt);
340362
341363 int stmmac_get_platform_resources(struct platform_device *pdev,
342364 struct stmmac_resources *stmmac_res)
@@ -392,10 +414,13 @@ int stmmac_pltfr_remove(struct platform_device *pdev) · 49 unmodified lines
392414 {
393415 struct net_device *ndev = platform_get_drvdata(pdev);
394416 struct stmmac_priv *priv = netdev_priv(ndev);
417+ struct plat_stmmacenet_data *plat = priv->plat;
395418 int ret = stmmac_dvr_remove(&pdev->dev);
396419
397− if (priv->plat->exit)
398− priv->plat->exit(pdev, priv->plat->bsp_priv);
420+ if (plat->exit)
421+ plat->exit(pdev, plat->bsp_priv);
422+
423+ stmmac_remove_config_dt(pdev, plat);
399424
400425 return ret;
401426 }
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h+2−0
@@ -23,6 +23,8 @@ · 22 unmodified lines
2323
2424 struct plat_stmmacenet_data *
2525 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);
2628
2729 int stmmac_get_platform_resources(struct platform_device *pdev,
2830 struct stmmac_resources *stmmac_res);