mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 09:01:36 -04:00
net: stmmac: restructure the error path of stmmac_probe_config_dt()
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>
This commit is contained in:
committed by
Jakub Kicinski
parent
a072ffd896
commit
2b6ffcd787
@@ -405,22 +405,6 @@ static int stmmac_of_get_mac_mode(struct device_node *np)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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().
|
||||
*/
|
||||
static void stmmac_remove_config_dt(struct platform_device *pdev,
|
||||
struct plat_stmmacenet_data *plat)
|
||||
{
|
||||
clk_disable_unprepare(plat->stmmac_clk);
|
||||
clk_disable_unprepare(plat->pclk);
|
||||
of_node_put(plat->phy_node);
|
||||
of_node_put(plat->mdio_node);
|
||||
}
|
||||
|
||||
/**
|
||||
* stmmac_probe_config_dt - parse device-tree driver parameters
|
||||
* @pdev: platform_device structure
|
||||
@@ -490,8 +474,10 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
|
||||
dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
|
||||
|
||||
rc = stmmac_mdio_setup(plat, np, &pdev->dev);
|
||||
if (rc)
|
||||
return ERR_PTR(rc);
|
||||
if (rc) {
|
||||
ret = ERR_PTR(rc);
|
||||
goto error_put_phy;
|
||||
}
|
||||
|
||||
of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size);
|
||||
|
||||
@@ -581,8 +567,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
|
||||
dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
|
||||
GFP_KERNEL);
|
||||
if (!dma_cfg) {
|
||||
stmmac_remove_config_dt(pdev, plat);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
ret = ERR_PTR(-ENOMEM);
|
||||
goto error_put_mdio;
|
||||
}
|
||||
plat->dma_cfg = dma_cfg;
|
||||
|
||||
@@ -610,8 +596,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
|
||||
|
||||
rc = stmmac_mtl_setup(pdev, plat);
|
||||
if (rc) {
|
||||
stmmac_remove_config_dt(pdev, plat);
|
||||
return ERR_PTR(rc);
|
||||
ret = ERR_PTR(rc);
|
||||
goto error_put_mdio;
|
||||
}
|
||||
|
||||
/* clock setup */
|
||||
@@ -663,6 +649,10 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
|
||||
clk_disable_unprepare(plat->pclk);
|
||||
error_pclk_get:
|
||||
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;
|
||||
}
|
||||
@@ -671,16 +661,17 @@ static void devm_stmmac_remove_config_dt(void *data)
|
||||
{
|
||||
struct plat_stmmacenet_data *plat = data;
|
||||
|
||||
/* Platform data argument is unused */
|
||||
stmmac_remove_config_dt(NULL, plat);
|
||||
clk_disable_unprepare(plat->stmmac_clk);
|
||||
clk_disable_unprepare(plat->pclk);
|
||||
of_node_put(plat->mdio_node);
|
||||
of_node_put(plat->phy_node);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_stmmac_probe_config_dt
|
||||
* @pdev: platform_device structure
|
||||
* @mac: MAC address to use
|
||||
* Description: Devres variant of stmmac_probe_config_dt(). Does not require
|
||||
* the user to call stmmac_remove_config_dt() at driver detach.
|
||||
* Description: Devres variant of stmmac_probe_config_dt().
|
||||
*/
|
||||
struct plat_stmmacenet_data *
|
||||
devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
|
||||
|
||||
Reference in New Issue
Block a user