summaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-xgene.c
diff options
context:
space:
mode:
authorAlexandre Belloni <alexandre.belloni@bootlin.com>2019-03-20 13:32:27 +0100
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2019-04-04 10:07:08 +0200
commita652e00ee1233e251a337c28e18a1da59224e5ce (patch)
tree5d4a8cc07bf9a3e52519cca3d1d4fb23c2c4b708 /drivers/rtc/rtc-xgene.c
parentrtc: test: do not use assignment in if condition (diff)
downloadlinux-a652e00ee1233e251a337c28e18a1da59224e5ce.tar.xz
linux-a652e00ee1233e251a337c28e18a1da59224e5ce.zip
rtc: xgene: fix possible race condition
The IRQ is requested before the struct rtc is allocated and registered, but this struct is used in the IRQ handler. This may lead to a NULL pointer dereference. Switch to devm_rtc_allocate_device/rtc_register_device to allocate the rtc struct before requesting the IRQ. Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Diffstat (limited to '')
-rw-r--r--drivers/rtc/rtc-xgene.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/rtc/rtc-xgene.c b/drivers/rtc/rtc-xgene.c
index 153820876a82..2f741f455c30 100644
--- a/drivers/rtc/rtc-xgene.c
+++ b/drivers/rtc/rtc-xgene.c
@@ -168,6 +168,10 @@ static int xgene_rtc_probe(struct platform_device *pdev)
if (IS_ERR(pdata->csr_base))
return PTR_ERR(pdata->csr_base);
+ pdata->rtc = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(pdata->rtc))
+ return PTR_ERR(pdata->rtc);
+
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "No IRQ resource\n");
@@ -198,15 +202,15 @@ static int xgene_rtc_probe(struct platform_device *pdev)
return ret;
}
- pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
- &xgene_rtc_ops, THIS_MODULE);
- if (IS_ERR(pdata->rtc)) {
- clk_disable_unprepare(pdata->clk);
- return PTR_ERR(pdata->rtc);
- }
-
/* HW does not support update faster than 1 seconds */
pdata->rtc->uie_unsupported = 1;
+ pdata->rtc->ops = &xgene_rtc_ops;
+
+ ret = rtc_register_device(pdata->rtc);
+ if (ret) {
+ clk_disable_unprepare(pdata->clk);
+ return ret;
+ }
return 0;
}