diff options
-rw-r--r-- | drivers/clocksource/Kconfig | 12 | ||||
-rw-r--r-- | drivers/clocksource/tcb_clksrc.c | 3 | ||||
-rw-r--r-- | fs/timerfd.c | 2 | ||||
-rw-r--r-- | include/linux/hrtimer.h | 34 | ||||
-rw-r--r-- | kernel/time/hrtimer.c | 55 | ||||
-rw-r--r-- | kernel/time/itimer.c | 2 | ||||
-rw-r--r-- | kernel/time/ntp.c | 14 | ||||
-rw-r--r-- | kernel/time/posix-timers.c | 2 | ||||
-rw-r--r-- | kernel/time/tick-sched.c | 16 | ||||
-rw-r--r-- | kernel/time/timer_list.c | 2 | ||||
-rw-r--r-- | tools/testing/selftests/timers/valid-adjtimex.c | 139 |
11 files changed, 245 insertions, 36 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 56777f04d2d9..33db7406c0e2 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig | |||
@@ -30,6 +30,8 @@ config CLKSRC_MMIO | |||
30 | config DIGICOLOR_TIMER | 30 | config DIGICOLOR_TIMER |
31 | bool "Digicolor timer driver" if COMPILE_TEST | 31 | bool "Digicolor timer driver" if COMPILE_TEST |
32 | depends on GENERIC_CLOCKEVENTS | 32 | depends on GENERIC_CLOCKEVENTS |
33 | select CLKSRC_MMIO | ||
34 | depends on HAS_IOMEM | ||
33 | help | 35 | help |
34 | Enables the support for the digicolor timer driver. | 36 | Enables the support for the digicolor timer driver. |
35 | 37 | ||
@@ -55,6 +57,7 @@ config ARMADA_370_XP_TIMER | |||
55 | bool "Armada 370 and XP timer driver" if COMPILE_TEST | 57 | bool "Armada 370 and XP timer driver" if COMPILE_TEST |
56 | depends on ARM | 58 | depends on ARM |
57 | select CLKSRC_OF | 59 | select CLKSRC_OF |
60 | select CLKSRC_MMIO | ||
58 | help | 61 | help |
59 | Enables the support for the Armada 370 and XP timer driver. | 62 | Enables the support for the Armada 370 and XP timer driver. |
60 | 63 | ||
@@ -76,6 +79,7 @@ config ORION_TIMER | |||
76 | config SUN4I_TIMER | 79 | config SUN4I_TIMER |
77 | bool "Sun4i timer driver" if COMPILE_TEST | 80 | bool "Sun4i timer driver" if COMPILE_TEST |
78 | depends on GENERIC_CLOCKEVENTS | 81 | depends on GENERIC_CLOCKEVENTS |
82 | depends on HAS_IOMEM | ||
79 | select CLKSRC_MMIO | 83 | select CLKSRC_MMIO |
80 | help | 84 | help |
81 | Enables support for the Sun4i timer. | 85 | Enables support for the Sun4i timer. |
@@ -89,6 +93,7 @@ config SUN5I_HSTIMER | |||
89 | 93 | ||
90 | config TEGRA_TIMER | 94 | config TEGRA_TIMER |
91 | bool "Tegra timer driver" if COMPILE_TEST | 95 | bool "Tegra timer driver" if COMPILE_TEST |
96 | select CLKSRC_MMIO | ||
92 | depends on ARM | 97 | depends on ARM |
93 | help | 98 | help |
94 | Enables support for the Tegra driver. | 99 | Enables support for the Tegra driver. |
@@ -96,6 +101,7 @@ config TEGRA_TIMER | |||
96 | config VT8500_TIMER | 101 | config VT8500_TIMER |
97 | bool "VT8500 timer driver" if COMPILE_TEST | 102 | bool "VT8500 timer driver" if COMPILE_TEST |
98 | depends on GENERIC_CLOCKEVENTS | 103 | depends on GENERIC_CLOCKEVENTS |
104 | depends on HAS_IOMEM | ||
99 | help | 105 | help |
100 | Enables support for the VT8500 driver. | 106 | Enables support for the VT8500 driver. |
101 | 107 | ||
@@ -131,6 +137,7 @@ config CLKSRC_NOMADIK_MTU_SCHED_CLOCK | |||
131 | config CLKSRC_DBX500_PRCMU | 137 | config CLKSRC_DBX500_PRCMU |
132 | bool "Clocksource PRCMU Timer" if COMPILE_TEST | 138 | bool "Clocksource PRCMU Timer" if COMPILE_TEST |
133 | depends on GENERIC_CLOCKEVENTS | 139 | depends on GENERIC_CLOCKEVENTS |
140 | depends on HAS_IOMEM | ||
134 | help | 141 | help |
135 | Use the always on PRCMU Timer as clocksource | 142 | Use the always on PRCMU Timer as clocksource |
136 | 143 | ||
@@ -248,6 +255,7 @@ config CLKSRC_EXYNOS_MCT | |||
248 | config CLKSRC_SAMSUNG_PWM | 255 | config CLKSRC_SAMSUNG_PWM |
249 | bool "PWM timer drvier for Samsung S3C, S5P" if COMPILE_TEST | 256 | bool "PWM timer drvier for Samsung S3C, S5P" if COMPILE_TEST |
250 | depends on GENERIC_CLOCKEVENTS | 257 | depends on GENERIC_CLOCKEVENTS |
258 | depends on HAS_IOMEM | ||
251 | help | 259 | help |
252 | This is a new clocksource driver for the PWM timer found in | 260 | This is a new clocksource driver for the PWM timer found in |
253 | Samsung S3C, S5P and Exynos SoCs, replacing an earlier driver | 261 | Samsung S3C, S5P and Exynos SoCs, replacing an earlier driver |
@@ -257,12 +265,14 @@ config CLKSRC_SAMSUNG_PWM | |||
257 | config FSL_FTM_TIMER | 265 | config FSL_FTM_TIMER |
258 | bool "Freescale FlexTimer Module driver" if COMPILE_TEST | 266 | bool "Freescale FlexTimer Module driver" if COMPILE_TEST |
259 | depends on GENERIC_CLOCKEVENTS | 267 | depends on GENERIC_CLOCKEVENTS |
268 | depends on HAS_IOMEM | ||
260 | select CLKSRC_MMIO | 269 | select CLKSRC_MMIO |
261 | help | 270 | help |
262 | Support for Freescale FlexTimer Module (FTM) timer. | 271 | Support for Freescale FlexTimer Module (FTM) timer. |
263 | 272 | ||
264 | config VF_PIT_TIMER | 273 | config VF_PIT_TIMER |
265 | bool | 274 | bool |
275 | select CLKSRC_MMIO | ||
266 | help | 276 | help |
267 | Support for Period Interrupt Timer on Freescale Vybrid Family SoCs. | 277 | Support for Period Interrupt Timer on Freescale Vybrid Family SoCs. |
268 | 278 | ||
@@ -360,6 +370,7 @@ config CLKSRC_TANGO_XTAL | |||
360 | config CLKSRC_PXA | 370 | config CLKSRC_PXA |
361 | bool "Clocksource for PXA or SA-11x0 platform" if COMPILE_TEST | 371 | bool "Clocksource for PXA or SA-11x0 platform" if COMPILE_TEST |
362 | depends on GENERIC_CLOCKEVENTS | 372 | depends on GENERIC_CLOCKEVENTS |
373 | depends on HAS_IOMEM | ||
363 | select CLKSRC_MMIO | 374 | select CLKSRC_MMIO |
364 | help | 375 | help |
365 | This enables OST0 support available on PXA and SA-11x0 | 376 | This enables OST0 support available on PXA and SA-11x0 |
@@ -394,6 +405,7 @@ config CLKSRC_ST_LPC | |||
394 | bool "Low power clocksource found in the LPC" if COMPILE_TEST | 405 | bool "Low power clocksource found in the LPC" if COMPILE_TEST |
395 | select CLKSRC_OF if OF | 406 | select CLKSRC_OF if OF |
396 | depends on HAS_IOMEM | 407 | depends on HAS_IOMEM |
408 | select CLKSRC_MMIO | ||
397 | help | 409 | help |
398 | Enable this option to use the Low Power controller timer | 410 | Enable this option to use the Low Power controller timer |
399 | as clocksource. | 411 | as clocksource. |
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c index 6ee91401918e..4da2af9694a2 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/tcb_clksrc.c | |||
@@ -98,7 +98,8 @@ static int tc_shutdown(struct clock_event_device *d) | |||
98 | 98 | ||
99 | __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR)); | 99 | __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR)); |
100 | __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR)); | 100 | __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR)); |
101 | clk_disable(tcd->clk); | 101 | if (!clockevent_state_detached(d)) |
102 | clk_disable(tcd->clk); | ||
102 | 103 | ||
103 | return 0; | 104 | return 0; |
104 | } | 105 | } |
diff --git a/fs/timerfd.c b/fs/timerfd.c index b94fa6c3c6eb..053818dd6c18 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c | |||
@@ -153,7 +153,7 @@ static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx) | |||
153 | if (isalarm(ctx)) | 153 | if (isalarm(ctx)) |
154 | remaining = alarm_expires_remaining(&ctx->t.alarm); | 154 | remaining = alarm_expires_remaining(&ctx->t.alarm); |
155 | else | 155 | else |
156 | remaining = hrtimer_expires_remaining(&ctx->t.tmr); | 156 | remaining = hrtimer_expires_remaining_adjusted(&ctx->t.tmr); |
157 | 157 | ||
158 | return remaining.tv64 < 0 ? ktime_set(0, 0): remaining; | 158 | return remaining.tv64 < 0 ? ktime_set(0, 0): remaining; |
159 | } | 159 | } |
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 76dd4f0da5ca..2ead22dd74a0 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
@@ -87,7 +87,8 @@ enum hrtimer_restart { | |||
87 | * @function: timer expiry callback function | 87 | * @function: timer expiry callback function |
88 | * @base: pointer to the timer base (per cpu and per clock) | 88 | * @base: pointer to the timer base (per cpu and per clock) |
89 | * @state: state information (See bit values above) | 89 | * @state: state information (See bit values above) |
90 | * @start_pid: timer statistics field to store the pid of the task which | 90 | * @is_rel: Set if the timer was armed relative |
91 | * @start_pid: timer statistics field to store the pid of the task which | ||
91 | * started the timer | 92 | * started the timer |
92 | * @start_site: timer statistics field to store the site where the timer | 93 | * @start_site: timer statistics field to store the site where the timer |
93 | * was started | 94 | * was started |
@@ -101,7 +102,8 @@ struct hrtimer { | |||
101 | ktime_t _softexpires; | 102 | ktime_t _softexpires; |
102 | enum hrtimer_restart (*function)(struct hrtimer *); | 103 | enum hrtimer_restart (*function)(struct hrtimer *); |
103 | struct hrtimer_clock_base *base; | 104 | struct hrtimer_clock_base *base; |
104 | unsigned long state; | 105 | u8 state; |
106 | u8 is_rel; | ||
105 | #ifdef CONFIG_TIMER_STATS | 107 | #ifdef CONFIG_TIMER_STATS |
106 | int start_pid; | 108 | int start_pid; |
107 | void *start_site; | 109 | void *start_site; |
@@ -321,6 +323,27 @@ static inline void clock_was_set_delayed(void) { } | |||
321 | 323 | ||
322 | #endif | 324 | #endif |
323 | 325 | ||
326 | static inline ktime_t | ||
327 | __hrtimer_expires_remaining_adjusted(const struct hrtimer *timer, ktime_t now) | ||
328 | { | ||
329 | ktime_t rem = ktime_sub(timer->node.expires, now); | ||
330 | |||
331 | /* | ||
332 | * Adjust relative timers for the extra we added in | ||
333 | * hrtimer_start_range_ns() to prevent short timeouts. | ||
334 | */ | ||
335 | if (IS_ENABLED(CONFIG_TIME_LOW_RES) && timer->is_rel) | ||
336 | rem.tv64 -= hrtimer_resolution; | ||
337 | return rem; | ||
338 | } | ||
339 | |||
340 | static inline ktime_t | ||
341 | hrtimer_expires_remaining_adjusted(const struct hrtimer *timer) | ||
342 | { | ||
343 | return __hrtimer_expires_remaining_adjusted(timer, | ||
344 | timer->base->get_time()); | ||
345 | } | ||
346 | |||
324 | extern void clock_was_set(void); | 347 | extern void clock_was_set(void); |
325 | #ifdef CONFIG_TIMERFD | 348 | #ifdef CONFIG_TIMERFD |
326 | extern void timerfd_clock_was_set(void); | 349 | extern void timerfd_clock_was_set(void); |
@@ -390,7 +413,12 @@ static inline void hrtimer_restart(struct hrtimer *timer) | |||
390 | } | 413 | } |
391 | 414 | ||
392 | /* Query timers: */ | 415 | /* Query timers: */ |
393 | extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer); | 416 | extern ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust); |
417 | |||
418 | static inline ktime_t hrtimer_get_remaining(const struct hrtimer *timer) | ||
419 | { | ||
420 | return __hrtimer_get_remaining(timer, false); | ||
421 | } | ||
394 | 422 | ||
395 | extern u64 hrtimer_get_next_event(void); | 423 | extern u64 hrtimer_get_next_event(void); |
396 | 424 | ||
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 435b8850dd80..fa909f9fd559 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c | |||
@@ -897,10 +897,10 @@ static int enqueue_hrtimer(struct hrtimer *timer, | |||
897 | */ | 897 | */ |
898 | static void __remove_hrtimer(struct hrtimer *timer, | 898 | static void __remove_hrtimer(struct hrtimer *timer, |
899 | struct hrtimer_clock_base *base, | 899 | struct hrtimer_clock_base *base, |
900 | unsigned long newstate, int reprogram) | 900 | u8 newstate, int reprogram) |
901 | { | 901 | { |
902 | struct hrtimer_cpu_base *cpu_base = base->cpu_base; | 902 | struct hrtimer_cpu_base *cpu_base = base->cpu_base; |
903 | unsigned int state = timer->state; | 903 | u8 state = timer->state; |
904 | 904 | ||
905 | timer->state = newstate; | 905 | timer->state = newstate; |
906 | if (!(state & HRTIMER_STATE_ENQUEUED)) | 906 | if (!(state & HRTIMER_STATE_ENQUEUED)) |
@@ -930,7 +930,7 @@ static inline int | |||
930 | remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool restart) | 930 | remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool restart) |
931 | { | 931 | { |
932 | if (hrtimer_is_queued(timer)) { | 932 | if (hrtimer_is_queued(timer)) { |
933 | unsigned long state = timer->state; | 933 | u8 state = timer->state; |
934 | int reprogram; | 934 | int reprogram; |
935 | 935 | ||
936 | /* | 936 | /* |
@@ -954,6 +954,22 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool rest | |||
954 | return 0; | 954 | return 0; |
955 | } | 955 | } |
956 | 956 | ||
957 | static inline ktime_t hrtimer_update_lowres(struct hrtimer *timer, ktime_t tim, | ||
958 | const enum hrtimer_mode mode) | ||
959 | { | ||
960 | #ifdef CONFIG_TIME_LOW_RES | ||
961 | /* | ||
962 | * CONFIG_TIME_LOW_RES indicates that the system has no way to return | ||
963 | * granular time values. For relative timers we add hrtimer_resolution | ||
964 | * (i.e. one jiffie) to prevent short timeouts. | ||
965 | */ | ||
966 | timer->is_rel = mode & HRTIMER_MODE_REL; | ||
967 | if (timer->is_rel) | ||
968 | tim = ktime_add_safe(tim, ktime_set(0, hrtimer_resolution)); | ||
969 | #endif | ||
970 | return tim; | ||
971 | } | ||
972 | |||
957 | /** | 973 | /** |
958 | * hrtimer_start_range_ns - (re)start an hrtimer on the current CPU | 974 | * hrtimer_start_range_ns - (re)start an hrtimer on the current CPU |
959 | * @timer: the timer to be added | 975 | * @timer: the timer to be added |
@@ -974,19 +990,10 @@ void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, | |||
974 | /* Remove an active timer from the queue: */ | 990 | /* Remove an active timer from the queue: */ |
975 | remove_hrtimer(timer, base, true); | 991 | remove_hrtimer(timer, base, true); |
976 | 992 | ||
977 | if (mode & HRTIMER_MODE_REL) { | 993 | if (mode & HRTIMER_MODE_REL) |
978 | tim = ktime_add_safe(tim, base->get_time()); | 994 | tim = ktime_add_safe(tim, base->get_time()); |
979 | /* | 995 | |
980 | * CONFIG_TIME_LOW_RES is a temporary way for architectures | 996 | tim = hrtimer_update_lowres(timer, tim, mode); |
981 | * to signal that they simply return xtime in | ||
982 | * do_gettimeoffset(). In this case we want to round up by | ||
983 | * resolution when starting a relative timer, to avoid short | ||
984 | * timeouts. This will go away with the GTOD framework. | ||
985 | */ | ||
986 | #ifdef CONFIG_TIME_LOW_RES | ||
987 | tim = ktime_add_safe(tim, ktime_set(0, hrtimer_resolution)); | ||
988 | #endif | ||
989 | } | ||
990 | 997 | ||
991 | hrtimer_set_expires_range_ns(timer, tim, delta_ns); | 998 | hrtimer_set_expires_range_ns(timer, tim, delta_ns); |
992 | 999 | ||
@@ -1074,19 +1081,23 @@ EXPORT_SYMBOL_GPL(hrtimer_cancel); | |||
1074 | /** | 1081 | /** |
1075 | * hrtimer_get_remaining - get remaining time for the timer | 1082 | * hrtimer_get_remaining - get remaining time for the timer |
1076 | * @timer: the timer to read | 1083 | * @timer: the timer to read |
1084 | * @adjust: adjust relative timers when CONFIG_TIME_LOW_RES=y | ||
1077 | */ | 1085 | */ |
1078 | ktime_t hrtimer_get_remaining(const struct hrtimer *timer) | 1086 | ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust) |
1079 | { | 1087 | { |
1080 | unsigned long flags; | 1088 | unsigned long flags; |
1081 | ktime_t rem; | 1089 | ktime_t rem; |
1082 | 1090 | ||
1083 | lock_hrtimer_base(timer, &flags); | 1091 | lock_hrtimer_base(timer, &flags); |
1084 | rem = hrtimer_expires_remaining(timer); | 1092 | if (IS_ENABLED(CONFIG_TIME_LOW_RES) && adjust) |
1093 | rem = hrtimer_expires_remaining_adjusted(timer); | ||
1094 | else | ||
1095 | rem = hrtimer_expires_remaining(timer); | ||
1085 | unlock_hrtimer_base(timer, &flags); | 1096 | unlock_hrtimer_base(timer, &flags); |
1086 | 1097 | ||
1087 | return rem; | 1098 | return rem; |
1088 | } | 1099 | } |
1089 | EXPORT_SYMBOL_GPL(hrtimer_get_remaining); | 1100 | EXPORT_SYMBOL_GPL(__hrtimer_get_remaining); |
1090 | 1101 | ||
1091 | #ifdef CONFIG_NO_HZ_COMMON | 1102 | #ifdef CONFIG_NO_HZ_COMMON |
1092 | /** | 1103 | /** |
@@ -1220,6 +1231,14 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base, | |||
1220 | fn = timer->function; | 1231 | fn = timer->function; |
1221 | 1232 | ||
1222 | /* | 1233 | /* |
1234 | * Clear the 'is relative' flag for the TIME_LOW_RES case. If the | ||
1235 | * timer is restarted with a period then it becomes an absolute | ||
1236 | * timer. If its not restarted it does not matter. | ||
1237 | */ | ||
1238 | if (IS_ENABLED(CONFIG_TIME_LOW_RES)) | ||
1239 | timer->is_rel = false; | ||
1240 | |||
1241 | /* | ||
1223 | * Because we run timers from hardirq context, there is no chance | 1242 | * Because we run timers from hardirq context, there is no chance |
1224 | * they get migrated to another cpu, therefore its safe to unlock | 1243 | * they get migrated to another cpu, therefore its safe to unlock |
1225 | * the timer base. | 1244 | * the timer base. |
diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c index 8d262b467573..1d5c7204ddc9 100644 --- a/kernel/time/itimer.c +++ b/kernel/time/itimer.c | |||
@@ -26,7 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | static struct timeval itimer_get_remtime(struct hrtimer *timer) | 27 | static struct timeval itimer_get_remtime(struct hrtimer *timer) |
28 | { | 28 | { |
29 | ktime_t rem = hrtimer_get_remaining(timer); | 29 | ktime_t rem = __hrtimer_get_remaining(timer, true); |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * Racy but safe: if the itimer expires after the above | 32 | * Racy but safe: if the itimer expires after the above |
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 36f2ca09aa5e..6df8927c58a5 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -685,8 +685,18 @@ int ntp_validate_timex(struct timex *txc) | |||
685 | if (!capable(CAP_SYS_TIME)) | 685 | if (!capable(CAP_SYS_TIME)) |
686 | return -EPERM; | 686 | return -EPERM; |
687 | 687 | ||
688 | if (!timeval_inject_offset_valid(&txc->time)) | 688 | if (txc->modes & ADJ_NANO) { |
689 | return -EINVAL; | 689 | struct timespec ts; |
690 | |||
691 | ts.tv_sec = txc->time.tv_sec; | ||
692 | ts.tv_nsec = txc->time.tv_usec; | ||
693 | if (!timespec_inject_offset_valid(&ts)) | ||
694 | return -EINVAL; | ||
695 | |||
696 | } else { | ||
697 | if (!timeval_inject_offset_valid(&txc->time)) | ||
698 | return -EINVAL; | ||
699 | } | ||
690 | } | 700 | } |
691 | 701 | ||
692 | /* | 702 | /* |
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 31d11ac9fa47..f2826c35e918 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c | |||
@@ -760,7 +760,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) | |||
760 | (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) | 760 | (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) |
761 | timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv); | 761 | timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv); |
762 | 762 | ||
763 | remaining = ktime_sub(hrtimer_get_expires(timer), now); | 763 | remaining = __hrtimer_expires_remaining_adjusted(timer, now); |
764 | /* Return 0 only, when the timer is expired and not pending */ | 764 | /* Return 0 only, when the timer is expired and not pending */ |
765 | if (remaining.tv64 <= 0) { | 765 | if (remaining.tv64 <= 0) { |
766 | /* | 766 | /* |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 9d7a053545f5..0b17424349eb 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -36,16 +36,17 @@ | |||
36 | */ | 36 | */ |
37 | static DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched); | 37 | static DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched); |
38 | 38 | ||
39 | /* | ||
40 | * The time, when the last jiffy update happened. Protected by jiffies_lock. | ||
41 | */ | ||
42 | static ktime_t last_jiffies_update; | ||
43 | |||
44 | struct tick_sched *tick_get_tick_sched(int cpu) | 39 | struct tick_sched *tick_get_tick_sched(int cpu) |
45 | { | 40 | { |
46 | return &per_cpu(tick_cpu_sched, cpu); | 41 | return &per_cpu(tick_cpu_sched, cpu); |
47 | } | 42 | } |
48 | 43 | ||
44 | #if defined(CONFIG_NO_HZ_COMMON) || defined(CONFIG_HIGH_RES_TIMERS) | ||
45 | /* | ||
46 | * The time, when the last jiffy update happened. Protected by jiffies_lock. | ||
47 | */ | ||
48 | static ktime_t last_jiffies_update; | ||
49 | |||
49 | /* | 50 | /* |
50 | * Must be called with interrupts disabled ! | 51 | * Must be called with interrupts disabled ! |
51 | */ | 52 | */ |
@@ -151,6 +152,7 @@ static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs) | |||
151 | update_process_times(user_mode(regs)); | 152 | update_process_times(user_mode(regs)); |
152 | profile_tick(CPU_PROFILING); | 153 | profile_tick(CPU_PROFILING); |
153 | } | 154 | } |
155 | #endif | ||
154 | 156 | ||
155 | #ifdef CONFIG_NO_HZ_FULL | 157 | #ifdef CONFIG_NO_HZ_FULL |
156 | cpumask_var_t tick_nohz_full_mask; | 158 | cpumask_var_t tick_nohz_full_mask; |
@@ -993,9 +995,9 @@ static void tick_nohz_switch_to_nohz(void) | |||
993 | /* Get the next period */ | 995 | /* Get the next period */ |
994 | next = tick_init_jiffy_update(); | 996 | next = tick_init_jiffy_update(); |
995 | 997 | ||
996 | hrtimer_forward_now(&ts->sched_timer, tick_period); | ||
997 | hrtimer_set_expires(&ts->sched_timer, next); | 998 | hrtimer_set_expires(&ts->sched_timer, next); |
998 | tick_program_event(next, 1); | 999 | hrtimer_forward_now(&ts->sched_timer, tick_period); |
1000 | tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1); | ||
999 | tick_nohz_activate(ts, NOHZ_MODE_LOWRES); | 1001 | tick_nohz_activate(ts, NOHZ_MODE_LOWRES); |
1000 | } | 1002 | } |
1001 | 1003 | ||
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index f75e35b60149..ba7d8b288bb3 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c | |||
@@ -69,7 +69,7 @@ print_timer(struct seq_file *m, struct hrtimer *taddr, struct hrtimer *timer, | |||
69 | print_name_offset(m, taddr); | 69 | print_name_offset(m, taddr); |
70 | SEQ_printf(m, ", "); | 70 | SEQ_printf(m, ", "); |
71 | print_name_offset(m, timer->function); | 71 | print_name_offset(m, timer->function); |
72 | SEQ_printf(m, ", S:%02lx", timer->state); | 72 | SEQ_printf(m, ", S:%02x", timer->state); |
73 | #ifdef CONFIG_TIMER_STATS | 73 | #ifdef CONFIG_TIMER_STATS |
74 | SEQ_printf(m, ", "); | 74 | SEQ_printf(m, ", "); |
75 | print_name_offset(m, timer->start_site); | 75 | print_name_offset(m, timer->start_site); |
diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c index e86d937cc22c..60fe3c569bd9 100644 --- a/tools/testing/selftests/timers/valid-adjtimex.c +++ b/tools/testing/selftests/timers/valid-adjtimex.c | |||
@@ -45,7 +45,17 @@ static inline int ksft_exit_fail(void) | |||
45 | } | 45 | } |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #define NSEC_PER_SEC 1000000000L | 48 | #define NSEC_PER_SEC 1000000000LL |
49 | #define USEC_PER_SEC 1000000LL | ||
50 | |||
51 | #define ADJ_SETOFFSET 0x0100 | ||
52 | |||
53 | #include <sys/syscall.h> | ||
54 | static int clock_adjtime(clockid_t id, struct timex *tx) | ||
55 | { | ||
56 | return syscall(__NR_clock_adjtime, id, tx); | ||
57 | } | ||
58 | |||
49 | 59 | ||
50 | /* clear NTP time_status & time_state */ | 60 | /* clear NTP time_status & time_state */ |
51 | int clear_time_state(void) | 61 | int clear_time_state(void) |
@@ -193,10 +203,137 @@ out: | |||
193 | } | 203 | } |
194 | 204 | ||
195 | 205 | ||
206 | int set_offset(long long offset, int use_nano) | ||
207 | { | ||
208 | struct timex tmx = {}; | ||
209 | int ret; | ||
210 | |||
211 | tmx.modes = ADJ_SETOFFSET; | ||
212 | if (use_nano) { | ||
213 | tmx.modes |= ADJ_NANO; | ||
214 | |||
215 | tmx.time.tv_sec = offset / NSEC_PER_SEC; | ||
216 | tmx.time.tv_usec = offset % NSEC_PER_SEC; | ||
217 | |||
218 | if (offset < 0 && tmx.time.tv_usec) { | ||
219 | tmx.time.tv_sec -= 1; | ||
220 | tmx.time.tv_usec += NSEC_PER_SEC; | ||
221 | } | ||
222 | } else { | ||
223 | tmx.time.tv_sec = offset / USEC_PER_SEC; | ||
224 | tmx.time.tv_usec = offset % USEC_PER_SEC; | ||
225 | |||
226 | if (offset < 0 && tmx.time.tv_usec) { | ||
227 | tmx.time.tv_sec -= 1; | ||
228 | tmx.time.tv_usec += USEC_PER_SEC; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | ret = clock_adjtime(CLOCK_REALTIME, &tmx); | ||
233 | if (ret < 0) { | ||
234 | printf("(sec: %ld usec: %ld) ", tmx.time.tv_sec, tmx.time.tv_usec); | ||
235 | printf("[FAIL]\n"); | ||
236 | return -1; | ||
237 | } | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | int set_bad_offset(long sec, long usec, int use_nano) | ||
242 | { | ||
243 | struct timex tmx = {}; | ||
244 | int ret; | ||
245 | |||
246 | tmx.modes = ADJ_SETOFFSET; | ||
247 | if (use_nano) | ||
248 | tmx.modes |= ADJ_NANO; | ||
249 | |||
250 | tmx.time.tv_sec = sec; | ||
251 | tmx.time.tv_usec = usec; | ||
252 | ret = clock_adjtime(CLOCK_REALTIME, &tmx); | ||
253 | if (ret >= 0) { | ||
254 | printf("Invalid (sec: %ld usec: %ld) did not fail! ", tmx.time.tv_sec, tmx.time.tv_usec); | ||
255 | printf("[FAIL]\n"); | ||
256 | return -1; | ||
257 | } | ||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | int validate_set_offset(void) | ||
262 | { | ||
263 | printf("Testing ADJ_SETOFFSET... "); | ||
264 | |||
265 | /* Test valid values */ | ||
266 | if (set_offset(NSEC_PER_SEC - 1, 1)) | ||
267 | return -1; | ||
268 | |||
269 | if (set_offset(-NSEC_PER_SEC + 1, 1)) | ||
270 | return -1; | ||
271 | |||
272 | if (set_offset(-NSEC_PER_SEC - 1, 1)) | ||
273 | return -1; | ||
274 | |||
275 | if (set_offset(5 * NSEC_PER_SEC, 1)) | ||
276 | return -1; | ||
277 | |||
278 | if (set_offset(-5 * NSEC_PER_SEC, 1)) | ||
279 | return -1; | ||
280 | |||
281 | if (set_offset(5 * NSEC_PER_SEC + NSEC_PER_SEC / 2, 1)) | ||
282 | return -1; | ||
283 | |||
284 | if (set_offset(-5 * NSEC_PER_SEC - NSEC_PER_SEC / 2, 1)) | ||
285 | return -1; | ||
286 | |||
287 | if (set_offset(USEC_PER_SEC - 1, 0)) | ||
288 | return -1; | ||
289 | |||
290 | if (set_offset(-USEC_PER_SEC + 1, 0)) | ||
291 | return -1; | ||
292 | |||
293 | if (set_offset(-USEC_PER_SEC - 1, 0)) | ||
294 | return -1; | ||
295 | |||
296 | if (set_offset(5 * USEC_PER_SEC, 0)) | ||
297 | return -1; | ||
298 | |||
299 | if (set_offset(-5 * USEC_PER_SEC, 0)) | ||
300 | return -1; | ||
301 | |||
302 | if (set_offset(5 * USEC_PER_SEC + USEC_PER_SEC / 2, 0)) | ||
303 | return -1; | ||
304 | |||
305 | if (set_offset(-5 * USEC_PER_SEC - USEC_PER_SEC / 2, 0)) | ||
306 | return -1; | ||
307 | |||
308 | /* Test invalid values */ | ||
309 | if (set_bad_offset(0, -1, 1)) | ||
310 | return -1; | ||
311 | if (set_bad_offset(0, -1, 0)) | ||
312 | return -1; | ||
313 | if (set_bad_offset(0, 2 * NSEC_PER_SEC, 1)) | ||
314 | return -1; | ||
315 | if (set_bad_offset(0, 2 * USEC_PER_SEC, 0)) | ||
316 | return -1; | ||
317 | if (set_bad_offset(0, NSEC_PER_SEC, 1)) | ||
318 | return -1; | ||
319 | if (set_bad_offset(0, USEC_PER_SEC, 0)) | ||
320 | return -1; | ||
321 | if (set_bad_offset(0, -NSEC_PER_SEC, 1)) | ||
322 | return -1; | ||
323 | if (set_bad_offset(0, -USEC_PER_SEC, 0)) | ||
324 | return -1; | ||
325 | |||
326 | printf("[OK]\n"); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
196 | int main(int argc, char **argv) | 330 | int main(int argc, char **argv) |
197 | { | 331 | { |
198 | if (validate_freq()) | 332 | if (validate_freq()) |
199 | return ksft_exit_fail(); | 333 | return ksft_exit_fail(); |
200 | 334 | ||
335 | if (validate_set_offset()) | ||
336 | return ksft_exit_fail(); | ||
337 | |||
201 | return ksft_exit_pass(); | 338 | return ksft_exit_pass(); |
202 | } | 339 | } |