diff options
| -rw-r--r-- | drivers/rtc/class.c | 3 | ||||
| -rw-r--r-- | drivers/rtc/systohc.c | 53 | ||||
| -rw-r--r-- | include/linux/rtc.h | 43 | ||||
| -rw-r--r-- | kernel/time/ntp.c | 166 |
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 | */ |
| 23 | int rtc_set_ntp_time(struct timespec64 now) | 26 | int 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 | |||
| 66 | out_close: | ||
| 67 | rtc_class_close(rtc); | ||
| 68 | out_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 | ||
| 173 | extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm); | 181 | extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm); |
| 174 | extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm); | 182 | extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm); |
| 175 | extern int rtc_set_ntp_time(struct timespec64 now); | 183 | extern int rtc_set_ntp_time(struct timespec64 now, unsigned long *target_nsec); |
| 176 | int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm); | 184 | int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm); |
| 177 | extern int rtc_read_alarm(struct rtc_device *rtc, | 185 | extern 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 | */ | ||
| 241 | static 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 | ||
| 495 | static void sync_hw_clock(struct work_struct *work); | ||
| 496 | static DECLARE_DELAYED_WORK(sync_work, sync_hw_clock); | ||
| 497 | |||
| 498 | static 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 | |||
| 530 | static 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 |
| 496 | int __weak update_persistent_clock(struct timespec now) | 557 | int __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) | 571 | static bool sync_cmos_clock(void) |
| 511 | static void sync_cmos_clock(struct work_struct *work); | ||
| 512 | |||
| 513 | static DECLARE_DELAYED_WORK(sync_cmos_work, sync_cmos_clock); | ||
| 514 | |||
| 515 | static 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 | */ | ||
| 620 | static 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 | ||
| 571 | void ntp_notify_cmos_timer(void) | 631 | void 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 | ||
| 577 | void 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: |
