diff options
author | Xunlei Pang <pang.xunlei@linaro.org> | 2015-04-01 23:34:30 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-04-03 02:18:26 -0400 |
commit | 0307b0d77a0830b0fd4a22b5db4a9fa723a5fa5f (patch) | |
tree | 7700009c3ae6c2733d285657001fdd9c9cfa8414 /drivers/rtc/rtc-mc13xxx.c | |
parent | 5c7e11bc66647f2e4bc95de9b4302fff6d612f3a (diff) |
drivers/rtc/mc13xxx: Update driver to address y2038/y2106 issues
This driver has a number of y2038/y2106 issues.
This patch resolves them by:
- Replacing rtc_time_to_tm() with rtc_time64_to_tm()
- Changing mc13xxx_rtc_set_mmss() to use rtc_class_ops's set_mmss64()
After this patch, the driver should not have any remaining
y2038/y2106 issues.
Signed-off-by: Xunlei Pang <pang.xunlei@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Acked-by: Alessandro Zummo <a.zummo@towertech.it>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1427945681-29972-11-git-send-email-john.stultz@linaro.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/rtc/rtc-mc13xxx.c')
-rw-r--r-- | drivers/rtc/rtc-mc13xxx.c | 32 |
1 files changed, 14 insertions, 18 deletions
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c index 5bce904b7ee6..32df1d812367 100644 --- a/drivers/rtc/rtc-mc13xxx.c +++ b/drivers/rtc/rtc-mc13xxx.c | |||
@@ -83,20 +83,19 @@ static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
83 | return ret; | 83 | return ret; |
84 | } while (days1 != days2); | 84 | } while (days1 != days2); |
85 | 85 | ||
86 | rtc_time_to_tm(days1 * SEC_PER_DAY + seconds, tm); | 86 | rtc_time64_to_tm((time64_t)days1 * SEC_PER_DAY + seconds, tm); |
87 | 87 | ||
88 | return rtc_valid_tm(tm); | 88 | return rtc_valid_tm(tm); |
89 | } | 89 | } |
90 | 90 | ||
91 | static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs) | 91 | static int mc13xxx_rtc_set_mmss(struct device *dev, time64_t secs) |
92 | { | 92 | { |
93 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | 93 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); |
94 | unsigned int seconds, days; | 94 | unsigned int seconds, days; |
95 | unsigned int alarmseconds; | 95 | unsigned int alarmseconds; |
96 | int ret; | 96 | int ret; |
97 | 97 | ||
98 | seconds = secs % SEC_PER_DAY; | 98 | days = div_s64_rem(secs, SEC_PER_DAY, &seconds); |
99 | days = secs / SEC_PER_DAY; | ||
100 | 99 | ||
101 | mc13xxx_lock(priv->mc13xxx); | 100 | mc13xxx_lock(priv->mc13xxx); |
102 | 101 | ||
@@ -159,7 +158,7 @@ static int mc13xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
159 | { | 158 | { |
160 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | 159 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); |
161 | unsigned seconds, days; | 160 | unsigned seconds, days; |
162 | unsigned long s1970; | 161 | time64_t s1970; |
163 | int enabled, pending; | 162 | int enabled, pending; |
164 | int ret; | 163 | int ret; |
165 | 164 | ||
@@ -189,10 +188,10 @@ out: | |||
189 | alarm->enabled = enabled; | 188 | alarm->enabled = enabled; |
190 | alarm->pending = pending; | 189 | alarm->pending = pending; |
191 | 190 | ||
192 | s1970 = days * SEC_PER_DAY + seconds; | 191 | s1970 = (time64_t)days * SEC_PER_DAY + seconds; |
193 | 192 | ||
194 | rtc_time_to_tm(s1970, &alarm->time); | 193 | rtc_time64_to_tm(s1970, &alarm->time); |
195 | dev_dbg(dev, "%s: %lu\n", __func__, s1970); | 194 | dev_dbg(dev, "%s: %lld\n", __func__, (long long)s1970); |
196 | 195 | ||
197 | return 0; | 196 | return 0; |
198 | } | 197 | } |
@@ -200,8 +199,8 @@ out: | |||
200 | static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 199 | static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
201 | { | 200 | { |
202 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | 201 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); |
203 | unsigned long s1970; | 202 | time64_t s1970; |
204 | unsigned seconds, days; | 203 | u32 seconds, days; |
205 | int ret; | 204 | int ret; |
206 | 205 | ||
207 | mc13xxx_lock(priv->mc13xxx); | 206 | mc13xxx_lock(priv->mc13xxx); |
@@ -215,20 +214,17 @@ static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
215 | if (unlikely(ret)) | 214 | if (unlikely(ret)) |
216 | goto out; | 215 | goto out; |
217 | 216 | ||
218 | ret = rtc_tm_to_time(&alarm->time, &s1970); | 217 | s1970 = rtc_tm_to_time64(&alarm->time); |
219 | if (unlikely(ret)) | ||
220 | goto out; | ||
221 | 218 | ||
222 | dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff", | 219 | dev_dbg(dev, "%s: o%2.s %lld\n", __func__, alarm->enabled ? "n" : "ff", |
223 | s1970); | 220 | (long long)s1970); |
224 | 221 | ||
225 | ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled, | 222 | ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled, |
226 | MC13XXX_IRQ_TODA); | 223 | MC13XXX_IRQ_TODA); |
227 | if (unlikely(ret)) | 224 | if (unlikely(ret)) |
228 | goto out; | 225 | goto out; |
229 | 226 | ||
230 | seconds = s1970 % SEC_PER_DAY; | 227 | days = div_s64_rem(s1970, SEC_PER_DAY, &seconds); |
231 | days = s1970 / SEC_PER_DAY; | ||
232 | 228 | ||
233 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days); | 229 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days); |
234 | if (unlikely(ret)) | 230 | if (unlikely(ret)) |
@@ -268,7 +264,7 @@ static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev) | |||
268 | 264 | ||
269 | static const struct rtc_class_ops mc13xxx_rtc_ops = { | 265 | static const struct rtc_class_ops mc13xxx_rtc_ops = { |
270 | .read_time = mc13xxx_rtc_read_time, | 266 | .read_time = mc13xxx_rtc_read_time, |
271 | .set_mmss = mc13xxx_rtc_set_mmss, | 267 | .set_mmss64 = mc13xxx_rtc_set_mmss, |
272 | .read_alarm = mc13xxx_rtc_read_alarm, | 268 | .read_alarm = mc13xxx_rtc_read_alarm, |
273 | .set_alarm = mc13xxx_rtc_set_alarm, | 269 | .set_alarm = mc13xxx_rtc_set_alarm, |
274 | .alarm_irq_enable = mc13xxx_rtc_alarm_irq_enable, | 270 | .alarm_irq_enable = mc13xxx_rtc_alarm_irq_enable, |