net: fec: Better handle pm_runtime_get() failing in .remove()
[ Upstream commit f816b9829b19394d318e01953aa3b2721bca040d ]
In the (unlikely) event that pm_runtime_get() (disguised as
pm_runtime_resume_and_get()) fails, the remove callback returned an
error early. The problem with this is that the driver core ignores the
error value and continues removing the device. This results in a
resource leak. Worse the devm allocated resources are freed and so if a
callback of the driver is called later the register mapping is already
gone which probably results in a crash.
Fixes: a31eda65ba
("net: fec: fix clock count mis-match")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20230510200020.1534610-1-u.kleine-koenig@pengutronix.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
033297ef3b
commit
b22b514209
@ -3769,7 +3769,9 @@ fec_drv_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
ret = pm_runtime_get_sync(&pdev->dev);
|
ret = pm_runtime_get_sync(&pdev->dev);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
dev_err(&pdev->dev,
|
||||||
|
"Failed to resume device in remove callback (%pe)\n",
|
||||||
|
ERR_PTR(ret));
|
||||||
|
|
||||||
cancel_work_sync(&fep->tx_timeout_work);
|
cancel_work_sync(&fep->tx_timeout_work);
|
||||||
fec_ptp_stop(pdev);
|
fec_ptp_stop(pdev);
|
||||||
@ -3782,8 +3784,13 @@ fec_drv_remove(struct platform_device *pdev)
|
|||||||
of_phy_deregister_fixed_link(np);
|
of_phy_deregister_fixed_link(np);
|
||||||
of_node_put(fep->phy_node);
|
of_node_put(fep->phy_node);
|
||||||
|
|
||||||
|
/* After pm_runtime_get_sync() failed, the clks are still off, so skip
|
||||||
|
* disabling them again.
|
||||||
|
*/
|
||||||
|
if (ret >= 0) {
|
||||||
clk_disable_unprepare(fep->clk_ahb);
|
clk_disable_unprepare(fep->clk_ahb);
|
||||||
clk_disable_unprepare(fep->clk_ipg);
|
clk_disable_unprepare(fep->clk_ipg);
|
||||||
|
}
|
||||||
pm_runtime_put_noidle(&pdev->dev);
|
pm_runtime_put_noidle(&pdev->dev);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user