net: stmmac: restructure the error path of stmmac_probe_config_dt()

[ Upstream commit 2b6ffcd7873b7e8a62c3e15a6f305bfc747c466b ]

Current implementation of stmmac_probe_config_dt() does not release the
OF node reference obtained by of_parse_phandle() in some error paths.
The problem is that some error paths call stmmac_remove_config_dt() to
clean up but others use and unwind ladder.  These two types of error
handling have not kept in sync and have been a recurring source of bugs.
Re-write the error handling in stmmac_probe_config_dt() to use an unwind
ladder. Consequently, stmmac_remove_config_dt() is not needed anymore,
thus remove it.

This bug was found by an experimental verification tool that I am
developing.

Fixes: 4838a54050 ("net: stmmac: Fix wrapper drivers not detecting PHY")
Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
Link: https://patch.msgid.link/20241219024119.2017012-1-joe@pf.is.s.u-tokyo.ac.jp
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Joe Hattori
2024-12-19 11:41:19 +09:00
committed by Greg Kroah-Hartman
parent 51c8cfd00e
commit 28f1e04d91

View File

@@ -473,8 +473,10 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n"); dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
rc = stmmac_mdio_setup(plat, np, &pdev->dev); rc = stmmac_mdio_setup(plat, np, &pdev->dev);
if (rc) if (rc) {
return ERR_PTR(rc); ret = ERR_PTR(rc);
goto error_put_phy;
}
of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size); of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size);
@@ -560,8 +562,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
GFP_KERNEL); GFP_KERNEL);
if (!dma_cfg) { if (!dma_cfg) {
stmmac_remove_config_dt(pdev, plat); ret = ERR_PTR(-ENOMEM);
return ERR_PTR(-ENOMEM); goto error_put_mdio;
} }
plat->dma_cfg = dma_cfg; plat->dma_cfg = dma_cfg;
@@ -589,8 +591,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
rc = stmmac_mtl_setup(pdev, plat); rc = stmmac_mtl_setup(pdev, plat);
if (rc) { if (rc) {
stmmac_remove_config_dt(pdev, plat); ret = ERR_PTR(rc);
return ERR_PTR(rc); goto error_put_mdio;
} }
/* clock setup */ /* clock setup */
@@ -642,6 +644,10 @@ error_hw_init:
clk_disable_unprepare(plat->pclk); clk_disable_unprepare(plat->pclk);
error_pclk_get: error_pclk_get:
clk_disable_unprepare(plat->stmmac_clk); clk_disable_unprepare(plat->stmmac_clk);
error_put_mdio:
of_node_put(plat->mdio_node);
error_put_phy:
of_node_put(plat->phy_node);
return ret; return ret;
} }
@@ -650,16 +656,17 @@ static void devm_stmmac_remove_config_dt(void *data)
{ {
struct plat_stmmacenet_data *plat = data; struct plat_stmmacenet_data *plat = data;
/* Platform data argument is unused */ clk_disable_unprepare(plat->stmmac_clk);
stmmac_remove_config_dt(NULL, plat); clk_disable_unprepare(plat->pclk);
of_node_put(plat->mdio_node);
of_node_put(plat->phy_node);
} }
/** /**
* devm_stmmac_probe_config_dt * devm_stmmac_probe_config_dt
* @pdev: platform_device structure * @pdev: platform_device structure
* @mac: MAC address to use * @mac: MAC address to use
* Description: Devres variant of stmmac_probe_config_dt(). Does not require * Description: Devres variant of stmmac_probe_config_dt().
* the user to call stmmac_remove_config_dt() at driver detach.
*/ */
struct plat_stmmacenet_data * struct plat_stmmacenet_data *
devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)