X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=include%2Flinux%2Ftimex.h;h=03914b7e41b17871aea961f6522ec4ce26a4f8ed;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=c9e92e016524ec1d90f3d4b13be1d09893d0d6ce;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/include/linux/timex.h b/include/linux/timex.h index c9e92e016..03914b7e4 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h @@ -47,39 +47,18 @@ * kernel PLL updated to 1994-12-13 specs (rfc-1589) * 1997-08-30 Ulrich Windl * Added new constant NTP_PHASE_LIMIT + * 2004-08-12 Christoph Lameter + * Reworked time interpolation logic */ #ifndef _LINUX_TIMEX_H #define _LINUX_TIMEX_H #include #include +#include #include - -/* - * The following defines establish the engineering parameters of the PLL - * model. The HZ variable establishes the timer interrupt frequency, 100 Hz - * for the SunOS kernel, 256 Hz for the Ultrix kernel and 1024 Hz for the - * OSF/1 kernel. The SHIFT_HZ define expresses the same value as the - * nearest power of two in order to avoid hardware multiply operations. - */ -#if HZ >= 12 && HZ < 24 -# define SHIFT_HZ 4 -#elif HZ >= 24 && HZ < 48 -# define SHIFT_HZ 5 -#elif HZ >= 48 && HZ < 96 -# define SHIFT_HZ 6 -#elif HZ >= 96 && HZ < 192 -# define SHIFT_HZ 7 -#elif HZ >= 192 && HZ < 384 -# define SHIFT_HZ 8 -#elif HZ >= 384 && HZ < 768 -# define SHIFT_HZ 9 -#elif HZ >= 768 && HZ < 1536 -# define SHIFT_HZ 10 -#else -# error You lose. -#endif +#include /* * SHIFT_KG and SHIFT_KF establish the damping of the PLL and are chosen @@ -118,72 +97,10 @@ #define MAXPHASE 512000L /* max phase error (us) */ #define MAXFREQ (512L << SHIFT_USEC) /* max frequency error (ppm) */ -#define MAXTIME (200L << PPS_AVG) /* max PPS error (jitter) (200 us) */ #define MINSEC 16L /* min interval between updates (s) */ #define MAXSEC 1200L /* max interval between updates (s) */ #define NTP_PHASE_LIMIT (MAXPHASE << 5) /* beyond max. dispersion */ -/* - * The following defines are used only if a pulse-per-second (PPS) - * signal is available and connected via a modem control lead, such as - * produced by the optional ppsclock feature incorporated in the Sun - * asynch driver. They establish the design parameters of the frequency- - * lock loop used to discipline the CPU clock oscillator to the PPS - * signal. - * - * PPS_AVG is the averaging factor for the frequency loop, as well as - * the time and frequency dispersion. - * - * PPS_SHIFT and PPS_SHIFTMAX specify the minimum and maximum - * calibration intervals, respectively, in seconds as a power of two. - * - * PPS_VALID is the maximum interval before the PPS signal is considered - * invalid and protocol updates used directly instead. - * - * MAXGLITCH is the maximum interval before a time offset of more than - * MAXTIME is believed. - */ -#define PPS_AVG 2 /* pps averaging constant (shift) */ -#define PPS_SHIFT 2 /* min interval duration (s) (shift) */ -#define PPS_SHIFTMAX 8 /* max interval duration (s) (shift) */ -#define PPS_VALID 120 /* pps signal watchdog max (s) */ -#define MAXGLITCH 30 /* pps signal glitch max (s) */ - -/* - * Pick up the architecture specific timex specifications - */ -#include - -/* LATCH is used in the interval timer and ftape setup. */ -#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ - -/* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, the we can - * improve accuracy by shifting LSH bits, hence calculating: - * (NOM << LSH) / DEN - * This however means trouble for large NOM, because (NOM << LSH) may no - * longer fit in 32 bits. The following way of calculating this gives us - * some slack, under the following conditions: - * - (NOM / DEN) fits in (32 - LSH) bits. - * - (NOM % DEN) fits in (32 - LSH) bits. - */ -#define SH_DIV(NOM,DEN,LSH) ( ((NOM / DEN) << LSH) \ - + (((NOM % DEN) << LSH) + DEN / 2) / DEN) - -/* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ -#define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) - -/* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */ -#define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8)) - -/* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ -#define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) - -/* TICK_USEC_TO_NSEC is the time between ticks in nsec assuming real ACTHZ and */ -/* a value TUSEC for TICK_USEC (can be set bij adjtimex) */ -#define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV (TUSEC * USER_HZ * 1000, ACTHZ, 8)) - - -#include /* * syscall interface - used (mainly by NTP daemon) * to discipline kernel clock oscillator @@ -296,127 +213,102 @@ extern long time_precision; /* clock precision (us) */ extern long time_maxerror; /* maximum error */ extern long time_esterror; /* estimated error */ -extern long time_phase; /* phase offset (scaled us) */ extern long time_freq; /* frequency offset (scaled ppm) */ -extern long time_adj; /* tick adjust (scaled 1 / HZ) */ extern long time_reftime; /* time at last adjustment (s) */ extern long time_adjust; /* The amount of adjtime left */ extern long time_next_adjust; /* Value for time_adjust at next tick */ -/* interface variables pps->timer interrupt */ -extern long pps_offset; /* pps time offset (us) */ -extern long pps_jitter; /* time dispersion (jitter) (us) */ -extern long pps_freq; /* frequency offset (scaled ppm) */ -extern long pps_stabil; /* frequency dispersion (scaled ppm) */ -extern long pps_valid; /* pps signal watchdog counter */ +/** + * ntp_clear - Clears the NTP state variables + * + * Must be called while holding a write on the xtime_lock + */ +static inline void ntp_clear(void) +{ + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; +} + +/** + * ntp_synced - Returns 1 if the NTP status is not UNSYNC + * + */ +static inline int ntp_synced(void) +{ + return !(time_status & STA_UNSYNC); +} + +/* Required to safely shift negative values */ +#define shift_right(x, s) ({ \ + __typeof__(x) __x = (x); \ + __typeof__(s) __s = (s); \ + __x < 0 ? -(-__x >> __s) : __x >> __s; \ +}) -/* interface variables pps->adjtimex */ -extern int pps_shift; /* interval duration (s) (shift) */ -extern long pps_jitcnt; /* jitter limit exceeded */ -extern long pps_calcnt; /* calibration intervals */ -extern long pps_errcnt; /* calibration errors */ -extern long pps_stbcnt; /* stability limit exceeded */ #ifdef CONFIG_TIME_INTERPOLATION -struct time_interpolator { - /* cache-hot stuff first: */ - unsigned long (*get_offset) (void); - void (*update) (long); - void (*reset) (void); +#define TIME_SOURCE_CPU 0 +#define TIME_SOURCE_MMIO64 1 +#define TIME_SOURCE_MMIO32 2 +#define TIME_SOURCE_FUNCTION 3 + +/* For proper operations time_interpolator clocks must run slightly slower + * than the standard clock since the interpolator may only correct by having + * time jump forward during a tick. A slower clock is usually a side effect + * of the integer divide of the nanoseconds in a second by the frequency. + * The accuracy of the division can be increased by specifying a shift. + * However, this may cause the clock not to be slow enough. + * The interpolator will self-tune the clock by slowing down if no + * resets occur or speeding up if the time jumps per analysis cycle + * become too high. + * + * Setting jitter compensates for a fluctuating timesource by comparing + * to the last value read from the timesource to insure that an earlier value + * is not returned by a later call. The price to pay + * for the compensation is that the timer routines are not as scalable anymore. + */ - /* cache-cold stuff follows here: */ - struct time_interpolator *next; - unsigned long frequency; /* frequency in counts/second */ +struct time_interpolator { + u16 source; /* time source flags */ + u8 shift; /* increases accuracy of multiply by shifting. */ + /* Note that bits may be lost if shift is set too high */ + u8 jitter; /* if set compensate for fluctuations */ + u32 nsec_per_cyc; /* set by register_time_interpolator() */ + void *addr; /* address of counter or function */ + u64 mask; /* mask the valid bits of the counter */ + unsigned long offset; /* nsec offset at last update of interpolator */ + u64 last_counter; /* counter value in units of the counter at last update */ + u64 last_cycle; /* Last timer value if TIME_SOURCE_JITTER is set */ + u64 frequency; /* frequency in counts/second */ long drift; /* drift in parts-per-million (or -1) */ + unsigned long skips; /* skips forward */ + unsigned long ns_skipped; /* nanoseconds skipped */ + struct time_interpolator *next; }; -extern volatile unsigned long last_nsec_offset; -#ifndef __HAVE_ARCH_CMPXCHG -extern spin_lock_t last_nsec_offset_lock; -#endif -extern struct time_interpolator *time_interpolator; - extern void register_time_interpolator(struct time_interpolator *); extern void unregister_time_interpolator(struct time_interpolator *); - -/* Called with xtime WRITE-lock acquired. */ -static inline void -time_interpolator_update(long delta_nsec) -{ - struct time_interpolator *ti = time_interpolator; - - if (last_nsec_offset > 0) { -#ifdef __HAVE_ARCH_CMPXCHG - unsigned long new, old; - - do { - old = last_nsec_offset; - if (old > delta_nsec) - new = old - delta_nsec; - else - new = 0; - } while (cmpxchg(&last_nsec_offset, old, new) != old); -#else - /* - * This really hurts, because it serializes gettimeofday(), but without an - * atomic single-word compare-and-exchange, there isn't all that much else - * we can do. - */ - spin_lock(&last_nsec_offset_lock); - { - last_nsec_offset -= min(last_nsec_offset, delta_nsec); - } - spin_unlock(&last_nsec_offset_lock); -#endif - } - - if (ti) - (*ti->update)(delta_nsec); -} - -/* Called with xtime WRITE-lock acquired. */ -static inline void -time_interpolator_reset(void) -{ - struct time_interpolator *ti = time_interpolator; - - last_nsec_offset = 0; - if (ti) - (*ti->reset)(); -} - -/* Called with xtime READ-lock acquired. */ -static inline unsigned long -time_interpolator_get_offset(void) -{ - struct time_interpolator *ti = time_interpolator; - if (ti) - return (*ti->get_offset)(); - return last_nsec_offset; -} +extern void time_interpolator_reset(void); +extern unsigned long time_interpolator_get_offset(void); #else /* !CONFIG_TIME_INTERPOLATION */ -static inline void -time_interpolator_update(long delta_nsec) -{ -} - static inline void time_interpolator_reset(void) { } -static inline unsigned long -time_interpolator_get_offset(void) -{ - return 0; -} - #endif /* !CONFIG_TIME_INTERPOLATION */ +/* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */ +extern u64 current_tick_length(void); + +extern int do_adjtimex(struct timex *); + #endif /* KERNEL */ #endif /* LINUX_TIMEX_H */