diff mbox series

rtc: rtc-at91sam9: disable wakeup in .remove() and the error path of .probe()

Message ID 20241209025032.1600719-1-joe@pf.is.s.u-tokyo.ac.jp
State Superseded
Headers show
Series rtc: rtc-at91sam9: disable wakeup in .remove() and the error path of .probe() | expand

Commit Message

Joe Hattori Dec. 9, 2024, 2:50 a.m. UTC
Current implementation leaves wakeup enabled in the .remove() and the
error path of .probe(), which results in a memory leak. Fix it by adding
device_init_wakeup(&pdev->dev, 0) calls.

This bug has been found by an experimental static analysis tool that we
are developing.

Fixes: 9fedc9f1b18f ("rtc-at91sam9 fixes")
Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
---
 drivers/rtc/rtc-at91sam9.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 15b21da2788f..539565c0c888 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -358,31 +358,36 @@  static int at91_rtc_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, rtc);
 
 	rtc->rtt = devm_platform_ioremap_resource(pdev, 0);
-	if (IS_ERR(rtc->rtt))
-		return PTR_ERR(rtc->rtt);
+	if (IS_ERR(rtc->rtt)) {
+		ret = PTR_ERR(rtc->rtt);
+		goto err_disable_wakeup;
+	}
 
 	ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
 					       "atmel,rtt-rtc-time-reg", 1, 0,
 					       &args);
 	if (ret)
-		return ret;
+		goto err_disable_wakeup;
 
 	rtc->gpbr = syscon_node_to_regmap(args.np);
 	of_node_put(args.np);
 	rtc->gpbr_offset = args.args[0];
 	if (IS_ERR(rtc->gpbr)) {
 		dev_err(&pdev->dev, "failed to retrieve gpbr regmap, aborting.\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_disable_wakeup;
 	}
 
 	rtc->sclk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(rtc->sclk))
-		return PTR_ERR(rtc->sclk);
+	if (IS_ERR(rtc->sclk)) {
+		ret = PTR_ERR(rtc->sclk);
+		goto err_disable_wakeup;
+	}
 
 	ret = clk_prepare_enable(rtc->sclk);
 	if (ret) {
 		dev_err(&pdev->dev, "Could not enable slow clock\n");
-		return ret;
+		goto err_disable_wakeup;
 	}
 
 	sclk_rate = clk_get_rate(rtc->sclk);
@@ -432,10 +437,15 @@  static int at91_rtc_probe(struct platform_device *pdev)
 		dev_warn(&pdev->dev, "%s: SET TIME!\n",
 			 dev_name(&rtc->rtcdev->dev));
 
-	return devm_rtc_register_device(rtc->rtcdev);
+	ret = devm_rtc_register_device(rtc->rtcdev);
+	if (ret)
+		goto err_clk;
+	return 0;
 
 err_clk:
 	clk_disable_unprepare(rtc->sclk);
+err_disable_wakeup:
+	device_init_wakeup(&pdev->dev, 0);
 
 	return ret;
 }
@@ -452,6 +462,7 @@  static void at91_rtc_remove(struct platform_device *pdev)
 	rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
 
 	clk_disable_unprepare(rtc->sclk);
+	device_init_wakeup(&pdev->dev, 0);
 }
 
 static void at91_rtc_shutdown(struct platform_device *pdev)