diff options
author | Wolfram Sang <w.sang@pengutronix.de> | 2011-05-25 06:56:51 -0400 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2011-07-01 21:09:55 -0400 |
commit | a91d2bab355f3a5caa767d7316f80422bfcd2ad6 (patch) | |
tree | d195bca36a8b606c58280011ef06cd6c5ec616bc /drivers/rtc | |
parent | 46b21218145ecef0936eb4338a9e0ffef84f00cf (diff) |
rtc: stmp3xxx: Initialize drvdata before registering device
Commit f44f7f96a20 ("RTC: Initialize kernel state from RTC") uncovered
an issue in a number of RTC drivers, where the drivers call
rtc_device_register before initializing the device or platform drvdata.
This frequently results in null pointer dereferences when the
rtc_device_register immediately makes use of the rtc device, calling
rtc_read_alarm.
The solution is to ensure the drvdata is initialized prior to registering
the rtc device.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Tested-by: Shawn Guo <shawn.guo@freescale.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-stmp3xxx.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index ac40f971a40e..90f05fe60620 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c | |||
@@ -176,6 +176,7 @@ static int stmp3xxx_rtc_remove(struct platform_device *pdev) | |||
176 | free_irq(rtc_data->irq_alarm, &pdev->dev); | 176 | free_irq(rtc_data->irq_alarm, &pdev->dev); |
177 | free_irq(rtc_data->irq_1msec, &pdev->dev); | 177 | free_irq(rtc_data->irq_1msec, &pdev->dev); |
178 | rtc_device_unregister(rtc_data->rtc); | 178 | rtc_device_unregister(rtc_data->rtc); |
179 | platform_set_drvdata(pdev, NULL); | ||
179 | iounmap(rtc_data->io); | 180 | iounmap(rtc_data->io); |
180 | kfree(rtc_data); | 181 | kfree(rtc_data); |
181 | 182 | ||
@@ -216,11 +217,14 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) | |||
216 | goto out_remap; | 217 | goto out_remap; |
217 | } | 218 | } |
218 | 219 | ||
220 | platform_set_drvdata(pdev, rtc_data); | ||
221 | |||
219 | mxs_reset_block(rtc_data->io); | 222 | mxs_reset_block(rtc_data->io); |
220 | __mxs_clrl(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | | 223 | __mxs_clrl(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | |
221 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | | 224 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | |
222 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, | 225 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, |
223 | rtc_data->io + STMP3XXX_RTC_PERSISTENT0); | 226 | rtc_data->io + STMP3XXX_RTC_PERSISTENT0); |
227 | |||
224 | rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev, | 228 | rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev, |
225 | &stmp3xxx_rtc_ops, THIS_MODULE); | 229 | &stmp3xxx_rtc_ops, THIS_MODULE); |
226 | if (IS_ERR(rtc_data->rtc)) { | 230 | if (IS_ERR(rtc_data->rtc)) { |
@@ -244,8 +248,6 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) | |||
244 | goto out_irq1; | 248 | goto out_irq1; |
245 | } | 249 | } |
246 | 250 | ||
247 | platform_set_drvdata(pdev, rtc_data); | ||
248 | |||
249 | return 0; | 251 | return 0; |
250 | 252 | ||
251 | out_irq1: | 253 | out_irq1: |
@@ -256,6 +258,7 @@ out_irq_alarm: | |||
256 | rtc_data->io + STMP3XXX_RTC_CTRL); | 258 | rtc_data->io + STMP3XXX_RTC_CTRL); |
257 | rtc_device_unregister(rtc_data->rtc); | 259 | rtc_device_unregister(rtc_data->rtc); |
258 | out_remap: | 260 | out_remap: |
261 | platform_set_drvdata(pdev, NULL); | ||
259 | iounmap(rtc_data->io); | 262 | iounmap(rtc_data->io); |
260 | out_free: | 263 | out_free: |
261 | kfree(rtc_data); | 264 | kfree(rtc_data); |