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

ntp/pps: use y2038 safe types in pps_event_time

The pps_event_time uses two 'timespec' structures internally, which
suffer from the y2038 problem. The uses of this structure are
fairly self-contained in the pps code, so this replaces them all at
once.

Unfortunately, this includes the sfc ethernet driver aside from the
pps subsystem, so we change that one as well. Both touch the
same data structure, and there probably is no good way to split
the patch into smaller units.

Acked-by: Richard Cochran <richardcochran@gmail.com>
Acked-by: David S. Miller <davem@davemloft.net>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: John Stultz <john.stultz@linaro.org>

authored by

Arnd Bergmann and committed by
John Stultz
ade1bdff 5fd96c42

+19 -26
+8 -8
drivers/net/ethernet/sfc/ptp.c
··· 646 646 struct pps_event_time *last_time) 647 647 { 648 648 struct pps_event_time now; 649 - struct timespec limit; 649 + struct timespec64 limit; 650 650 struct efx_ptp_data *ptp = efx->ptp_data; 651 - struct timespec start; 651 + struct timespec64 start; 652 652 int *mc_running = ptp->start.addr; 653 653 654 654 pps_get_ts(&now); 655 655 start = now.ts_real; 656 656 limit = now.ts_real; 657 - timespec_add_ns(&limit, SYNCHRONISE_PERIOD_NS); 657 + timespec64_add_ns(&limit, SYNCHRONISE_PERIOD_NS); 658 658 659 659 /* Write host time for specified period or until MC is done */ 660 - while ((timespec_compare(&now.ts_real, &limit) < 0) && 660 + while ((timespec64_compare(&now.ts_real, &limit) < 0) && 661 661 ACCESS_ONCE(*mc_running)) { 662 - struct timespec update_time; 662 + struct timespec64 update_time; 663 663 unsigned int host_time; 664 664 665 665 /* Don't update continuously to avoid saturating the PCIe bus */ 666 666 update_time = now.ts_real; 667 - timespec_add_ns(&update_time, SYNCHRONISATION_GRANULARITY_NS); 667 + timespec64_add_ns(&update_time, SYNCHRONISATION_GRANULARITY_NS); 668 668 do { 669 669 pps_get_ts(&now); 670 - } while ((timespec_compare(&now.ts_real, &update_time) < 0) && 670 + } while ((timespec64_compare(&now.ts_real, &update_time) < 0) && 671 671 ACCESS_ONCE(*mc_running)); 672 672 673 673 /* Synchronise NIC with single word of time only */ ··· 723 723 struct efx_ptp_data *ptp = efx->ptp_data; 724 724 u32 last_sec; 725 725 u32 start_sec; 726 - struct timespec delta; 726 + struct timespec64 delta; 727 727 ktime_t mc_time; 728 728 729 729 if (number_readings == 0)
+2 -2
drivers/pps/kapi.c
··· 179 179 /* check event type */ 180 180 BUG_ON((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0); 181 181 182 - dev_dbg(pps->dev, "PPS event at %ld.%09ld\n", 183 - ts->ts_real.tv_sec, ts->ts_real.tv_nsec); 182 + dev_dbg(pps->dev, "PPS event at %lld.%09ld\n", 183 + (s64)ts->ts_real.tv_sec, ts->ts_real.tv_nsec); 184 184 185 185 timespec_to_pps_ktime(&ts_real, ts->ts_real); 186 186
+1 -3
drivers/pps/kc.c
··· 113 113 int event) 114 114 { 115 115 unsigned long flags; 116 - struct timespec64 real = timespec_to_timespec64(ts->ts_real); 117 - struct timespec64 raw = timespec_to_timespec64(ts->ts_raw); 118 116 119 117 /* Pass some events to kernel consumer if activated */ 120 118 spin_lock_irqsave(&pps_kc_hardpps_lock, flags); 121 119 if (pps == pps_kc_hardpps_dev && event & pps_kc_hardpps_mode) 122 - hardpps(&real, &raw); 120 + hardpps(&ts->ts_real, &ts->ts_raw); 123 121 spin_unlock_irqrestore(&pps_kc_hardpps_lock, flags); 124 122 }
+8 -13
include/linux/pps_kernel.h
··· 48 48 49 49 struct pps_event_time { 50 50 #ifdef CONFIG_NTP_PPS 51 - struct timespec ts_raw; 51 + struct timespec64 ts_raw; 52 52 #endif /* CONFIG_NTP_PPS */ 53 - struct timespec ts_real; 53 + struct timespec64 ts_real; 54 54 }; 55 55 56 56 /* The main struct */ ··· 105 105 struct pps_device *pps_lookup_dev(void const *cookie); 106 106 107 107 static inline void timespec_to_pps_ktime(struct pps_ktime *kt, 108 - struct timespec ts) 108 + struct timespec64 ts) 109 109 { 110 110 kt->sec = ts.tv_sec; 111 111 kt->nsec = ts.tv_nsec; ··· 115 115 116 116 static inline void pps_get_ts(struct pps_event_time *ts) 117 117 { 118 - struct timespec64 raw, real; 119 - 120 - ktime_get_raw_and_real_ts64(&raw, &real); 121 - 122 - ts->ts_raw = timespec64_to_timespec(raw); 123 - ts->ts_real = timespec64_to_timespec(real); 118 + ktime_get_raw_and_real_ts64(&ts->ts_raw, &ts->ts_real); 124 119 } 125 120 126 121 #else /* CONFIG_NTP_PPS */ 127 122 128 123 static inline void pps_get_ts(struct pps_event_time *ts) 129 124 { 130 - getnstimeofday(&ts->ts_real); 125 + ktime_get_real_ts64(&ts->ts_real); 131 126 } 132 127 133 128 #endif /* CONFIG_NTP_PPS */ 134 129 135 130 /* Subtract known time delay from PPS event time(s) */ 136 - static inline void pps_sub_ts(struct pps_event_time *ts, struct timespec delta) 131 + static inline void pps_sub_ts(struct pps_event_time *ts, struct timespec64 delta) 137 132 { 138 - ts->ts_real = timespec_sub(ts->ts_real, delta); 133 + ts->ts_real = timespec64_sub(ts->ts_real, delta); 139 134 #ifdef CONFIG_NTP_PPS 140 - ts->ts_raw = timespec_sub(ts->ts_raw, delta); 135 + ts->ts_raw = timespec64_sub(ts->ts_raw, delta); 141 136 #endif 142 137 } 143 138