aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>2017-10-13 13:54:33 -0400
committerJohn Stultz <john.stultz@linaro.org>2017-10-30 18:03:24 -0400
commit0f295b0650c90362b4111f46d7f9149a0a4191be (patch)
tree4589b6e58d710ac1f2967317305c6c8fc28903d3
parent9e66317d3c92ddaab330c125dfe9d06eee268aff (diff)
rtc: Allow rtc drivers to specify the tv_nsec value for ntp
ntp is currently hardwired to try and call the rtc set when wall clock tv_nsec is 0.5 seconds. This historical behaviour works well with certain PC RTCs, but is not universal to all rtc hardware. Change how this works by introducing the driver specific concept of set_offset_nsec, the delay between current wall clock time and the target time to set (with a 0 tv_nsecs). For x86-style CMOS set_offset_nsec should be -0.5 s which causes the last second to be written 0.5 s after it has started. For compat with the old rtc_set_ntp_time, the value is defaulted to + 0.5 s, which causes the next second to be written 0.5s before it starts, as things were before this patch. Testing shows many non-x86 RTCs would like set_offset_nsec ~= 0, so ultimately each RTC driver should set the set_offset_nsec according to its needs, and non x86 architectures should stop using update_persistent_clock64 in order to access this feature. Future patches will revise the drivers as needed. Since CMOS and RTC now have very different handling they are split into two dedicated code paths, sharing the support code, and ifdefs are replaced with IS_ENABLED. Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@kernel.org> Cc: Miroslav Lichvar <mlichvar@redhat.com> Cc: Richard Cochran <richardcochran@gmail.com> Cc: Prarit Bhargava <prarit@redhat.com> Cc: Stephen Boyd <stephen.boyd@linaro.org> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: John Stultz <john.stultz@linaro.org>
-rw-r--r--drivers/rtc/class.c3
-rw-r--r--drivers/rtc/systohc.c53
-rw-r--r--include/linux/rtc.h43
-rw-r--r--kernel/time/ntp.c166
4 files changed, 196 insertions, 69 deletions
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 2ed970d61da1..722d683e0b0f 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -161,6 +161,9 @@ static struct rtc_device *rtc_allocate_device(void)
161 161
162 device_initialize(&rtc->dev); 162 device_initialize(&rtc->dev);
163 163
164 /* Drivers can revise this default after allocating the device. */
165 rtc->set_offset_nsec = NSEC_PER_SEC / 2;
166
164 rtc->irq_freq = 1; 167 rtc->irq_freq = 1;
165 rtc->max_user_freq = 64; 168 rtc->max_user_freq = 64;
166 rtc->dev.class = rtc_class; 169 rtc->dev.class = rtc_class;
diff --git a/drivers/rtc/systohc.c b/drivers/rtc/systohc.c
index b4a68ffcd06b..0c177647ea6c 100644
--- a/drivers/rtc/systohc.c
+++ b/drivers/rtc/systohc.c
@@ -10,6 +10,7 @@
10/** 10/**
11 * rtc_set_ntp_time - Save NTP synchronized time to the RTC 11 * rtc_set_ntp_time - Save NTP synchronized time to the RTC
12 * @now: Current time of day 12 * @now: Current time of day
13 * @target_nsec: pointer for desired now->tv_nsec value
13 * 14 *
14 * Replacement for the NTP platform function update_persistent_clock64 15 * Replacement for the NTP platform function update_persistent_clock64
15 * that stores time for later retrieval by rtc_hctosys. 16 * that stores time for later retrieval by rtc_hctosys.
@@ -18,30 +19,52 @@
18 * possible at all, and various other -errno for specific temporary failure 19 * possible at all, and various other -errno for specific temporary failure
19 * cases. 20 * cases.
20 * 21 *
22 * -EPROTO is returned if now.tv_nsec is not close enough to *target_nsec.
23 (
21 * If temporary failure is indicated the caller should try again 'soon' 24 * If temporary failure is indicated the caller should try again 'soon'
22 */ 25 */
23int rtc_set_ntp_time(struct timespec64 now) 26int rtc_set_ntp_time(struct timespec64 now, unsigned long *target_nsec)
24{ 27{
25 struct rtc_device *rtc; 28 struct rtc_device *rtc;
26 struct rtc_time tm; 29 struct rtc_time tm;
30 struct timespec64 to_set;
27 int err = -ENODEV; 31 int err = -ENODEV;
28 32 bool ok;
29 if (now.tv_nsec < (NSEC_PER_SEC >> 1))
30 rtc_time64_to_tm(now.tv_sec, &tm);
31 else
32 rtc_time64_to_tm(now.tv_sec + 1, &tm);
33 33
34 rtc = rtc_class_open(CONFIG_RTC_SYSTOHC_DEVICE); 34 rtc = rtc_class_open(CONFIG_RTC_SYSTOHC_DEVICE);
35 if (rtc) { 35 if (!rtc)
36 /* rtc_hctosys exclusively uses UTC, so we call set_time here, 36 goto out_err;
37 * not set_mmss. */ 37
38 if (rtc->ops && 38 if (!rtc->ops || (!rtc->ops->set_time && !rtc->ops->set_mmss64 &&
39 (rtc->ops->set_time || 39 !rtc->ops->set_mmss))
40 rtc->ops->set_mmss64 || 40 goto out_close;
41 rtc->ops->set_mmss)) 41
42 err = rtc_set_time(rtc, &tm); 42 /* Compute the value of tv_nsec we require the caller to supply in
43 rtc_class_close(rtc); 43 * now.tv_nsec. This is the value such that (now +
44 * set_offset_nsec).tv_nsec == 0.
45 */
46 set_normalized_timespec64(&to_set, 0, -rtc->set_offset_nsec);
47 *target_nsec = to_set.tv_nsec;
48
49 /* The ntp code must call this with the correct value in tv_nsec, if
50 * it does not we update target_nsec and return EPROTO to make the ntp
51 * code try again later.
52 */
53 ok = rtc_tv_nsec_ok(rtc->set_offset_nsec, &to_set, &now);
54 if (!ok) {
55 err = -EPROTO;
56 goto out_close;
44 } 57 }
45 58
59 rtc_time64_to_tm(to_set.tv_sec, &tm);
60
61 /* rtc_hctosys exclusively uses UTC, so we call set_time here, not
62 * set_mmss.
63 */
64 err = rtc_set_time(rtc, &tm);
65
66out_close:
67 rtc_class_close(rtc);
68out_err:
46 return err; 69 return err;
47} 70}
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index e6d0f9c1cafd..5b13fa029fd6 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -135,6 +135,14 @@ struct rtc_device {
135 /* Some hardware can't support UIE mode */ 135 /* Some hardware can't support UIE mode */
136 int uie_unsupported; 136 int uie_unsupported;
137 137
138 /* Number of nsec it takes to set the RTC clock. This influences when
139 * the set ops are called. An offset:
140 * - of 0.5 s will call RTC set for wall clock time 10.0 s at 9.5 s
141 * - of 1.5 s will call RTC set for wall clock time 10.0 s at 8.5 s
142 * - of -0.5 s will call RTC set for wall clock time 10.0 s at 10.5 s
143 */
144 long set_offset_nsec;
145
138 bool registered; 146 bool registered;
139 147
140 struct nvmem_config *nvmem_config; 148 struct nvmem_config *nvmem_config;
@@ -172,7 +180,7 @@ extern void devm_rtc_device_unregister(struct device *dev,
172 180
173extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm); 181extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm);
174extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm); 182extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm);
175extern int rtc_set_ntp_time(struct timespec64 now); 183extern int rtc_set_ntp_time(struct timespec64 now, unsigned long *target_nsec);
176int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm); 184int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm);
177extern int rtc_read_alarm(struct rtc_device *rtc, 185extern int rtc_read_alarm(struct rtc_device *rtc,
178 struct rtc_wkalrm *alrm); 186 struct rtc_wkalrm *alrm);
@@ -221,6 +229,39 @@ static inline bool is_leap_year(unsigned int year)
221 return (!(year % 4) && (year % 100)) || !(year % 400); 229 return (!(year % 4) && (year % 100)) || !(year % 400);
222} 230}
223 231
232/* Determine if we can call to driver to set the time. Drivers can only be
233 * called to set a second aligned time value, and the field set_offset_nsec
234 * specifies how far away from the second aligned time to call the driver.
235 *
236 * This also computes 'to_set' which is the time we are trying to set, and has
237 * a zero in tv_nsecs, such that:
238 * to_set - set_delay_nsec == now +/- FUZZ
239 *
240 */
241static inline bool rtc_tv_nsec_ok(s64 set_offset_nsec,
242 struct timespec64 *to_set,
243 const struct timespec64 *now)
244{
245 /* Allowed error in tv_nsec, arbitarily set to 5 jiffies in ns. */
246 const unsigned long TIME_SET_NSEC_FUZZ = TICK_NSEC * 5;
247 struct timespec64 delay = {.tv_sec = 0,
248 .tv_nsec = set_offset_nsec};
249
250 *to_set = timespec64_add(*now, delay);
251
252 if (to_set->tv_nsec < TIME_SET_NSEC_FUZZ) {
253 to_set->tv_nsec = 0;
254 return true;
255 }
256
257 if (to_set->tv_nsec > NSEC_PER_SEC - TIME_SET_NSEC_FUZZ) {
258 to_set->tv_sec++;
259 to_set->tv_nsec = 0;
260 return true;
261 }
262 return false;
263}
264
224#define rtc_register_device(device) \ 265#define rtc_register_device(device) \
225 __rtc_register_device(THIS_MODULE, device) 266 __rtc_register_device(THIS_MODULE, device)
226 267
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index edf19cc53140..bc19de1a0683 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -492,6 +492,67 @@ out:
492 return leap; 492 return leap;
493} 493}
494 494
495static void sync_hw_clock(struct work_struct *work);
496static DECLARE_DELAYED_WORK(sync_work, sync_hw_clock);
497
498static void sched_sync_hw_clock(struct timespec64 now,
499 unsigned long target_nsec, bool fail)
500
501{
502 struct timespec64 next;
503
504 getnstimeofday64(&next);
505 if (!fail)
506 next.tv_sec = 659;
507 else {
508 /*
509 * Try again as soon as possible. Delaying long periods
510 * decreases the accuracy of the work queue timer. Due to this
511 * the algorithm is very likely to require a short-sleep retry
512 * after the above long sleep to synchronize ts_nsec.
513 */
514 next.tv_sec = 0;
515 }
516
517 /* Compute the needed delay that will get to tv_nsec == target_nsec */
518 next.tv_nsec = target_nsec - next.tv_nsec;
519 if (next.tv_nsec <= 0)
520 next.tv_nsec += NSEC_PER_SEC;
521 if (next.tv_nsec >= NSEC_PER_SEC) {
522 next.tv_sec++;
523 next.tv_nsec -= NSEC_PER_SEC;
524 }
525
526 queue_delayed_work(system_power_efficient_wq, &sync_work,
527 timespec64_to_jiffies(&next));
528}
529
530static void sync_rtc_clock(void)
531{
532 unsigned long target_nsec;
533 struct timespec64 adjust, now;
534 int rc;
535
536 if (!IS_ENABLED(CONFIG_RTC_SYSTOHC))
537 return;
538
539 getnstimeofday64(&now);
540
541 adjust = now;
542 if (persistent_clock_is_local)
543 adjust.tv_sec -= (sys_tz.tz_minuteswest * 60);
544
545 /*
546 * The current RTC in use will provide the target_nsec it wants to be
547 * called at, and does rtc_tv_nsec_ok internally.
548 */
549 rc = rtc_set_ntp_time(adjust, &target_nsec);
550 if (rc == -ENODEV)
551 return;
552
553 sched_sync_hw_clock(now, target_nsec, rc);
554}
555
495#ifdef CONFIG_GENERIC_CMOS_UPDATE 556#ifdef CONFIG_GENERIC_CMOS_UPDATE
496int __weak update_persistent_clock(struct timespec now) 557int __weak update_persistent_clock(struct timespec now)
497{ 558{
@@ -507,76 +568,75 @@ int __weak update_persistent_clock64(struct timespec64 now64)
507} 568}
508#endif 569#endif
509 570
510#if defined(CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC) 571static bool sync_cmos_clock(void)
511static void sync_cmos_clock(struct work_struct *work);
512
513static DECLARE_DELAYED_WORK(sync_cmos_work, sync_cmos_clock);
514
515static void sync_cmos_clock(struct work_struct *work)
516{ 572{
573 static bool no_cmos;
517 struct timespec64 now; 574 struct timespec64 now;
518 struct timespec64 next; 575 struct timespec64 adjust;
519 int fail = 1; 576 int rc = -EPROTO;
577 long target_nsec = NSEC_PER_SEC / 2;
578
579 if (!IS_ENABLED(CONFIG_GENERIC_CMOS_UPDATE))
580 return false;
581
582 if (no_cmos)
583 return false;
520 584
521 /* 585 /*
522 * If we have an externally synchronized Linux clock, then update 586 * Historically update_persistent_clock64() has followed x86
523 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be 587 * semantics, which match the MC146818A/etc RTC. This RTC will store
524 * called as close as possible to 500 ms before the new second starts. 588 * 'adjust' and then in .5s it will advance once second.
525 * This code is run on a timer. If the clock is set, that timer 589 *
526 * may not expire at the correct time. Thus, we adjust... 590 * Architectures are strongly encouraged to use rtclib and not
527 * We want the clock to be within a couple of ticks from the target. 591 * implement this legacy API.
528 */ 592 */
529 if (!ntp_synced()) {
530 /*
531 * Not synced, exit, do not restart a timer (if one is
532 * running, let it run out).
533 */
534 return;
535 }
536
537 getnstimeofday64(&now); 593 getnstimeofday64(&now);
538 if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec * 5) { 594 if (rtc_tv_nsec_ok(-1 * target_nsec, &adjust, &now)) {
539 struct timespec64 adjust = now;
540
541 fail = -ENODEV;
542 if (persistent_clock_is_local) 595 if (persistent_clock_is_local)
543 adjust.tv_sec -= (sys_tz.tz_minuteswest * 60); 596 adjust.tv_sec -= (sys_tz.tz_minuteswest * 60);
544#ifdef CONFIG_GENERIC_CMOS_UPDATE 597 rc = update_persistent_clock64(adjust);
545 fail = update_persistent_clock64(adjust); 598 /*
546#endif 599 * The machine does not support update_persistent_clock64 even
547 600 * though it defines CONFIG_GENERIC_CMOS_UPDATE.
548#ifdef CONFIG_RTC_SYSTOHC 601 */
549 if (fail == -ENODEV) 602 if (rc == -ENODEV) {
550 fail = rtc_set_ntp_time(adjust); 603 no_cmos = true;
551#endif 604 return false;
605 }
552 } 606 }
553 607
554 next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec - (TICK_NSEC / 2); 608 sched_sync_hw_clock(now, target_nsec, rc);
555 if (next.tv_nsec <= 0) 609 return true;
556 next.tv_nsec += NSEC_PER_SEC; 610}
557 611
558 if (!fail || fail == -ENODEV) 612/*
559 next.tv_sec = 659; 613 * If we have an externally synchronized Linux clock, then update RTC clock
560 else 614 * accordingly every ~11 minutes. Generally RTCs can only store second
561 next.tv_sec = 0; 615 * precision, but many RTCs will adjust the phase of their second tick to
616 * match the moment of update. This infrastructure arranges to call to the RTC
617 * set at the correct moment to phase synchronize the RTC second tick over
618 * with the kernel clock.
619 */
620static void sync_hw_clock(struct work_struct *work)
621{
622 if (!ntp_synced())
623 return;
562 624
563 if (next.tv_nsec >= NSEC_PER_SEC) { 625 if (sync_cmos_clock())
564 next.tv_sec++; 626 return;
565 next.tv_nsec -= NSEC_PER_SEC; 627
566 } 628 sync_rtc_clock();
567 queue_delayed_work(system_power_efficient_wq,
568 &sync_cmos_work, timespec64_to_jiffies(&next));
569} 629}
570 630
571void ntp_notify_cmos_timer(void) 631void ntp_notify_cmos_timer(void)
572{ 632{
573 queue_delayed_work(system_power_efficient_wq, &sync_cmos_work, 0); 633 if (!ntp_synced())
574} 634 return;
575
576#else
577void ntp_notify_cmos_timer(void) { }
578#endif
579 635
636 if (IS_ENABLED(CONFIG_GENERIC_CMOS_UPDATE) ||
637 IS_ENABLED(CONFIG_RTC_SYSTOHC))
638 queue_delayed_work(system_power_efficient_wq, &sync_work, 0);
639}
580 640
581/* 641/*
582 * Propagate a new txc->status value into the NTP state: 642 * Propagate a new txc->status value into the NTP state: