diff options
-rw-r--r-- | include/linux/timex.h | 7 | ||||
-rw-r--r-- | kernel/time.c | 25 | ||||
-rw-r--r-- | kernel/timer.c | 53 |
3 files changed, 24 insertions, 61 deletions
diff --git a/include/linux/timex.h b/include/linux/timex.h index 7e050a2cc35b..04a4a8cb4ed3 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h | |||
@@ -282,6 +282,13 @@ static inline int ntp_synced(void) | |||
282 | return !(time_status & STA_UNSYNC); | 282 | return !(time_status & STA_UNSYNC); |
283 | } | 283 | } |
284 | 284 | ||
285 | /* Required to safely shift negative values */ | ||
286 | #define shift_right(x, s) ({ \ | ||
287 | __typeof__(x) __x = (x); \ | ||
288 | __typeof__(s) __s = (s); \ | ||
289 | __x < 0 ? -(-__x >> __s) : __x >> __s; \ | ||
290 | }) | ||
291 | |||
285 | 292 | ||
286 | #ifdef CONFIG_TIME_INTERPOLATION | 293 | #ifdef CONFIG_TIME_INTERPOLATION |
287 | 294 | ||
diff --git a/kernel/time.c b/kernel/time.c index a3c2100470e1..245d595a13cb 100644 --- a/kernel/time.c +++ b/kernel/time.c | |||
@@ -338,30 +338,20 @@ int do_adjtimex(struct timex *txc) | |||
338 | if (mtemp >= MINSEC) { | 338 | if (mtemp >= MINSEC) { |
339 | ltemp = (time_offset / mtemp) << (SHIFT_USEC - | 339 | ltemp = (time_offset / mtemp) << (SHIFT_USEC - |
340 | SHIFT_UPDATE); | 340 | SHIFT_UPDATE); |
341 | if (ltemp < 0) | 341 | time_freq += shift_right(ltemp, SHIFT_KH); |
342 | time_freq -= -ltemp >> SHIFT_KH; | ||
343 | else | ||
344 | time_freq += ltemp >> SHIFT_KH; | ||
345 | } else /* calibration interval too short (p. 12) */ | 342 | } else /* calibration interval too short (p. 12) */ |
346 | result = TIME_ERROR; | 343 | result = TIME_ERROR; |
347 | } else { /* PLL mode */ | 344 | } else { /* PLL mode */ |
348 | if (mtemp < MAXSEC) { | 345 | if (mtemp < MAXSEC) { |
349 | ltemp *= mtemp; | 346 | ltemp *= mtemp; |
350 | if (ltemp < 0) | 347 | time_freq += shift_right(ltemp,(time_constant + |
351 | time_freq -= -ltemp >> (time_constant + | ||
352 | time_constant + | ||
353 | SHIFT_KF - SHIFT_USEC); | ||
354 | else | ||
355 | time_freq += ltemp >> (time_constant + | ||
356 | time_constant + | 348 | time_constant + |
357 | SHIFT_KF - SHIFT_USEC); | 349 | SHIFT_KF - SHIFT_USEC)); |
358 | } else /* calibration interval too long (p. 12) */ | 350 | } else /* calibration interval too long (p. 12) */ |
359 | result = TIME_ERROR; | 351 | result = TIME_ERROR; |
360 | } | 352 | } |
361 | if (time_freq > time_tolerance) | 353 | time_freq = min(time_freq, time_tolerance); |
362 | time_freq = time_tolerance; | 354 | time_freq = max(time_freq, -time_tolerance); |
363 | else if (time_freq < -time_tolerance) | ||
364 | time_freq = -time_tolerance; | ||
365 | } /* STA_PLL || STA_PPSTIME */ | 355 | } /* STA_PLL || STA_PPSTIME */ |
366 | } /* txc->modes & ADJ_OFFSET */ | 356 | } /* txc->modes & ADJ_OFFSET */ |
367 | if (txc->modes & ADJ_TICK) { | 357 | if (txc->modes & ADJ_TICK) { |
@@ -384,10 +374,7 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0 | |||
384 | if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) | 374 | if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) |
385 | txc->offset = save_adjust; | 375 | txc->offset = save_adjust; |
386 | else { | 376 | else { |
387 | if (time_offset < 0) | 377 | txc->offset = shift_right(time_offset, SHIFT_UPDATE); |
388 | txc->offset = -(-time_offset >> SHIFT_UPDATE); | ||
389 | else | ||
390 | txc->offset = time_offset >> SHIFT_UPDATE; | ||
391 | } | 378 | } |
392 | txc->freq = time_freq + pps_freq; | 379 | txc->freq = time_freq + pps_freq; |
393 | txc->maxerror = time_maxerror; | 380 | txc->maxerror = time_maxerror; |
diff --git a/kernel/timer.c b/kernel/timer.c index 6ed1a826e5ce..6b94adb45b03 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -703,23 +703,13 @@ static void second_overflow(void) | |||
703 | * the adjustment over not more than the number of | 703 | * the adjustment over not more than the number of |
704 | * seconds between updates. | 704 | * seconds between updates. |
705 | */ | 705 | */ |
706 | if (time_offset < 0) { | ||
707 | ltemp = -time_offset; | ||
708 | if (!(time_status & STA_FLL)) | ||
709 | ltemp >>= SHIFT_KG + time_constant; | ||
710 | if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE) | ||
711 | ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE; | ||
712 | time_offset += ltemp; | ||
713 | time_adj = -ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE); | ||
714 | } else { | ||
715 | ltemp = time_offset; | 706 | ltemp = time_offset; |
716 | if (!(time_status & STA_FLL)) | 707 | if (!(time_status & STA_FLL)) |
717 | ltemp >>= SHIFT_KG + time_constant; | 708 | ltemp = shift_right(ltemp, SHIFT_KG + time_constant); |
718 | if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE) | 709 | ltemp = min(ltemp, (MAXPHASE / MINSEC) << SHIFT_UPDATE); |
719 | ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE; | 710 | ltemp = max(ltemp, -(MAXPHASE / MINSEC) << SHIFT_UPDATE); |
720 | time_offset -= ltemp; | 711 | time_offset -= ltemp; |
721 | time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE); | 712 | time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE); |
722 | } | ||
723 | 713 | ||
724 | /* | 714 | /* |
725 | * Compute the frequency estimate and additional phase | 715 | * Compute the frequency estimate and additional phase |
@@ -736,39 +726,25 @@ static void second_overflow(void) | |||
736 | STA_PPSWANDER | STA_PPSERROR); | 726 | STA_PPSWANDER | STA_PPSERROR); |
737 | } | 727 | } |
738 | ltemp = time_freq + pps_freq; | 728 | ltemp = time_freq + pps_freq; |
739 | if (ltemp < 0) | 729 | time_adj += shift_right(ltemp,(SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE)); |
740 | time_adj -= -ltemp >> | ||
741 | (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE); | ||
742 | else | ||
743 | time_adj += ltemp >> | ||
744 | (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE); | ||
745 | 730 | ||
746 | #if HZ == 100 | 731 | #if HZ == 100 |
747 | /* Compensate for (HZ==100) != (1 << SHIFT_HZ). | 732 | /* Compensate for (HZ==100) != (1 << SHIFT_HZ). |
748 | * Add 25% and 3.125% to get 128.125; => only 0.125% error (p. 14) | 733 | * Add 25% and 3.125% to get 128.125; => only 0.125% error (p. 14) |
749 | */ | 734 | */ |
750 | if (time_adj < 0) | 735 | time_adj += shift_right(time_adj, 2) + shift_right(time_adj, 5); |
751 | time_adj -= (-time_adj >> 2) + (-time_adj >> 5); | ||
752 | else | ||
753 | time_adj += (time_adj >> 2) + (time_adj >> 5); | ||
754 | #endif | 736 | #endif |
755 | #if HZ == 250 | 737 | #if HZ == 250 |
756 | /* Compensate for (HZ==250) != (1 << SHIFT_HZ). | 738 | /* Compensate for (HZ==250) != (1 << SHIFT_HZ). |
757 | * Add 1.5625% and 0.78125% to get 255.85938; => only 0.05% error (p. 14) | 739 | * Add 1.5625% and 0.78125% to get 255.85938; => only 0.05% error (p. 14) |
758 | */ | 740 | */ |
759 | if (time_adj < 0) | 741 | time_adj += shift_right(time_adj, 6) + shift_right(time_adj, 7); |
760 | time_adj -= (-time_adj >> 6) + (-time_adj >> 7); | ||
761 | else | ||
762 | time_adj += (time_adj >> 6) + (time_adj >> 7); | ||
763 | #endif | 742 | #endif |
764 | #if HZ == 1000 | 743 | #if HZ == 1000 |
765 | /* Compensate for (HZ==1000) != (1 << SHIFT_HZ). | 744 | /* Compensate for (HZ==1000) != (1 << SHIFT_HZ). |
766 | * Add 1.5625% and 0.78125% to get 1023.4375; => only 0.05% error (p. 14) | 745 | * Add 1.5625% and 0.78125% to get 1023.4375; => only 0.05% error (p. 14) |
767 | */ | 746 | */ |
768 | if (time_adj < 0) | 747 | time_adj += shift_right(time_adj, 6) + shift_right(time_adj, 7); |
769 | time_adj -= (-time_adj >> 6) + (-time_adj >> 7); | ||
770 | else | ||
771 | time_adj += (time_adj >> 6) + (time_adj >> 7); | ||
772 | #endif | 748 | #endif |
773 | } | 749 | } |
774 | 750 | ||
@@ -787,10 +763,8 @@ static void update_wall_time_one_tick(void) | |||
787 | * Limit the amount of the step to be in the range | 763 | * Limit the amount of the step to be in the range |
788 | * -tickadj .. +tickadj | 764 | * -tickadj .. +tickadj |
789 | */ | 765 | */ |
790 | if (time_adjust > tickadj) | 766 | time_adjust_step = min(time_adjust_step, (long)tickadj); |
791 | time_adjust_step = tickadj; | 767 | time_adjust_step = max(time_adjust_step, (long)-tickadj); |
792 | else if (time_adjust < -tickadj) | ||
793 | time_adjust_step = -tickadj; | ||
794 | 768 | ||
795 | /* Reduce by this step the amount of time left */ | 769 | /* Reduce by this step the amount of time left */ |
796 | time_adjust -= time_adjust_step; | 770 | time_adjust -= time_adjust_step; |
@@ -801,13 +775,8 @@ static void update_wall_time_one_tick(void) | |||
801 | * advance the tick more. | 775 | * advance the tick more. |
802 | */ | 776 | */ |
803 | time_phase += time_adj; | 777 | time_phase += time_adj; |
804 | if (time_phase <= -FINENSEC) { | 778 | if ((time_phase >= FINENSEC) || (time_phase <= -FINENSEC)) { |
805 | long ltemp = -time_phase >> (SHIFT_SCALE - 10); | 779 | long ltemp = shift_right(time_phase, (SHIFT_SCALE - 10)); |
806 | time_phase += ltemp << (SHIFT_SCALE - 10); | ||
807 | delta_nsec -= ltemp; | ||
808 | } | ||
809 | else if (time_phase >= FINENSEC) { | ||
810 | long ltemp = time_phase >> (SHIFT_SCALE - 10); | ||
811 | time_phase -= ltemp << (SHIFT_SCALE - 10); | 780 | time_phase -= ltemp << (SHIFT_SCALE - 10); |
812 | delta_nsec += ltemp; | 781 | delta_nsec += ltemp; |
813 | } | 782 | } |