mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
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:
committed by
Greg Kroah-Hartman
parent
51c8cfd00e
commit
28f1e04d91
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user