diff options
| -rw-r--r-- | drivers/rtc/class.c | 10 | ||||
| -rw-r--r-- | drivers/rtc/interface.c | 44 | ||||
| -rw-r--r-- | kernel/time/clockevents.c | 1 | ||||
| -rw-r--r-- | kernel/time/clocksource.c | 4 | ||||
| -rw-r--r-- | kernel/time/tick-broadcast.c | 2 |
5 files changed, 43 insertions, 18 deletions
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index e8326f26fa2f..dc4c2748bbc3 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
| @@ -63,7 +63,7 @@ static int rtc_suspend(struct device *dev, pm_message_t mesg) | |||
| 63 | */ | 63 | */ |
| 64 | delta = timespec_sub(old_system, old_rtc); | 64 | delta = timespec_sub(old_system, old_rtc); |
| 65 | delta_delta = timespec_sub(delta, old_delta); | 65 | delta_delta = timespec_sub(delta, old_delta); |
| 66 | if (abs(delta_delta.tv_sec) >= 2) { | 66 | if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2) { |
| 67 | /* | 67 | /* |
| 68 | * if delta_delta is too large, assume time correction | 68 | * if delta_delta is too large, assume time correction |
| 69 | * has occured and set old_delta to the current delta. | 69 | * has occured and set old_delta to the current delta. |
| @@ -97,9 +97,8 @@ static int rtc_resume(struct device *dev) | |||
| 97 | rtc_tm_to_time(&tm, &new_rtc.tv_sec); | 97 | rtc_tm_to_time(&tm, &new_rtc.tv_sec); |
| 98 | new_rtc.tv_nsec = 0; | 98 | new_rtc.tv_nsec = 0; |
| 99 | 99 | ||
| 100 | if (new_rtc.tv_sec <= old_rtc.tv_sec) { | 100 | if (new_rtc.tv_sec < old_rtc.tv_sec) { |
| 101 | if (new_rtc.tv_sec < old_rtc.tv_sec) | 101 | pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); |
| 102 | pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); | ||
| 103 | return 0; | 102 | return 0; |
| 104 | } | 103 | } |
| 105 | 104 | ||
| @@ -116,7 +115,8 @@ static int rtc_resume(struct device *dev) | |||
| 116 | sleep_time = timespec_sub(sleep_time, | 115 | sleep_time = timespec_sub(sleep_time, |
| 117 | timespec_sub(new_system, old_system)); | 116 | timespec_sub(new_system, old_system)); |
| 118 | 117 | ||
| 119 | timekeeping_inject_sleeptime(&sleep_time); | 118 | if (sleep_time.tv_sec >= 0) |
| 119 | timekeeping_inject_sleeptime(&sleep_time); | ||
| 120 | return 0; | 120 | return 0; |
| 121 | } | 121 | } |
| 122 | 122 | ||
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 8e286259a007..fa4d9f324189 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
| @@ -319,6 +319,20 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
| 319 | } | 319 | } |
| 320 | EXPORT_SYMBOL_GPL(rtc_read_alarm); | 320 | EXPORT_SYMBOL_GPL(rtc_read_alarm); |
| 321 | 321 | ||
| 322 | static int ___rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | ||
| 323 | { | ||
| 324 | int err; | ||
| 325 | |||
| 326 | if (!rtc->ops) | ||
| 327 | err = -ENODEV; | ||
| 328 | else if (!rtc->ops->set_alarm) | ||
| 329 | err = -EINVAL; | ||
| 330 | else | ||
| 331 | err = rtc->ops->set_alarm(rtc->dev.parent, alarm); | ||
| 332 | |||
| 333 | return err; | ||
| 334 | } | ||
| 335 | |||
| 322 | static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 336 | static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
| 323 | { | 337 | { |
| 324 | struct rtc_time tm; | 338 | struct rtc_time tm; |
| @@ -342,14 +356,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
| 342 | * over right here, before we set the alarm. | 356 | * over right here, before we set the alarm. |
| 343 | */ | 357 | */ |
| 344 | 358 | ||
| 345 | if (!rtc->ops) | 359 | return ___rtc_set_alarm(rtc, alarm); |
| 346 | err = -ENODEV; | ||
| 347 | else if (!rtc->ops->set_alarm) | ||
| 348 | err = -EINVAL; | ||
| 349 | else | ||
| 350 | err = rtc->ops->set_alarm(rtc->dev.parent, alarm); | ||
| 351 | |||
| 352 | return err; | ||
| 353 | } | 360 | } |
| 354 | 361 | ||
| 355 | int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 362 | int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
| @@ -763,6 +770,20 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | |||
| 763 | return 0; | 770 | return 0; |
| 764 | } | 771 | } |
| 765 | 772 | ||
| 773 | static void rtc_alarm_disable(struct rtc_device *rtc) | ||
| 774 | { | ||
| 775 | struct rtc_wkalrm alarm; | ||
| 776 | struct rtc_time tm; | ||
| 777 | |||
| 778 | __rtc_read_time(rtc, &tm); | ||
| 779 | |||
| 780 | alarm.time = rtc_ktime_to_tm(ktime_add(rtc_tm_to_ktime(tm), | ||
| 781 | ktime_set(300, 0))); | ||
| 782 | alarm.enabled = 0; | ||
| 783 | |||
| 784 | ___rtc_set_alarm(rtc, &alarm); | ||
| 785 | } | ||
| 786 | |||
| 766 | /** | 787 | /** |
| 767 | * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue | 788 | * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue |
| 768 | * @rtc rtc device | 789 | * @rtc rtc device |
| @@ -784,8 +805,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) | |||
| 784 | struct rtc_wkalrm alarm; | 805 | struct rtc_wkalrm alarm; |
| 785 | int err; | 806 | int err; |
| 786 | next = timerqueue_getnext(&rtc->timerqueue); | 807 | next = timerqueue_getnext(&rtc->timerqueue); |
| 787 | if (!next) | 808 | if (!next) { |
| 809 | rtc_alarm_disable(rtc); | ||
| 788 | return; | 810 | return; |
| 811 | } | ||
| 789 | alarm.time = rtc_ktime_to_tm(next->expires); | 812 | alarm.time = rtc_ktime_to_tm(next->expires); |
| 790 | alarm.enabled = 1; | 813 | alarm.enabled = 1; |
| 791 | err = __rtc_set_alarm(rtc, &alarm); | 814 | err = __rtc_set_alarm(rtc, &alarm); |
| @@ -847,7 +870,8 @@ again: | |||
| 847 | err = __rtc_set_alarm(rtc, &alarm); | 870 | err = __rtc_set_alarm(rtc, &alarm); |
| 848 | if (err == -ETIME) | 871 | if (err == -ETIME) |
| 849 | goto again; | 872 | goto again; |
| 850 | } | 873 | } else |
| 874 | rtc_alarm_disable(rtc); | ||
| 851 | 875 | ||
| 852 | mutex_unlock(&rtc->ops_lock); | 876 | mutex_unlock(&rtc->ops_lock); |
| 853 | } | 877 | } |
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 1ecd6ba36d6c..c4eb71c8b2ea 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c | |||
| @@ -387,6 +387,7 @@ void clockevents_exchange_device(struct clock_event_device *old, | |||
| 387 | * released list and do a notify add later. | 387 | * released list and do a notify add later. |
| 388 | */ | 388 | */ |
| 389 | if (old) { | 389 | if (old) { |
| 390 | old->event_handler = clockevents_handle_noop; | ||
| 390 | clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED); | 391 | clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED); |
| 391 | list_del(&old->list); | 392 | list_del(&old->list); |
| 392 | list_add(&old->list, &clockevents_released); | 393 | list_add(&old->list, &clockevents_released); |
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index cfc65e1eb9fb..da2f760e780c 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c | |||
| @@ -548,7 +548,7 @@ static u64 clocksource_max_deferment(struct clocksource *cs) | |||
| 548 | * note a margin of 12.5% is used because this can be computed with | 548 | * note a margin of 12.5% is used because this can be computed with |
| 549 | * a shift, versus say 10% which would require division. | 549 | * a shift, versus say 10% which would require division. |
| 550 | */ | 550 | */ |
| 551 | return max_nsecs - (max_nsecs >> 5); | 551 | return max_nsecs - (max_nsecs >> 3); |
| 552 | } | 552 | } |
| 553 | 553 | ||
| 554 | #ifndef CONFIG_ARCH_USES_GETTIMEOFFSET | 554 | #ifndef CONFIG_ARCH_USES_GETTIMEOFFSET |
| @@ -669,7 +669,7 @@ void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq) | |||
| 669 | * ~ 0.06ppm granularity for NTP. We apply the same 12.5% | 669 | * ~ 0.06ppm granularity for NTP. We apply the same 12.5% |
| 670 | * margin as we do in clocksource_max_deferment() | 670 | * margin as we do in clocksource_max_deferment() |
| 671 | */ | 671 | */ |
| 672 | sec = (cs->mask - (cs->mask >> 5)); | 672 | sec = (cs->mask - (cs->mask >> 3)); |
| 673 | do_div(sec, freq); | 673 | do_div(sec, freq); |
| 674 | do_div(sec, scale); | 674 | do_div(sec, scale); |
| 675 | if (!sec) | 675 | if (!sec) |
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index f954282d9a82..fd4a7b1625a2 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c | |||
| @@ -71,7 +71,7 @@ int tick_check_broadcast_device(struct clock_event_device *dev) | |||
| 71 | (dev->features & CLOCK_EVT_FEAT_C3STOP)) | 71 | (dev->features & CLOCK_EVT_FEAT_C3STOP)) |
| 72 | return 0; | 72 | return 0; |
| 73 | 73 | ||
| 74 | clockevents_exchange_device(NULL, dev); | 74 | clockevents_exchange_device(tick_broadcast_device.evtdev, dev); |
| 75 | tick_broadcast_device.evtdev = dev; | 75 | tick_broadcast_device.evtdev = dev; |
| 76 | if (!cpumask_empty(tick_get_broadcast_mask())) | 76 | if (!cpumask_empty(tick_get_broadcast_mask())) |
| 77 | tick_broadcast_start_periodic(dev); | 77 | tick_broadcast_start_periodic(dev); |
