aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjohn stultz <johnstul@us.ibm.com>2007-02-16 04:27:26 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-16 11:13:56 -0500
commitf4304ab21513b834c8fe3403927c60c2b81a72d7 (patch)
tree212c8fa327d9cf3f29cccf172f0707a3eb6524f8
parent771ee3b04eaac6184312825eb600b4c598f027a5 (diff)
[PATCH] HZ free ntp
Distangle the NTP update from HZ. This is necessary for dynamic tick enabled kernels. Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@elte.hu> Cc: john stultz <johnstul@us.ibm.com> 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>
-rw-r--r--include/linux/timex.h7
-rw-r--r--kernel/hrtimer.c11
-rw-r--r--kernel/time/ntp.c30
-rw-r--r--kernel/timer.c4
4 files changed, 36 insertions, 16 deletions
diff --git a/include/linux/timex.h b/include/linux/timex.h
index 9a24e500c311..da929dbbea2a 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -286,6 +286,13 @@ static inline void time_interpolator_update(long delta_nsec)
286 286
287#define TICK_LENGTH_SHIFT 32 287#define TICK_LENGTH_SHIFT 32
288 288
289#ifdef CONFIG_NO_HZ
290#define NTP_INTERVAL_FREQ (2)
291#else
292#define NTP_INTERVAL_FREQ (HZ)
293#endif
294#define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ)
295
289/* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */ 296/* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
290extern u64 current_tick_length(void); 297extern u64 current_tick_length(void);
291 298
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index f44e499e8fca..80666f6cd4f9 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -128,15 +128,20 @@ EXPORT_SYMBOL_GPL(ktime_get_ts);
128static void hrtimer_get_softirq_time(struct hrtimer_base *base) 128static void hrtimer_get_softirq_time(struct hrtimer_base *base)
129{ 129{
130 ktime_t xtim, tomono; 130 ktime_t xtim, tomono;
131 struct timespec xts;
131 unsigned long seq; 132 unsigned long seq;
132 133
133 do { 134 do {
134 seq = read_seqbegin(&xtime_lock); 135 seq = read_seqbegin(&xtime_lock);
135 xtim = timespec_to_ktime(xtime); 136#ifdef CONFIG_NO_HZ
136 tomono = timespec_to_ktime(wall_to_monotonic); 137 getnstimeofday(&xts);
137 138#else
139 xts = xtime;
140#endif
138 } while (read_seqretry(&xtime_lock, seq)); 141 } while (read_seqretry(&xtime_lock, seq));
139 142
143 xtim = timespec_to_ktime(xts);
144 tomono = timespec_to_ktime(wall_to_monotonic);
140 base[CLOCK_REALTIME].softirq_time = xtim; 145 base[CLOCK_REALTIME].softirq_time = xtim;
141 base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono); 146 base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono);
142} 147}
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 3afeaa3a73f9..eb12509e00bd 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -24,7 +24,7 @@ static u64 tick_length, tick_length_base;
24 24
25#define MAX_TICKADJ 500 /* microsecs */ 25#define MAX_TICKADJ 500 /* microsecs */
26#define MAX_TICKADJ_SCALED (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \ 26#define MAX_TICKADJ_SCALED (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \
27 TICK_LENGTH_SHIFT) / HZ) 27 TICK_LENGTH_SHIFT) / NTP_INTERVAL_FREQ)
28 28
29/* 29/*
30 * phase-lock loop variables 30 * phase-lock loop variables
@@ -46,13 +46,17 @@ long time_adjust;
46 46
47static void ntp_update_frequency(void) 47static void ntp_update_frequency(void)
48{ 48{
49 tick_length_base = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT; 49 u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ)
50 tick_length_base += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT; 50 << TICK_LENGTH_SHIFT;
51 tick_length_base += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC); 51 second_length += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
52 second_length += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
52 53
53 do_div(tick_length_base, HZ); 54 tick_length_base = second_length;
54 55
55 tick_nsec = tick_length_base >> TICK_LENGTH_SHIFT; 56 do_div(second_length, HZ);
57 tick_nsec = second_length >> TICK_LENGTH_SHIFT;
58
59 do_div(tick_length_base, NTP_INTERVAL_FREQ);
56} 60}
57 61
58/** 62/**
@@ -162,7 +166,7 @@ void second_overflow(void)
162 tick_length -= MAX_TICKADJ_SCALED; 166 tick_length -= MAX_TICKADJ_SCALED;
163 } else { 167 } else {
164 tick_length += (s64)(time_adjust * NSEC_PER_USEC / 168 tick_length += (s64)(time_adjust * NSEC_PER_USEC /
165 HZ) << TICK_LENGTH_SHIFT; 169 NTP_INTERVAL_FREQ) << TICK_LENGTH_SHIFT;
166 time_adjust = 0; 170 time_adjust = 0;
167 } 171 }
168 } 172 }
@@ -239,7 +243,8 @@ int do_adjtimex(struct timex *txc)
239 result = -EINVAL; 243 result = -EINVAL;
240 goto leave; 244 goto leave;
241 } 245 }
242 time_freq = ((s64)txc->freq * NSEC_PER_USEC) >> (SHIFT_USEC - SHIFT_NSEC); 246 time_freq = ((s64)txc->freq * NSEC_PER_USEC)
247 >> (SHIFT_USEC - SHIFT_NSEC);
243 } 248 }
244 249
245 if (txc->modes & ADJ_MAXERROR) { 250 if (txc->modes & ADJ_MAXERROR) {
@@ -309,7 +314,8 @@ int do_adjtimex(struct timex *txc)
309 freq_adj += time_freq; 314 freq_adj += time_freq;
310 freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC); 315 freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC);
311 time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC); 316 time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC);
312 time_offset = (time_offset / HZ) << SHIFT_UPDATE; 317 time_offset = (time_offset / NTP_INTERVAL_FREQ)
318 << SHIFT_UPDATE;
313 } /* STA_PLL */ 319 } /* STA_PLL */
314 } /* txc->modes & ADJ_OFFSET */ 320 } /* txc->modes & ADJ_OFFSET */
315 if (txc->modes & ADJ_TICK) 321 if (txc->modes & ADJ_TICK)
@@ -324,8 +330,10 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
324 if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) 330 if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
325 txc->offset = save_adjust; 331 txc->offset = save_adjust;
326 else 332 else
327 txc->offset = shift_right(time_offset, SHIFT_UPDATE) * HZ / 1000; 333 txc->offset = shift_right(time_offset, SHIFT_UPDATE)
328 txc->freq = (time_freq / NSEC_PER_USEC) << (SHIFT_USEC - SHIFT_NSEC); 334 * NTP_INTERVAL_FREQ / 1000;
335 txc->freq = (time_freq / NSEC_PER_USEC)
336 << (SHIFT_USEC - SHIFT_NSEC);
329 txc->maxerror = time_maxerror; 337 txc->maxerror = time_maxerror;
330 txc->esterror = time_esterror; 338 txc->esterror = time_esterror;
331 txc->status = time_status; 339 txc->status = time_status;
diff --git a/kernel/timer.c b/kernel/timer.c
index 4902181e10e6..4f9cc2a48beb 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -890,7 +890,7 @@ void __init timekeeping_init(void)
890 ntp_clear(); 890 ntp_clear();
891 891
892 clock = clocksource_get_next(); 892 clock = clocksource_get_next();
893 clocksource_calculate_interval(clock, tick_nsec); 893 clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
894 clock->cycle_last = clocksource_read(clock); 894 clock->cycle_last = clocksource_read(clock);
895 895
896 write_sequnlock_irqrestore(&xtime_lock, flags); 896 write_sequnlock_irqrestore(&xtime_lock, flags);
@@ -1092,7 +1092,7 @@ static void update_wall_time(void)
1092 if (change_clocksource()) { 1092 if (change_clocksource()) {
1093 clock->error = 0; 1093 clock->error = 0;
1094 clock->xtime_nsec = 0; 1094 clock->xtime_nsec = 0;
1095 clocksource_calculate_interval(clock, tick_nsec); 1095 clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
1096 } 1096 }
1097} 1097}
1098 1098