[PATCH] phy: ti: phy-ti-pipe3: fix a device reference leak in ti_pipe3_get_sysctrl()

Joe Hattori joe at pf.is.s.u-tokyo.ac.jp
Tue Dec 17 01:46:20 PST 2024


ti_pipe3_get_sysctrl() calls of_find_device_by_node() to obtain an OF
node reference, but does not release it on error or on removal. Call
put_device() in the error path of ti_pipe3_get_sysctrl() and .probe(),
and in .remove() to fix this.

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

Fixes: 73bbc78e57c9 ("phy: ti-pipe3: move sysctrl initialization to a separate function")
Signed-off-by: Joe Hattori <joe at pf.is.s.u-tokyo.ac.jp>
---
 drivers/phy/ti/phy-ti-pipe3.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/phy/ti/phy-ti-pipe3.c b/drivers/phy/ti/phy-ti-pipe3.c
index da2cbacb982c..ab3614d169ec 100644
--- a/drivers/phy/ti/phy-ti-pipe3.c
+++ b/drivers/phy/ti/phy-ti-pipe3.c
@@ -719,6 +719,7 @@ static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy)
 						       &phy->pcie_pcs_reg)) {
 				dev_err(dev,
 					"couldn't get pcie pcs reg. offset\n");
+				put_device(phy->control_dev);
 				return -EINVAL;
 			}
 		}
@@ -737,6 +738,7 @@ static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy)
 						       &phy->dpll_reset_reg)) {
 				dev_err(dev,
 					"couldn't get pllreset reg. offset\n");
+				put_device(phy->control_dev);
 				return -EINVAL;
 			}
 		}
@@ -808,7 +810,7 @@ static int ti_pipe3_probe(struct platform_device *pdev)
 
 	ret = ti_pipe3_get_clk(phy);
 	if (ret)
-		return ret;
+		goto err;
 
 	platform_set_drvdata(pdev, phy);
 	pm_runtime_enable(dev);
@@ -824,15 +826,25 @@ static int ti_pipe3_probe(struct platform_device *pdev)
 	}
 
 	generic_phy = devm_phy_create(dev, NULL, &ops);
-	if (IS_ERR(generic_phy))
-		return PTR_ERR(generic_phy);
+	if (IS_ERR(generic_phy)) {
+		ret = PTR_ERR(generic_phy);
+		goto err;
+	}
 
 	phy_set_drvdata(generic_phy, phy);
 
 	ti_pipe3_power_off(generic_phy);
 
 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-	return PTR_ERR_OR_ZERO(phy_provider);
+	if (IS_ERR(phy_provider)) {
+		ret = PTR_ERR(phy_provider);
+		goto err;
+	}
+	return 0;
+
+err:
+	put_device(phy->control_dev);
+	return ret;
 }
 
 static void ti_pipe3_remove(struct platform_device *pdev)
@@ -844,6 +856,7 @@ static void ti_pipe3_remove(struct platform_device *pdev)
 		phy->sata_refclk_enabled = false;
 	}
 	pm_runtime_disable(&pdev->dev);
+	put_device(phy->control_dev);
 }
 
 static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy)
-- 
2.34.1




More information about the linux-phy mailing list