Commit f4304ab2 authored by john stultz's avatar john stultz Committed by Linus Torvalds

[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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 771ee3b0
...@@ -286,6 +286,13 @@ static inline void time_interpolator_update(long delta_nsec) ...@@ -286,6 +286,13 @@ static inline void time_interpolator_update(long delta_nsec)
#define TICK_LENGTH_SHIFT 32 #define TICK_LENGTH_SHIFT 32
#ifdef CONFIG_NO_HZ
#define NTP_INTERVAL_FREQ (2)
#else
#define NTP_INTERVAL_FREQ (HZ)
#endif
#define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ)
/* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */ /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
extern u64 current_tick_length(void); extern u64 current_tick_length(void);
......
...@@ -128,15 +128,20 @@ EXPORT_SYMBOL_GPL(ktime_get_ts); ...@@ -128,15 +128,20 @@ EXPORT_SYMBOL_GPL(ktime_get_ts);
static void hrtimer_get_softirq_time(struct hrtimer_base *base) static void hrtimer_get_softirq_time(struct hrtimer_base *base)
{ {
ktime_t xtim, tomono; ktime_t xtim, tomono;
struct timespec xts;
unsigned long seq; unsigned long seq;
do { do {
seq = read_seqbegin(&xtime_lock); seq = read_seqbegin(&xtime_lock);
xtim = timespec_to_ktime(xtime); #ifdef CONFIG_NO_HZ
tomono = timespec_to_ktime(wall_to_monotonic); getnstimeofday(&xts);
#else
xts = xtime;
#endif
} while (read_seqretry(&xtime_lock, seq)); } while (read_seqretry(&xtime_lock, seq));
xtim = timespec_to_ktime(xts);
tomono = timespec_to_ktime(wall_to_monotonic);
base[CLOCK_REALTIME].softirq_time = xtim; base[CLOCK_REALTIME].softirq_time = xtim;
base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono); base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono);
} }
......
...@@ -24,7 +24,7 @@ static u64 tick_length, tick_length_base; ...@@ -24,7 +24,7 @@ static u64 tick_length, tick_length_base;
#define MAX_TICKADJ 500 /* microsecs */ #define MAX_TICKADJ 500 /* microsecs */
#define MAX_TICKADJ_SCALED (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \ #define MAX_TICKADJ_SCALED (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \
TICK_LENGTH_SHIFT) / HZ) TICK_LENGTH_SHIFT) / NTP_INTERVAL_FREQ)
/* /*
* phase-lock loop variables * phase-lock loop variables
...@@ -46,13 +46,17 @@ long time_adjust; ...@@ -46,13 +46,17 @@ long time_adjust;
static void ntp_update_frequency(void) static void ntp_update_frequency(void)
{ {
tick_length_base = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT; u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ)
tick_length_base += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT; << TICK_LENGTH_SHIFT;
tick_length_base += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC); second_length += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
second_length += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
do_div(tick_length_base, HZ); tick_length_base = second_length;
tick_nsec = tick_length_base >> TICK_LENGTH_SHIFT; do_div(second_length, HZ);
tick_nsec = second_length >> TICK_LENGTH_SHIFT;
do_div(tick_length_base, NTP_INTERVAL_FREQ);
} }
/** /**
...@@ -162,7 +166,7 @@ void second_overflow(void) ...@@ -162,7 +166,7 @@ void second_overflow(void)
tick_length -= MAX_TICKADJ_SCALED; tick_length -= MAX_TICKADJ_SCALED;
} else { } else {
tick_length += (s64)(time_adjust * NSEC_PER_USEC / tick_length += (s64)(time_adjust * NSEC_PER_USEC /
HZ) << TICK_LENGTH_SHIFT; NTP_INTERVAL_FREQ) << TICK_LENGTH_SHIFT;
time_adjust = 0; time_adjust = 0;
} }
} }
...@@ -239,7 +243,8 @@ int do_adjtimex(struct timex *txc) ...@@ -239,7 +243,8 @@ int do_adjtimex(struct timex *txc)
result = -EINVAL; result = -EINVAL;
goto leave; goto leave;
} }
time_freq = ((s64)txc->freq * NSEC_PER_USEC) >> (SHIFT_USEC - SHIFT_NSEC); time_freq = ((s64)txc->freq * NSEC_PER_USEC)
>> (SHIFT_USEC - SHIFT_NSEC);
} }
if (txc->modes & ADJ_MAXERROR) { if (txc->modes & ADJ_MAXERROR) {
...@@ -309,7 +314,8 @@ int do_adjtimex(struct timex *txc) ...@@ -309,7 +314,8 @@ int do_adjtimex(struct timex *txc)
freq_adj += time_freq; freq_adj += time_freq;
freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC); freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC);
time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC); time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC);
time_offset = (time_offset / HZ) << SHIFT_UPDATE; time_offset = (time_offset / NTP_INTERVAL_FREQ)
<< SHIFT_UPDATE;
} /* STA_PLL */ } /* STA_PLL */
} /* txc->modes & ADJ_OFFSET */ } /* txc->modes & ADJ_OFFSET */
if (txc->modes & ADJ_TICK) if (txc->modes & ADJ_TICK)
...@@ -324,8 +330,10 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0) ...@@ -324,8 +330,10 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
txc->offset = save_adjust; txc->offset = save_adjust;
else else
txc->offset = shift_right(time_offset, SHIFT_UPDATE) * HZ / 1000; txc->offset = shift_right(time_offset, SHIFT_UPDATE)
txc->freq = (time_freq / NSEC_PER_USEC) << (SHIFT_USEC - SHIFT_NSEC); * NTP_INTERVAL_FREQ / 1000;
txc->freq = (time_freq / NSEC_PER_USEC)
<< (SHIFT_USEC - SHIFT_NSEC);
txc->maxerror = time_maxerror; txc->maxerror = time_maxerror;
txc->esterror = time_esterror; txc->esterror = time_esterror;
txc->status = time_status; txc->status = time_status;
......
...@@ -890,7 +890,7 @@ void __init timekeeping_init(void) ...@@ -890,7 +890,7 @@ void __init timekeeping_init(void)
ntp_clear(); ntp_clear();
clock = clocksource_get_next(); clock = clocksource_get_next();
clocksource_calculate_interval(clock, tick_nsec); clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
clock->cycle_last = clocksource_read(clock); clock->cycle_last = clocksource_read(clock);
write_sequnlock_irqrestore(&xtime_lock, flags); write_sequnlock_irqrestore(&xtime_lock, flags);
...@@ -1092,7 +1092,7 @@ static void update_wall_time(void) ...@@ -1092,7 +1092,7 @@ static void update_wall_time(void)
if (change_clocksource()) { if (change_clocksource()) {
clock->error = 0; clock->error = 0;
clock->xtime_nsec = 0; clock->xtime_nsec = 0;
clocksource_calculate_interval(clock, tick_nsec); clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment