Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pps: capture MONOTONIC_RAW timestamps as well

MONOTONIC_RAW clock timestamps are ideally suited for frequency
calculation and also fit well into the original NTP hardpps design. Now
phase and frequency can be adjusted separately: the former based on
REALTIME clock and the latter based on MONOTONIC_RAW clock.

A new function getnstime_raw_and_real is added to timekeeping subsystem to
capture both timestamps at the same time and atomically.

Signed-off-by: Alexander Gordeev <lasaine@lvk.cs.msu.su>
Acked-by: John Stultz <johnstul@us.ibm.com>
Cc: Rodolfo Giometti <giometti@enneenne.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Alexander Gordeev and committed by
Linus Torvalds
e2c18e49 025b40ab

+59
+14
include/linux/pps_kernel.h
··· 47 47 }; 48 48 49 49 struct pps_event_time { 50 + #ifdef CONFIG_NTP_PPS 51 + struct timespec ts_raw; 52 + #endif /* CONFIG_NTP_PPS */ 50 53 struct timespec ts_real; 51 54 }; 52 55 ··· 100 97 kt->nsec = ts.tv_nsec; 101 98 } 102 99 100 + #ifdef CONFIG_NTP_PPS 101 + 102 + static inline void pps_get_ts(struct pps_event_time *ts) 103 + { 104 + getnstime_raw_and_real(&ts->ts_raw, &ts->ts_real); 105 + } 106 + 107 + #else /* CONFIG_NTP_PPS */ 108 + 103 109 static inline void pps_get_ts(struct pps_event_time *ts) 104 110 { 105 111 getnstimeofday(&ts->ts_real); 106 112 } 113 + 114 + #endif /* CONFIG_NTP_PPS */ 107 115 108 116 #endif /* LINUX_PPS_KERNEL_H */ 109 117
+2
include/linux/time.h
··· 158 158 extern int do_getitimer(int which, struct itimerval *value); 159 159 extern void getnstimeofday(struct timespec *tv); 160 160 extern void getrawmonotonic(struct timespec *ts); 161 + extern void getnstime_raw_and_real(struct timespec *ts_raw, 162 + struct timespec *ts_real); 161 163 extern void getboottime(struct timespec *ts); 162 164 extern void monotonic_to_bootbased(struct timespec *ts); 163 165
+43
kernel/time/timekeeping.c
··· 288 288 } 289 289 EXPORT_SYMBOL_GPL(ktime_get_ts); 290 290 291 + #ifdef CONFIG_NTP_PPS 292 + 293 + /** 294 + * getnstime_raw_and_real - get day and raw monotonic time in timespec format 295 + * @ts_raw: pointer to the timespec to be set to raw monotonic time 296 + * @ts_real: pointer to the timespec to be set to the time of day 297 + * 298 + * This function reads both the time of day and raw monotonic time at the 299 + * same time atomically and stores the resulting timestamps in timespec 300 + * format. 301 + */ 302 + void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real) 303 + { 304 + unsigned long seq; 305 + s64 nsecs_raw, nsecs_real; 306 + 307 + WARN_ON_ONCE(timekeeping_suspended); 308 + 309 + do { 310 + u32 arch_offset; 311 + 312 + seq = read_seqbegin(&xtime_lock); 313 + 314 + *ts_raw = raw_time; 315 + *ts_real = xtime; 316 + 317 + nsecs_raw = timekeeping_get_ns_raw(); 318 + nsecs_real = timekeeping_get_ns(); 319 + 320 + /* If arch requires, add in gettimeoffset() */ 321 + arch_offset = arch_gettimeoffset(); 322 + nsecs_raw += arch_offset; 323 + nsecs_real += arch_offset; 324 + 325 + } while (read_seqretry(&xtime_lock, seq)); 326 + 327 + timespec_add_ns(ts_raw, nsecs_raw); 328 + timespec_add_ns(ts_real, nsecs_real); 329 + } 330 + EXPORT_SYMBOL(getnstime_raw_and_real); 331 + 332 + #endif /* CONFIG_NTP_PPS */ 333 + 291 334 /** 292 335 * do_gettimeofday - Returns the time of day in a timeval 293 336 * @tv: pointer to the timeval to be set