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);
 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;
 }
 
                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,
        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);
 
        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);
 
        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[] = {
 
        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) {
                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[] = {
 
                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[] = {
 
                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;
 
 
 err_clk_disable:
        clk_disable_unprepare(dwmac->m25_div_clk);
+err_remove_config_dt:
+       stmmac_remove_config_dt(pdev, plat_dat);
 
        return ret;
 }
 
        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)
 
 err_gmac_exit:
        rk_gmac_exit(pdev, plat_dat->bsp_priv);
+err_remove_config_dt:
+       stmmac_remove_config_dt(pdev, plat_dat);
 
        return ret;
 }
 
                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;
 
        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);
 
 err_dvr_remove:
        stmmac_dvr_remove(&pdev->dev);
+err_remove_config_dt:
+       stmmac_remove_config_dt(pdev, plat_dat);
 
        return ret;
 }
 
                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;
 
        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)
 
 err_dwmac_exit:
        sti_dwmac_exit(pdev, plat_dat->bsp_priv);
+err_remove_config_dt:
+       stmmac_remove_config_dt(pdev, plat_dat);
 
        return ret;
 }
 
                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;
 }
 
                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;
        }
 
        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;
 }
 
        stmmac_set_mac(priv->ioaddr, false);
        netif_carrier_off(ndev);
        unregister_netdev(ndev);
-       of_node_put(priv->plat->phy_node);
        if (priv->stmmac_rst)
                reset_control_assert(priv->stmmac_rst);
        clk_disable_unprepare(priv->pclk);
 
                dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
                                       GFP_KERNEL);
                if (!dma_cfg) {
-                       of_node_put(plat->phy_node);
+                       stmmac_remove_config_dt(pdev, plat);
                        return ERR_PTR(-ENOMEM);
                }
                plat->dma_cfg = dma_cfg;
 
        return plat;
 }
+
+/**
+ * stmmac_remove_config_dt - undo the effects of stmmac_probe_config_dt()
+ * @pdev: platform_device structure
+ * @plat: driver data platform structure
+ *
+ * Release resources claimed by stmmac_probe_config_dt().
+ */
+void stmmac_remove_config_dt(struct platform_device *pdev,
+                            struct plat_stmmacenet_data *plat)
+{
+       struct device_node *np = pdev->dev.of_node;
+
+       if (of_phy_is_fixed_link(np))
+               of_phy_deregister_fixed_link(np);
+       of_node_put(plat->phy_node);
+}
 #else
 struct plat_stmmacenet_data *
 stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
 {
        return ERR_PTR(-ENOSYS);
 }
+
+void stmmac_remove_config_dt(struct platform_device *pdev,
+                            struct plat_stmmacenet_data *plat)
+{
+}
 #endif /* CONFIG_OF */
 EXPORT_SYMBOL_GPL(stmmac_probe_config_dt);
+EXPORT_SYMBOL_GPL(stmmac_remove_config_dt);
 
 int stmmac_get_platform_resources(struct platform_device *pdev,
                                  struct stmmac_resources *stmmac_res)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct stmmac_priv *priv = netdev_priv(ndev);
+       struct plat_stmmacenet_data *plat = priv->plat;
        int ret = stmmac_dvr_remove(&pdev->dev);
 
-       if (priv->plat->exit)
-               priv->plat->exit(pdev, priv->plat->bsp_priv);
+       if (plat->exit)
+               plat->exit(pdev, plat->bsp_priv);
+
+       stmmac_remove_config_dt(pdev, plat);
 
        return ret;
 }
 
 
 struct plat_stmmacenet_data *
 stmmac_probe_config_dt(struct platform_device *pdev, const char **mac);
+void stmmac_remove_config_dt(struct platform_device *pdev,
+                            struct plat_stmmacenet_data *plat);
 
 int stmmac_get_platform_resources(struct platform_device *pdev,
                                  struct stmmac_resources *stmmac_res);