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 | |
| 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>
| -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); |
