Commit 82644459c592a28a3eab682f9b88d81019ddfe8b
Committed by
Linus Torvalds
1 parent
99bc2fcb28
Exists in
master
and in
7 other branches
NTP: move the cmos update code into ntp.c
i386 and sparc64 have the identical code to update the cmos clock. Move it into kernel/time/ntp.c as there are other architectures coming along with the same requirements. [akpm@linux-foundation.org: build fixes] Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Chris Wright <chrisw@sous-sol.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: john stultz <johnstul@us.ibm.com> Cc: David Miller <davem@davemloft.net> Cc: Roman Zippel <zippel@linux-m68k.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 7 changed files with 71 additions and 103 deletions Side-by-side Diff
arch/i386/Kconfig
arch/i386/kernel/time.c
... | ... | @@ -207,55 +207,9 @@ |
207 | 207 | return retval; |
208 | 208 | } |
209 | 209 | |
210 | -static void sync_cmos_clock(unsigned long dummy); | |
211 | - | |
212 | -static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0); | |
213 | -int no_sync_cmos_clock; | |
214 | - | |
215 | -static void sync_cmos_clock(unsigned long dummy) | |
210 | +int update_persistent_clock(struct timespec now) | |
216 | 211 | { |
217 | - struct timeval now, next; | |
218 | - int fail = 1; | |
219 | - | |
220 | - /* | |
221 | - * If we have an externally synchronized Linux clock, then update | |
222 | - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be | |
223 | - * called as close as possible to 500 ms before the new second starts. | |
224 | - * This code is run on a timer. If the clock is set, that timer | |
225 | - * may not expire at the correct time. Thus, we adjust... | |
226 | - */ | |
227 | - if (!ntp_synced()) | |
228 | - /* | |
229 | - * Not synced, exit, do not restart a timer (if one is | |
230 | - * running, let it run out). | |
231 | - */ | |
232 | - return; | |
233 | - | |
234 | - do_gettimeofday(&now); | |
235 | - if (now.tv_usec >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 && | |
236 | - now.tv_usec <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2) | |
237 | - fail = set_rtc_mmss(now.tv_sec); | |
238 | - | |
239 | - next.tv_usec = USEC_AFTER - now.tv_usec; | |
240 | - if (next.tv_usec <= 0) | |
241 | - next.tv_usec += USEC_PER_SEC; | |
242 | - | |
243 | - if (!fail) | |
244 | - next.tv_sec = 659; | |
245 | - else | |
246 | - next.tv_sec = 0; | |
247 | - | |
248 | - if (next.tv_usec >= USEC_PER_SEC) { | |
249 | - next.tv_sec++; | |
250 | - next.tv_usec -= USEC_PER_SEC; | |
251 | - } | |
252 | - mod_timer(&sync_cmos_timer, jiffies + timeval_to_jiffies(&next)); | |
253 | -} | |
254 | - | |
255 | -void notify_arch_cmos_timer(void) | |
256 | -{ | |
257 | - if (!no_sync_cmos_clock) | |
258 | - mod_timer(&sync_cmos_timer, jiffies + 1); | |
212 | + return set_rtc_mmss(now.tv_sec); | |
259 | 213 | } |
260 | 214 | |
261 | 215 | extern void (*late_time_init)(void); |
arch/sparc64/Kconfig
arch/sparc64/kernel/time.c
... | ... | @@ -403,58 +403,9 @@ |
403 | 403 | |
404 | 404 | static unsigned long timer_ticks_per_nsec_quotient __read_mostly; |
405 | 405 | |
406 | -#define TICK_SIZE (tick_nsec / 1000) | |
407 | - | |
408 | -#define USEC_AFTER 500000 | |
409 | -#define USEC_BEFORE 500000 | |
410 | - | |
411 | -static void sync_cmos_clock(unsigned long dummy); | |
412 | - | |
413 | -static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0); | |
414 | - | |
415 | -static void sync_cmos_clock(unsigned long dummy) | |
406 | +int update_persistent_clock(struct timespec now) | |
416 | 407 | { |
417 | - struct timeval now, next; | |
418 | - int fail = 1; | |
419 | - | |
420 | - /* | |
421 | - * If we have an externally synchronized Linux clock, then update | |
422 | - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be | |
423 | - * called as close as possible to 500 ms before the new second starts. | |
424 | - * This code is run on a timer. If the clock is set, that timer | |
425 | - * may not expire at the correct time. Thus, we adjust... | |
426 | - */ | |
427 | - if (!ntp_synced()) | |
428 | - /* | |
429 | - * Not synced, exit, do not restart a timer (if one is | |
430 | - * running, let it run out). | |
431 | - */ | |
432 | - return; | |
433 | - | |
434 | - do_gettimeofday(&now); | |
435 | - if (now.tv_usec >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 && | |
436 | - now.tv_usec <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2) | |
437 | - fail = set_rtc_mmss(now.tv_sec); | |
438 | - | |
439 | - next.tv_usec = USEC_AFTER - now.tv_usec; | |
440 | - if (next.tv_usec <= 0) | |
441 | - next.tv_usec += USEC_PER_SEC; | |
442 | - | |
443 | - if (!fail) | |
444 | - next.tv_sec = 659; | |
445 | - else | |
446 | - next.tv_sec = 0; | |
447 | - | |
448 | - if (next.tv_usec >= USEC_PER_SEC) { | |
449 | - next.tv_sec++; | |
450 | - next.tv_usec -= USEC_PER_SEC; | |
451 | - } | |
452 | - mod_timer(&sync_cmos_timer, jiffies + timeval_to_jiffies(&next)); | |
453 | -} | |
454 | - | |
455 | -void notify_arch_cmos_timer(void) | |
456 | -{ | |
457 | - mod_timer(&sync_cmos_timer, jiffies + 1); | |
408 | + return set_rtc_mmss(now.tv_sec); | |
458 | 409 | } |
459 | 410 | |
460 | 411 | /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ |
include/asm-i386/timer.h
include/linux/time.h
... | ... | @@ -4,6 +4,7 @@ |
4 | 4 | #include <linux/types.h> |
5 | 5 | |
6 | 6 | #ifdef __KERNEL__ |
7 | +# include <linux/cache.h> | |
7 | 8 | # include <linux/seqlock.h> |
8 | 9 | #endif |
9 | 10 | |
... | ... | @@ -94,6 +95,8 @@ |
94 | 95 | extern seqlock_t xtime_lock __attribute__((weak)); |
95 | 96 | |
96 | 97 | extern unsigned long read_persistent_clock(void); |
98 | +extern int update_persistent_clock(struct timespec now); | |
99 | +extern int no_sync_cmos_clock __read_mostly; | |
97 | 100 | void timekeeping_init(void); |
98 | 101 | |
99 | 102 | static inline unsigned long get_seconds(void) |
kernel/time/ntp.c
... | ... | @@ -10,6 +10,7 @@ |
10 | 10 | |
11 | 11 | #include <linux/mm.h> |
12 | 12 | #include <linux/time.h> |
13 | +#include <linux/timer.h> | |
13 | 14 | #include <linux/timex.h> |
14 | 15 | #include <linux/jiffies.h> |
15 | 16 | #include <linux/hrtimer.h> |
16 | 17 | |
17 | 18 | |
18 | 19 | |
... | ... | @@ -175,12 +176,64 @@ |
175 | 176 | return tick_length; |
176 | 177 | } |
177 | 178 | |
179 | +#ifdef CONFIG_GENERIC_CMOS_UPDATE | |
178 | 180 | |
179 | -void __attribute__ ((weak)) notify_arch_cmos_timer(void) | |
181 | +/* Disable the cmos update - used by virtualization and embedded */ | |
182 | +int no_sync_cmos_clock __read_mostly; | |
183 | + | |
184 | +static void sync_cmos_clock(unsigned long dummy); | |
185 | + | |
186 | +static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0); | |
187 | + | |
188 | +static void sync_cmos_clock(unsigned long dummy) | |
180 | 189 | { |
181 | - return; | |
190 | + struct timespec now, next; | |
191 | + int fail = 1; | |
192 | + | |
193 | + /* | |
194 | + * If we have an externally synchronized Linux clock, then update | |
195 | + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be | |
196 | + * called as close as possible to 500 ms before the new second starts. | |
197 | + * This code is run on a timer. If the clock is set, that timer | |
198 | + * may not expire at the correct time. Thus, we adjust... | |
199 | + */ | |
200 | + if (!ntp_synced()) | |
201 | + /* | |
202 | + * Not synced, exit, do not restart a timer (if one is | |
203 | + * running, let it run out). | |
204 | + */ | |
205 | + return; | |
206 | + | |
207 | + getnstimeofday(&now); | |
208 | + if (abs(xtime.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) | |
209 | + fail = update_persistent_clock(now); | |
210 | + | |
211 | + next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec; | |
212 | + if (next.tv_nsec <= 0) | |
213 | + next.tv_nsec += NSEC_PER_SEC; | |
214 | + | |
215 | + if (!fail) | |
216 | + next.tv_sec = 659; | |
217 | + else | |
218 | + next.tv_sec = 0; | |
219 | + | |
220 | + if (next.tv_nsec >= NSEC_PER_SEC) { | |
221 | + next.tv_sec++; | |
222 | + next.tv_nsec -= NSEC_PER_SEC; | |
223 | + } | |
224 | + mod_timer(&sync_cmos_timer, jiffies + timespec_to_jiffies(&next)); | |
182 | 225 | } |
183 | 226 | |
227 | +static void notify_cmos_timer(void) | |
228 | +{ | |
229 | + if (no_sync_cmos_clock) | |
230 | + mod_timer(&sync_cmos_timer, jiffies + 1); | |
231 | +} | |
232 | + | |
233 | +#else | |
234 | +static inline void notify_cmos_timer(void) { } | |
235 | +#endif | |
236 | + | |
184 | 237 | /* adjtimex mainly allows reading (and writing, if superuser) of |
185 | 238 | * kernel time-keeping variables. used by xntpd. |
186 | 239 | */ |
... | ... | @@ -345,7 +398,7 @@ |
345 | 398 | txc->stbcnt = 0; |
346 | 399 | write_sequnlock_irq(&xtime_lock); |
347 | 400 | do_gettimeofday(&txc->time); |
348 | - notify_arch_cmos_timer(); | |
401 | + notify_cmos_timer(); | |
349 | 402 | return(result); |
350 | 403 | } |