diff options
-rw-r--r-- | arch/i386/Kconfig | 4 | ||||
-rw-r--r-- | arch/i386/kernel/time.c | 50 | ||||
-rw-r--r-- | arch/sparc64/Kconfig | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/time.c | 53 | ||||
-rw-r--r-- | include/asm-i386/timer.h | 1 | ||||
-rw-r--r-- | include/linux/time.h | 3 | ||||
-rw-r--r-- | kernel/time/ntp.c | 59 |
7 files changed, 71 insertions, 103 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 7a11b905ef49..361aca8b3ec3 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig | |||
@@ -18,6 +18,10 @@ config GENERIC_TIME | |||
18 | bool | 18 | bool |
19 | default y | 19 | default y |
20 | 20 | ||
21 | config GENERIC_CMOS_UPDATE | ||
22 | bool | ||
23 | default y | ||
24 | |||
21 | config CLOCKSOURCE_WATCHDOG | 25 | config CLOCKSOURCE_WATCHDOG |
22 | bool | 26 | bool |
23 | default y | 27 | default y |
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index a665df61f08c..19a6c678d02e 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c | |||
@@ -207,55 +207,9 @@ unsigned long read_persistent_clock(void) | |||
207 | return retval; | 207 | return retval; |
208 | } | 208 | } |
209 | 209 | ||
210 | static void sync_cmos_clock(unsigned long dummy); | 210 | int update_persistent_clock(struct timespec now) |
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) | ||
216 | { | ||
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 | { | 211 | { |
257 | if (!no_sync_cmos_clock) | 212 | return set_rtc_mmss(now.tv_sec); |
258 | mod_timer(&sync_cmos_timer, jiffies + 1); | ||
259 | } | 213 | } |
260 | 214 | ||
261 | extern void (*late_time_init)(void); | 215 | extern void (*late_time_init)(void); |
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index f1cc55677ff2..33dabf588bdd 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig | |||
@@ -23,6 +23,10 @@ config GENERIC_TIME | |||
23 | bool | 23 | bool |
24 | default y | 24 | default y |
25 | 25 | ||
26 | config GENERIC_CMOS_UPDATE | ||
27 | bool | ||
28 | default y | ||
29 | |||
26 | config GENERIC_CLOCKEVENTS | 30 | config GENERIC_CLOCKEVENTS |
27 | bool | 31 | bool |
28 | default y | 32 | default y |
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 87c10a7544da..49063ca2efcd 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c | |||
@@ -403,58 +403,9 @@ static struct sparc64_tick_ops hbtick_operations __read_mostly = { | |||
403 | 403 | ||
404 | static unsigned long timer_ticks_per_nsec_quotient __read_mostly; | 404 | static unsigned long timer_ticks_per_nsec_quotient __read_mostly; |
405 | 405 | ||
406 | #define TICK_SIZE (tick_nsec / 1000) | 406 | int update_persistent_clock(struct timespec now) |
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) | ||
416 | { | ||
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 | { | 407 | { |
457 | mod_timer(&sync_cmos_timer, jiffies + 1); | 408 | return set_rtc_mmss(now.tv_sec); |
458 | } | 409 | } |
459 | 410 | ||
460 | /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ | 411 | /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ |
diff --git a/include/asm-i386/timer.h b/include/asm-i386/timer.h index 51a713e33a9e..b371667cfdeb 100644 --- a/include/asm-i386/timer.h +++ b/include/asm-i386/timer.h | |||
@@ -11,7 +11,6 @@ unsigned long native_calculate_cpu_khz(void); | |||
11 | 11 | ||
12 | extern int timer_ack; | 12 | extern int timer_ack; |
13 | extern int no_timer_check; | 13 | extern int no_timer_check; |
14 | extern int no_sync_cmos_clock; | ||
15 | extern int recalibrate_cpu_khz(void); | 14 | extern int recalibrate_cpu_khz(void); |
16 | 15 | ||
17 | #ifndef CONFIG_PARAVIRT | 16 | #ifndef CONFIG_PARAVIRT |
diff --git a/include/linux/time.h b/include/linux/time.h index ec3b0ced0afe..e6aea5146e5d 100644 --- a/include/linux/time.h +++ b/include/linux/time.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | 5 | ||
6 | #ifdef __KERNEL__ | 6 | #ifdef __KERNEL__ |
7 | # include <linux/cache.h> | ||
7 | # include <linux/seqlock.h> | 8 | # include <linux/seqlock.h> |
8 | #endif | 9 | #endif |
9 | 10 | ||
@@ -94,6 +95,8 @@ extern struct timespec wall_to_monotonic; | |||
94 | extern seqlock_t xtime_lock __attribute__((weak)); | 95 | extern seqlock_t xtime_lock __attribute__((weak)); |
95 | 96 | ||
96 | extern unsigned long read_persistent_clock(void); | 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 | void timekeeping_init(void); | 100 | void timekeeping_init(void); |
98 | 101 | ||
99 | static inline unsigned long get_seconds(void) | 102 | static inline unsigned long get_seconds(void) |
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index b5e352597cbb..cd91237dbfe3 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
12 | #include <linux/time.h> | 12 | #include <linux/time.h> |
13 | #include <linux/timer.h> | ||
13 | #include <linux/timex.h> | 14 | #include <linux/timex.h> |
14 | #include <linux/jiffies.h> | 15 | #include <linux/jiffies.h> |
15 | #include <linux/hrtimer.h> | 16 | #include <linux/hrtimer.h> |
@@ -175,12 +176,64 @@ u64 current_tick_length(void) | |||
175 | return tick_length; | 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) | ||
189 | { | ||
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)); | ||
225 | } | ||
226 | |||
227 | static void notify_cmos_timer(void) | ||
180 | { | 228 | { |
181 | return; | 229 | if (no_sync_cmos_clock) |
230 | mod_timer(&sync_cmos_timer, jiffies + 1); | ||
182 | } | 231 | } |
183 | 232 | ||
233 | #else | ||
234 | static inline void notify_cmos_timer(void) { } | ||
235 | #endif | ||
236 | |||
184 | /* adjtimex mainly allows reading (and writing, if superuser) of | 237 | /* adjtimex mainly allows reading (and writing, if superuser) of |
185 | * kernel time-keeping variables. used by xntpd. | 238 | * kernel time-keeping variables. used by xntpd. |
186 | */ | 239 | */ |
@@ -345,6 +398,6 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0) | |||
345 | txc->stbcnt = 0; | 398 | txc->stbcnt = 0; |
346 | write_sequnlock_irq(&xtime_lock); | 399 | write_sequnlock_irq(&xtime_lock); |
347 | do_gettimeofday(&txc->time); | 400 | do_gettimeofday(&txc->time); |
348 | notify_arch_cmos_timer(); | 401 | notify_cmos_timer(); |
349 | return(result); | 402 | return(result); |
350 | } | 403 | } |