History

Merge tag 'timers-ptp-2026-06-13' of gitolite.kernel.org:pub/scm/linux/kernel/git/tip/tip

Pull timekeeping updates from Thomas Gleixner: "Updates for NTP/timekeeping and PTP: - Expand timekeeping snapshot mechanisms The various snapshot functions are mostly used for PTP to collect "atomic" snapshots of various involved clocks. They lack support for the recently introduced AUX clocks and do not provide the underlying counter value (e.g. TSC) to user space. Exposing the counter value snapshot allows for better control and steering. Convert the hard wired ktime_get_snapshot() to take a clock ID, which allows the caller to select the clock ID to be captured along with CLOCK_MONONOTONIC_RAW. Additionally capture the underlying hardware counter value and the clock source ID of the counter. Expand the hardware based snapshot capture where devices provide a mechanism to snapshot the hardware PTP clock and the system counter (usually via PCI/PTM) to support AUX clocks and also provide the captured counter value back to the caller and not only the clock timestamps derived from it. - Add a new optional read_snapshot() callback to clocksources That is required to capture atomic snapshots from clocksources which are derived from TSC with a scaling mechanism (e.g. Hyper-V, KVMclock). The value pair is handed back in the snapshot structure to the callers, so they can do the necessary correlations in a more precise way. This touches usage sites of the affected functions and data structure all over the tree, but stays fully backwards compatible for the existing user space exposed interfaces. New PTP IOCTLs will provide access to the extended functionality in later kernel versions" * tag 'timers-ptp-2026-06-13' of gitolite.kernel.org:pub/scm/linux/kernel/git/tip/tip: (28 commits) ptp: vmclock: Use hw_cycles from snapshot for precise TSC pairing x86/kvmclock: Implement read_snapshot() for kvmclock clocksource clocksource/hyperv: Implement read_snapshot() for TSC page clocksource timekeeping: Add clocksource read_snapshot() method and hw_cycles to snapshot ptp: Switch to ktime_get_snapshot_id() for pre/post timestamps timekeeping: Add support for AUX clock cross timestamping timekeeping: Remove system_device_crosststamp::sys_realtime ALSA: hda/common: Use system_device_crosststamp::sys_systime wifi: iwlwifi: Use system_device_crosststamp::sys_systime ptp: Use system_device_crosststamp::sys_systime timekeeping: Prepare for cross timestamps on arbitrary clock IDs timekeeping: Remove ktime_get_snapshot() virtio_rtc: Use provided clock ID for history snapshot net/mlx5: Use provided clock ID for history snapshot igc: Use provided clock ID for history snapshot ice/ptp: Use provided clock ID for history snapshot wifi: iwlwifi: Adopt PTP cross timestamps to core changes timekeeping: Add CLOCK ID to system_device_crosststamp timekeeping: Add system_counterval_t to struct system_device_crosststamp timekeeping: Add CLOCK_AUX support for ktime_get_snapshot_id() ...

Linus Torvalds committed 5 months ago

Commit 2d6d57f2 parents a53fcff bc484a523 files · +348 −194Browse files

Unified · Split

23 files
  1. arch/arm64/kvm/hyp_trace.c +4 −4
  2. arch/arm64/kvm/hypercalls.c +3 −3
  3. arch/x86/kernel/kvmclock.c +29 −7
  4. drivers/clocksource/hyperv_timer.c +27 −10
  5. drivers/net/dsa/sja1105/sja1105_main.c +4 −4
  6. drivers/net/ethernet/intel/ice/ice_ptp.c +4 −1
  7. drivers/net/ethernet/intel/igc/igc.h +1 −0
  8. drivers/net/ethernet/intel/igc/igc_ptp.c +3 −1
  9. drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +2 −2
  10. drivers/net/wireless/intel/iwlwifi/mld/ptp.c +3 −2
  11. drivers/net/wireless/intel/iwlwifi/mvm/ptp.c +4 −3
  12. drivers/pps/generators/pps_gen-dummy.c +1 −5
  13. drivers/pps/generators/pps_gen_tio.c +1 −5
  14. drivers/ptp/ptp_chardev.c +11 −7
  15. drivers/ptp/ptp_ocp.c +4 −7
  16. drivers/ptp/ptp_vmclock.c +12 −17
  17. drivers/virtio/virtio_rtc_ptp.c +1 −1
  18. include/linux/clocksource.h +24 −0
  19. include/linux/pps_kernel.h +6 −4
  20. include/linux/ptp_clock_kernel.h +8 −7
  21. include/linux/timekeeping.h +36 −25
  22. kernel/time/timekeeping.c +158 −77
  23. sound/hda/common/controller.c +2 −2
arch/arm64/kvm/hyp_trace.c+4−4
@@ -51,8 +51,8 @@ static void __hyp_clock_work(struct work_struct *work) · 50 unmodified lines
51 51
52 hyp_clock = container_of(dwork, struct hyp_trace_clock, work);52 hyp_clock = container_of(dwork, struct hyp_trace_clock, work);
53 53
54 ktime_get_snapshot(&snap);54 ktime_get_snapshot_id(CLOCK_BOOTTIME, &snap);
55 boot = ktime_to_ns(snap.boot);55 boot = ktime_to_ns(snap.systime);
56 56
57 delta_boot = boot - hyp_clock->boot;57 delta_boot = boot - hyp_clock->boot;
58 delta_cycles = snap.cycles - hyp_clock->cycles;58 delta_cycles = snap.cycles - hyp_clock->cycles;
@@ -118,9 +118,9 @@ static void hyp_trace_clock_enable(struct hyp_trace_clock *hyp_clock, bool enabl · 59 unmodified lines
118 hyp_clock->running = false;118 hyp_clock->running = false;
119 }119 }
120 120
121 ktime_get_snapshot(&snap);121 ktime_get_snapshot_id(CLOCK_BOOTTIME, &snap);
122 122
123 hyp_clock->boot = ktime_to_ns(snap.boot);123 hyp_clock->boot = ktime_to_ns(snap.systime);
124 hyp_clock->cycles = snap.cycles;124 hyp_clock->cycles = snap.cycles;
125 hyp_clock->mult = 0;125 hyp_clock->mult = 0;
126 126
arch/arm64/kvm/hypercalls.c+3−3
@@ -28,7 +28,7 @@ static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val) · 27 unmodified lines
28 * system time and counter value must captured at the same28 * system time and counter value must captured at the same
29 * time to keep consistency and precision.29 * time to keep consistency and precision.
30 */30 */
31 ktime_get_snapshot(&systime_snapshot);31 ktime_get_snapshot_id(CLOCK_REALTIME, &systime_snapshot);
32 32
33 /*33 /*
34 * This is only valid if the current clocksource is the34 * This is only valid if the current clocksource is the
@@ -61,8 +61,8 @@ static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val) · 26 unmodified lines
61 * in the future (about 292 years from 1970, and at that stage61 * in the future (about 292 years from 1970, and at that stage
62 * nobody will give a damn about it).62 * nobody will give a damn about it).
63 */63 */
64 val[0] = upper_32_bits(systime_snapshot.real);64 val[0] = upper_32_bits(systime_snapshot.systime);
65 val[1] = lower_32_bits(systime_snapshot.real);65 val[1] = lower_32_bits(systime_snapshot.systime);
66 val[2] = upper_32_bits(cycles);66 val[2] = upper_32_bits(cycles);
67 val[3] = lower_32_bits(cycles);67 val[3] = lower_32_bits(cycles);
68}68}
arch/x86/kernel/kvmclock.c+29−7
@@ -87,6 +87,27 @@ static u64 kvm_clock_get_cycles(struct clocksource *cs) · 86 unmodified lines
87 return kvm_clock_read();87 return kvm_clock_read();
88}88}
89 89
90static u64 kvm_clock_get_cycles_snapshot(struct clocksource *cs,
91 struct clocksource_hw_snapshot *chs)
92{
93 struct pvclock_vcpu_time_info *src;
94 unsigned version;
95 u64 ret, tsc;
96
97 preempt_disable_notrace();
98 src = this_cpu_pvti();
99 do {
100 version = pvclock_read_begin(src);
101 tsc = rdtsc_ordered();
102 ret = __pvclock_read_cycles(src, tsc);
103 } while (pvclock_read_retry(src, version));
104 preempt_enable_notrace();
105
106 chs->hw_cycles = tsc;
107 chs->hw_csid = CSID_X86_TSC;
108 return ret;
109}
110
90static noinstr u64 kvm_sched_clock_read(void)111static noinstr u64 kvm_sched_clock_read(void)
91{112{
92 return pvclock_clocksource_read_nowd(this_cpu_pvti()) - kvm_sched_clock_offset;113 return pvclock_clocksource_read_nowd(this_cpu_pvti()) - kvm_sched_clock_offset;
@@ -156,13 +177,14 @@ static int kvm_cs_enable(struct clocksource *cs) · 63 unmodified lines
156}177}
157 178
158static struct clocksource kvm_clock = {179static struct clocksource kvm_clock = {
159 .name = "kvm-clock",180 .name = "kvm-clock",
160 .read = kvm_clock_get_cycles,181 .read = kvm_clock_get_cycles,
161 .rating = 400,182 .read_snapshot = kvm_clock_get_cycles_snapshot,
162 .mask = CLOCKSOURCE_MASK(64),183 .rating = 400,
163 .flags = CLOCK_SOURCE_IS_CONTINUOUS,184 .mask = CLOCKSOURCE_MASK(64),
164 .id = CSID_X86_KVM_CLK,185 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
165 .enable = kvm_cs_enable,186 .id = CSID_X86_KVM_CLK,
187 .enable = kvm_cs_enable,
166};188};
167 189
168static void kvm_register_clock(char *txt)190static void kvm_register_clock(char *txt)
drivers/clocksource/hyperv_timer.c+27−10
@@ -444,6 +444,22 @@ static u64 notrace read_hv_clock_tsc_cs(struct clocksource *arg) · 443 unmodified lines
444 return read_hv_clock_tsc();444 return read_hv_clock_tsc();
445}445}
446 446
447static u64 notrace read_hv_clock_tsc_cs_snapshot(struct clocksource *arg,
448 struct clocksource_hw_snapshot *chs)
449{
450 u64 time;
451
452 if (hv_read_tsc_page_tsc(tsc_page, &chs->hw_cycles, &time)) {
453 chs->hw_csid = CSID_X86_TSC;
454 } else {
455 chs->hw_cycles = 0;
456 chs->hw_csid = CSID_GENERIC;
457 time = read_hv_clock_msr();
458 }
459
460 return time;
461}
462
447static u64 noinstr read_hv_sched_clock_tsc(void)463static u64 noinstr read_hv_sched_clock_tsc(void)
448{464{
449 return (read_hv_clock_tsc() - hv_sched_clock_offset) *465 return (read_hv_clock_tsc() - hv_sched_clock_offset) *
@@ -492,18 +508,19 @@ static int hv_cs_enable(struct clocksource *cs) · 42 unmodified lines
492#endif508#endif
493 509
494static struct clocksource hyperv_cs_tsc = {510static struct clocksource hyperv_cs_tsc = {
495 .name = "hyperv_clocksource_tsc_page",511 .name = "hyperv_clocksource_tsc_page",
496 .rating = 500,512 .rating = 500,
497 .read = read_hv_clock_tsc_cs,513 .read = read_hv_clock_tsc_cs,
498 .mask = CLOCKSOURCE_MASK(64),514 .read_snapshot = read_hv_clock_tsc_cs_snapshot,
499 .flags = CLOCK_SOURCE_IS_CONTINUOUS,515 .mask = CLOCKSOURCE_MASK(64),
500 .suspend= suspend_hv_clock_tsc,516 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
501 .resume = resume_hv_clock_tsc,517 .suspend = suspend_hv_clock_tsc,
518 .resume = resume_hv_clock_tsc,
502#ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK519#ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK
503 .enable = hv_cs_enable,520 .enable = hv_cs_enable,
504 .vdso_clock_mode = VDSO_CLOCKMODE_HVCLOCK,521 .vdso_clock_mode = VDSO_CLOCKMODE_HVCLOCK,
505#else522#else
506 .vdso_clock_mode = VDSO_CLOCKMODE_NONE,523 .vdso_clock_mode = VDSO_CLOCKMODE_NONE,
507#endif524#endif
508};525};
509 526
drivers/net/dsa/sja1105/sja1105_main.c+4−4
@@ -2310,10 +2310,10 @@ int sja1105_static_config_reload(struct sja1105_private *priv, · 2309 unmodified lines
2310 goto out;2310 goto out;
2311 }2311 }
2312 2312
2313 t1 = timespec64_to_ns(&ptp_sts_before.pre_ts);2313 t1 = ktime_to_ns(ptp_sts_before.pre_sts.systime);
2314 t2 = timespec64_to_ns(&ptp_sts_before.post_ts);2314 t2 = ktime_to_ns(ptp_sts_before.post_sts.systime);
2315 t3 = timespec64_to_ns(&ptp_sts_after.pre_ts);2315 t3 = ktime_to_ns(ptp_sts_after.pre_sts.systime);
2316 t4 = timespec64_to_ns(&ptp_sts_after.post_ts);2316 t4 = ktime_to_ns(ptp_sts_after.post_sts.systime);
2317 /* Mid point, corresponds to pre-reset PTPCLKVAL */2317 /* Mid point, corresponds to pre-reset PTPCLKVAL */
2318 t12 = t1 + (t2 - t1) / 2;2318 t12 = t1 + (t2 - t1) / 2;
2319 /* Mid point, corresponds to post-reset PTPCLKVAL, aka 0 */2319 /* Mid point, corresponds to post-reset PTPCLKVAL, aka 0 */
drivers/net/ethernet/intel/ice/ice_ptp.c+4−1
@@ -2065,11 +2065,13 @@ static const struct ice_crosststamp_cfg ice_crosststamp_cfg_e830 = { · 2064 unmodified lines
2065/**2065/**
2066 * struct ice_crosststamp_ctx - Device cross timestamp context2066 * struct ice_crosststamp_ctx - Device cross timestamp context
2067 * @snapshot: snapshot of system clocks for historic interpolation2067 * @snapshot: snapshot of system clocks for historic interpolation
2068 * @snapshot_clock_id: System clock ID for @snapshot
2068 * @pf: pointer to the PF private structure2069 * @pf: pointer to the PF private structure
2069 * @cfg: pointer to hardware configuration for cross timestamp2070 * @cfg: pointer to hardware configuration for cross timestamp
2070 */2071 */
2071struct ice_crosststamp_ctx {2072struct ice_crosststamp_ctx {
2072 struct system_time_snapshot snapshot;2073 struct system_time_snapshot snapshot;
2074 clockid_t snapshot_clock_id;
2073 struct ice_pf *pf;2075 struct ice_pf *pf;
2074 const struct ice_crosststamp_cfg *cfg;2076 const struct ice_crosststamp_cfg *cfg;
2075};2077};
@@ -2115,7 +2117,7 @@ static int ice_capture_crosststamp(ktime_t *device, · 39 unmodified lines
2115 }2117 }
2116 2118
2117 /* Snapshot system time for historic interpolation */2119 /* Snapshot system time for historic interpolation */
2118 ktime_get_snapshot(&ctx->snapshot);2120 ktime_get_snapshot_id(ctx->snapshot_clock_id, &ctx->snapshot);
2119 2121
2120 /* Program cmd to master timer */2122 /* Program cmd to master timer */
2121 ice_ptp_src_cmd(hw, ICE_PTP_READ_TIME);2123 ice_ptp_src_cmd(hw, ICE_PTP_READ_TIME);
@@ -2176,6 +2178,7 @@ static int ice_ptp_getcrosststamp(struct ptp_clock_info *info, · 54 unmodified lines
2176{2178{
2177 struct ice_pf *pf = ptp_info_to_pf(info);2179 struct ice_pf *pf = ptp_info_to_pf(info);
2178 struct ice_crosststamp_ctx ctx = {2180 struct ice_crosststamp_ctx ctx = {
2181 .snapshot_clock_id = cts->clock_id,
2179 .pf = pf,2182 .pf = pf,
2180 };2183 };
2181 2184
drivers/net/ethernet/intel/igc/igc.h+1−0
@@ -326,6 +326,7 @@ struct igc_adapter { · 325 unmodified lines
326 struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */326 struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */
327 ktime_t ptp_reset_start; /* Reset time in clock mono */327 ktime_t ptp_reset_start; /* Reset time in clock mono */
328 struct system_time_snapshot snapshot;328 struct system_time_snapshot snapshot;
329 clockid_t snapshot_clock_id;
329 struct mutex ptm_lock; /* Only allow one PTM transaction at a time */330 struct mutex ptm_lock; /* Only allow one PTM transaction at a time */
330 331
331 char fw_version[32];332 char fw_version[32];
drivers/net/ethernet/intel/igc/igc_ptp.c+3−1
@@ -1049,7 +1049,7 @@ static int igc_phc_get_syncdevicetime(ktime_t *device, · 1048 unmodified lines
1049 */1049 */
1050 do {1050 do {
1051 /* Get a snapshot of system clocks to use as historic value. */1051 /* Get a snapshot of system clocks to use as historic value. */
1052 ktime_get_snapshot(&adapter->snapshot);1052 ktime_get_snapshot_id(adapter->snapshot_clock_id, &adapter->snapshot);
1053 1053
1054 igc_ptm_trigger(hw);1054 igc_ptm_trigger(hw);
1055 1055
@@ -1103,6 +1103,8 @@ static int igc_ptp_getcrosststamp(struct ptp_clock_info *ptp, · 47 unmodified lines
1103 /* This blocks until any in progress PTM transactions complete */1103 /* This blocks until any in progress PTM transactions complete */
1104 mutex_lock(&adapter->ptm_lock);1104 mutex_lock(&adapter->ptm_lock);
1105 1105
1106 adapter->snapshot_clock_id = cts->clock_id;
1107
1106 ret = get_device_system_crosststamp(igc_phc_get_syncdevicetime,1108 ret = get_device_system_crosststamp(igc_phc_get_syncdevicetime,
1107 adapter, &adapter->snapshot, cts);1109 adapter, &adapter->snapshot, cts);
1108 mutex_unlock(&adapter->ptm_lock);1110 mutex_unlock(&adapter->ptm_lock);
drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c+2−2
@@ -340,7 +340,7 @@ static int mlx5_ptp_getcrosststamp(struct ptp_clock_info *ptp, · 339 unmodified lines
340 goto unlock;340 goto unlock;
341 }341 }
342 342
343 ktime_get_snapshot(&history_begin);343 ktime_get_snapshot_id(cts->clock_id, &history_begin);
344 344
345 err = get_device_system_crosststamp(mlx5_mtctr_syncdevicetime, mdev,345 err = get_device_system_crosststamp(mlx5_mtctr_syncdevicetime, mdev,
346 &history_begin, cts);346 &history_begin, cts);
@@ -366,7 +366,7 @@ static int mlx5_ptp_getcrosscycles(struct ptp_clock_info *ptp, · 19 unmodified lines
366 goto unlock;366 goto unlock;
367 }367 }
368 368
369 ktime_get_snapshot(&history_begin);369 ktime_get_snapshot_id(cts->clock_id, &history_begin);
370 370
371 err = get_device_system_crosststamp(mlx5_mtctr_syncdevicecyclestime,371 err = get_device_system_crosststamp(mlx5_mtctr_syncdevicecyclestime,
372 mdev, &history_begin, cts);372 mdev, &history_begin, cts);
drivers/net/wireless/intel/iwlwifi/mld/ptp.c+3−2
@@ -250,7 +250,8 @@ iwl_mld_phc_get_crosstimestamp(struct ptp_clock_info *ptp, · 249 unmodified lines
250 /* System (wall) time */250 /* System (wall) time */
251 ktime_t sys_time;251 ktime_t sys_time;
252 252
253 memset(xtstamp, 0, sizeof(struct system_device_crosststamp));253 if (xtstamp->clock_id != CLOCK_REALTIME)
254 return -ENOTSUPP;
254 255
255 ret = iwl_mld_get_crosstimestamp_fw(mld, &gp2, &sys_time);256 ret = iwl_mld_get_crosstimestamp_fw(mld, &gp2, &sys_time);
256 if (ret) {257 if (ret) {
@@ -270,7 +271,7 @@ iwl_mld_phc_get_crosstimestamp(struct ptp_clock_info *ptp, · 13 unmodified lines
270 271
271 /* System monotonic raw time is not used */272 /* System monotonic raw time is not used */
272 xtstamp->device = ns_to_ktime(gp2_ns);273 xtstamp->device = ns_to_ktime(gp2_ns);
273 xtstamp->sys_realtime = sys_time;274 xtstamp->sys_systime = sys_time;
274 275
275 return ret;276 return ret;
276}277}
drivers/net/wireless/intel/iwlwifi/mvm/ptp.c+4−3
@@ -160,13 +160,14 @@ iwl_mvm_phc_get_crosstimestamp(struct ptp_clock_info *ptp, · 159 unmodified lines
160 /* System (wall) time */160 /* System (wall) time */
161 ktime_t sys_time;161 ktime_t sys_time;
162 162
163 memset(xtstamp, 0, sizeof(struct system_device_crosststamp));
164
165 if (!mvm->ptp_data.ptp_clock) {163 if (!mvm->ptp_data.ptp_clock) {
166 IWL_ERR(mvm, "No PHC clock registered\n");164 IWL_ERR(mvm, "No PHC clock registered\n");
167 return -ENODEV;165 return -ENODEV;
168 }166 }
169 167
168 if (xtstamp->clock_id != CLOCK_REALTIME)
169 return -ENOTSUPP;
170
170 mutex_lock(&mvm->mutex);171 mutex_lock(&mvm->mutex);
171 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SYNCED_TIME)) {172 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SYNCED_TIME)) {
172 ret = iwl_mvm_get_crosstimestamp_fw(mvm, &gp2, &sys_time);173 ret = iwl_mvm_get_crosstimestamp_fw(mvm, &gp2, &sys_time);
@@ -184,7 +185,7 @@ iwl_mvm_phc_get_crosstimestamp(struct ptp_clock_info *ptp, · 11 unmodified lines
184 185
185 /* System monotonic raw time is not used */186 /* System monotonic raw time is not used */
186 xtstamp->device = (ktime_t)gp2_ns;187 xtstamp->device = (ktime_t)gp2_ns;
187 xtstamp->sys_realtime = sys_time;188 xtstamp->sys_systime = sys_time;
188 189
189out:190out:
190 mutex_unlock(&mvm->mutex);191 mutex_unlock(&mvm->mutex);
drivers/pps/generators/pps_gen-dummy.c+1−5
@@ -39,11 +39,7 @@ static void pps_gen_ktimer_event(struct timer_list *unused) · 38 unmodified lines
39static int pps_gen_dummy_get_time(struct pps_gen_device *pps_gen,39static int pps_gen_dummy_get_time(struct pps_gen_device *pps_gen,
40 struct timespec64 *time)40 struct timespec64 *time)
41{41{
42 struct system_time_snapshot snap;42 ktime_get_real_ts64(time);
43
44 ktime_get_snapshot(&snap);
45 *time = ktime_to_timespec64(snap.real);
46
47 return 0;43 return 0;
48}44}
49 45
drivers/pps/generators/pps_gen_tio.c+1−5
@@ -189,11 +189,7 @@ static int pps_tio_gen_enable(struct pps_gen_device *pps_gen, bool enable) · 188 unmodified lines
189static int pps_tio_get_time(struct pps_gen_device *pps_gen,189static int pps_tio_get_time(struct pps_gen_device *pps_gen,
190 struct timespec64 *time)190 struct timespec64 *time)
191{191{
192 struct system_time_snapshot snap;192 ktime_get_real_ts64(time);
193
194 ktime_get_snapshot(&snap);
195 *time = ktime_to_timespec64(snap.real);
196
197 return 0;193 return 0;
198}194}
199 195
drivers/ptp/ptp_chardev.c+11−7
@@ -317,8 +317,8 @@ typedef int (*ptp_crosststamp_fn)(struct ptp_clock_info *, · 316 unmodified lines
317static long ptp_sys_offset_precise(struct ptp_clock *ptp, void __user *arg,317static long ptp_sys_offset_precise(struct ptp_clock *ptp, void __user *arg,
318 ptp_crosststamp_fn crosststamp_fn)318 ptp_crosststamp_fn crosststamp_fn)
319{319{
320 struct system_device_crosststamp xtstamp = { .clock_id = CLOCK_REALTIME };
320 struct ptp_sys_offset_precise precise_offset;321 struct ptp_sys_offset_precise precise_offset;
321 struct system_device_crosststamp xtstamp;
322 struct timespec64 ts;322 struct timespec64 ts;
323 int err;323 int err;
324 324
@@ -333,7 +333,7 @@ static long ptp_sys_offset_precise(struct ptp_clock *ptp, void __user *arg, · 8 unmodified lines
333 ts = ktime_to_timespec64(xtstamp.device);333 ts = ktime_to_timespec64(xtstamp.device);
334 precise_offset.device.sec = ts.tv_sec;334 precise_offset.device.sec = ts.tv_sec;
335 precise_offset.device.nsec = ts.tv_nsec;335 precise_offset.device.nsec = ts.tv_nsec;
336 ts = ktime_to_timespec64(xtstamp.sys_realtime);336 ts = ktime_to_timespec64(xtstamp.sys_systime);
337 precise_offset.sys_realtime.sec = ts.tv_sec;337 precise_offset.sys_realtime.sec = ts.tv_sec;
338 precise_offset.sys_realtime.nsec = ts.tv_nsec;338 precise_offset.sys_realtime.nsec = ts.tv_nsec;
339 ts = ktime_to_timespec64(xtstamp.sys_monoraw);339 ts = ktime_to_timespec64(xtstamp.sys_monoraw);
@@ -386,15 +386,19 @@ static long ptp_sys_offset_extended(struct ptp_clock *ptp, void __user *arg, · 46 unmodified lines
386 return err;386 return err;
387 387
388 /* Filter out disabled or unavailable clocks */388 /* Filter out disabled or unavailable clocks */
389 if (sts.pre_ts.tv_sec < 0 || sts.post_ts.tv_sec < 0)389 if (!sts.pre_sts.valid || !sts.post_sts.valid)
390 return -EINVAL;390 return -EINVAL;
391 391
392 extoff->ts[i][0].sec = sts.pre_ts.tv_sec;
393 extoff->ts[i][0].nsec = sts.pre_ts.tv_nsec;
394 extoff->ts[i][1].sec = ts.tv_sec;392 extoff->ts[i][1].sec = ts.tv_sec;
395 extoff->ts[i][1].nsec = ts.tv_nsec;393 extoff->ts[i][1].nsec = ts.tv_nsec;
396 extoff->ts[i][2].sec = sts.post_ts.tv_sec;394
397 extoff->ts[i][2].nsec = sts.post_ts.tv_nsec;395 ts = ktime_to_timespec64(sts.pre_sts.systime);
396 extoff->ts[i][0].sec = ts.tv_sec;
397 extoff->ts[i][0].nsec = ts.tv_nsec;
398
399 ts = ktime_to_timespec64(sts.post_sts.systime);
400 extoff->ts[i][2].sec = ts.tv_sec;
401 extoff->ts[i][2].nsec = ts.tv_nsec;
398 }402 }
399 403
400 return copy_to_user(arg, extoff, sizeof(*extoff)) ? -EFAULT : 0;404 return copy_to_user(arg, extoff, sizeof(*extoff)) ? -EFAULT : 0;
drivers/ptp/ptp_ocp.c+4−7
@@ -1491,11 +1491,8 @@ __ptp_ocp_gettime_locked(struct ptp_ocp *bp, struct timespec64 *ts, · 1490 unmodified lines
1491 }1491 }
1492 ptp_read_system_postts(sts);1492 ptp_read_system_postts(sts);
1493 1493
1494 if (sts && bp->ts_window_adjust) {1494 if (sts && bp->ts_window_adjust)
1495 s64 ns = timespec64_to_ns(&sts->post_ts);1495 sts->post_sts.systime -= bp->ts_window_adjust;
1496
1497 sts->post_ts = ns_to_timespec64(ns - bp->ts_window_adjust);
1498 }
1499 1496
1500 time_ns = ioread32(&bp->reg->time_ns);1497 time_ns = ioread32(&bp->reg->time_ns);
1501 time_sec = ioread32(&bp->reg->time_sec);1498 time_sec = ioread32(&bp->reg->time_sec);
@@ -4600,8 +4597,8 @@ ptp_ocp_summary_show(struct seq_file *s, void *data) · 3098 unmodified lines
4600 struct timespec64 sys_ts;4597 struct timespec64 sys_ts;
4601 s64 pre_ns, post_ns, ns;4598 s64 pre_ns, post_ns, ns;
4602 4599
4603 pre_ns = timespec64_to_ns(&sts.pre_ts);4600 pre_ns = ktime_to_ns(sts.pre_sts.systime);
4604 post_ns = timespec64_to_ns(&sts.post_ts);4601 post_ns = ktime_to_ns(sts.post_sts.systime);
4605 ns = (pre_ns + post_ns) / 2;4602 ns = (pre_ns + post_ns) / 2;
4606 ns += (s64)bp->utc_tai_offset * NSEC_PER_SEC;4603 ns += (s64)bp->utc_tai_offset * NSEC_PER_SEC;
4607 sys_ts = ns_to_timespec64(ns);4604 sys_ts = ns_to_timespec64(ns);
drivers/ptp/ptp_vmclock.c+12−17
@@ -101,7 +101,6 @@ static int vmclock_get_crosststamp(struct vmclock_state *st, · 100 unmodified lines
101 struct timespec64 *tspec)101 struct timespec64 *tspec)
102{102{
103 ktime_t deadline = ktime_add(ktime_get(), VMCLOCK_MAX_WAIT);103 ktime_t deadline = ktime_add(ktime_get(), VMCLOCK_MAX_WAIT);
104 struct system_time_snapshot systime_snapshot;
105 uint64_t cycle, delta, seq, frac_sec;104 uint64_t cycle, delta, seq, frac_sec;
106 105
107#ifdef CONFIG_X86106#ifdef CONFIG_X86
@@ -132,17 +131,19 @@ static int vmclock_get_crosststamp(struct vmclock_state *st, · 24 unmodified lines
132 * will be derived from the *same* counter value.131 * will be derived from the *same* counter value.
133 *132 *
134 * If the system isn't using the same counter, then the value133 * If the system isn't using the same counter, then the value
135 * from ktime_get_snapshot() will still be used as pre_ts, and134 * from ptp_read_system_prets() will still be used as pre_ts,
136 * ptp_read_system_postts() is called to populate postts after135 * and ptp_read_system_postts() is called to populate postts
137 * calling get_cycles().136 * after calling get_cycles().
138 *
139 * The conversion to timespec64 happens further down, outside
140 * the seq_count loop.
141 */137 */
142 if (sts) {138 if (sts) {
143 ktime_get_snapshot(&systime_snapshot);139 ptp_read_system_prets(sts);
144 if (systime_snapshot.cs_id == st->cs_id) {140 if (sts->pre_sts.cs_id == st->cs_id) {
145 cycle = systime_snapshot.cycles;141 cycle = sts->pre_sts.cycles;
142 sts->post_sts = sts->pre_sts;
143 } else if (sts->pre_sts.hw_csid == st->cs_id &&
144 sts->pre_sts.hw_cycles) {
145 cycle = sts->pre_sts.hw_cycles;
146 sts->post_sts = sts->pre_sts;
146 } else {147 } else {
147 cycle = get_cycles();148 cycle = get_cycles();
148 ptp_read_system_postts(sts);149 ptp_read_system_postts(sts);
@@ -180,12 +181,6 @@ static int vmclock_get_crosststamp(struct vmclock_state *st, · 31 unmodified lines
180 system_counter->cs_id = st->cs_id;181 system_counter->cs_id = st->cs_id;
181 }182 }
182 183
183 if (sts) {
184 sts->pre_ts = ktime_to_timespec64(systime_snapshot.real);
185 if (systime_snapshot.cs_id == st->cs_id)
186 sts->post_ts = sts->pre_ts;
187 }
188
189 return 0;184 return 0;
190}185}
191 186
@@ -272,7 +267,7 @@ static int ptp_vmclock_getcrosststamp(struct ptp_clock_info *ptp, · 80 unmodified lines
272 if (ret == -ENODEV) {267 if (ret == -ENODEV) {
273 struct system_time_snapshot systime_snapshot;268 struct system_time_snapshot systime_snapshot;
274 269
275 ktime_get_snapshot(&systime_snapshot);270 ktime_get_snapshot_id(CLOCK_REALTIME, &systime_snapshot);
276 271
277 if (systime_snapshot.cs_id == CSID_X86_TSC ||272 if (systime_snapshot.cs_id == CSID_X86_TSC ||
278 systime_snapshot.cs_id == CSID_X86_KVM_CLK) {273 systime_snapshot.cs_id == CSID_X86_KVM_CLK) {
drivers/virtio/virtio_rtc_ptp.c+1−1
@@ -139,7 +139,7 @@ static int viortc_ptp_getcrosststamp(struct ptp_clock_info *ptp, · 138 unmodified lines
139 if (ret)139 if (ret)
140 return ret;140 return ret;
141 141
142 ktime_get_snapshot(&history_begin);142 ktime_get_snapshot_id(xtstamp->clock_id, &history_begin);
143 if (history_begin.cs_id != cs_id)143 if (history_begin.cs_id != cs_id)
144 return -EOPNOTSUPP;144 return -EOPNOTSUPP;
145 145
include/linux/clocksource.h+24−0
@@ -31,6 +31,21 @@ struct module; · 30 unmodified lines
31 31
32#include <vdso/clocksource.h>32#include <vdso/clocksource.h>
33 33
34/**
35 * struct clocksource_hw_snapshot - Snapshot for the underlying hardware counter of derived
36 * clocksources like kvmclock or Hyper-V scaled TSC
37 * @hw_cycles: The hardware counter value
38 * @hw_csid: Clocksource ID of the hardware counter
39 *
40 * Such clocksources must implement the read_snapshot() callback and fill in the
41 * hardware counter value, the clocksource ID of the hardware counter and derive
42 * the actual clocksource cycles from @hw_cycles to provide an atomic snapshot
43 */
44struct clocksource_hw_snapshot {
45 u64 hw_cycles;
46 enum clocksource_ids hw_csid;
47};
48
34/**49/**
35 * struct clocksource - hardware abstraction for a free running counter50 * struct clocksource - hardware abstraction for a free running counter
36 * Provides mostly state-free accessors to the underlying hardware.51 * Provides mostly state-free accessors to the underlying hardware.
@@ -72,6 +87,14 @@ struct module; · 35 unmodified lines
72 * @flags: Flags describing special properties87 * @flags: Flags describing special properties
73 * @base: Hardware abstraction for clock on which a clocksource88 * @base: Hardware abstraction for clock on which a clocksource
74 * is based89 * is based
90 * @read_snapshot: Extended @read() function for clocksources such as
91 * kvmclock or the Hyper-V scaled TSC where the actual
92 * clocksource value for timekeeping is calculated from an
93 * underlying hardware counter. Returns the timekeeping
94 * relevant cycle value and stores the raw value of the
95 * underlying counter from which it was calculated
96 * including the clocksource ID of that counter in the
97 * clocksource hardware snapshot.
75 * @enable: Optional function to enable the clocksource98 * @enable: Optional function to enable the clocksource
76 * @disable: Optional function to disable the clocksource99 * @disable: Optional function to disable the clocksource
77 * @suspend: Optional suspend function for the clocksource100 * @suspend: Optional suspend function for the clocksource
@@ -113,6 +136,7 @@ struct clocksource { · 35 unmodified lines
113 unsigned long flags;136 unsigned long flags;
114 struct clocksource_base *base;137 struct clocksource_base *base;
115 138
139 u64 (*read_snapshot)(struct clocksource *cs, struct clocksource_hw_snapshot *chs);
116 int (*enable)(struct clocksource *cs);140 int (*enable)(struct clocksource *cs);
117 void (*disable)(struct clocksource *cs);141 void (*disable)(struct clocksource *cs);
118 void (*suspend)(struct clocksource *cs);142 void (*suspend)(struct clocksource *cs);
include/linux/pps_kernel.h+6−4
@@ -99,12 +99,14 @@ static inline void timespec_to_pps_ktime(struct pps_ktime *kt, · 98 unmodified lines
99 99
100static inline void pps_get_ts(struct pps_event_time *ts)100static inline void pps_get_ts(struct pps_event_time *ts)
101{101{
102#ifdef CONFIG_NTP_PPS
102 struct system_time_snapshot snap;103 struct system_time_snapshot snap;
103 104
104 ktime_get_snapshot(&snap);105 ktime_get_snapshot_id(CLOCK_REALTIME, &snap);
105 ts->ts_real = ktime_to_timespec64(snap.real);106 ts->ts_real = ktime_to_timespec64(snap.systime);
106#ifdef CONFIG_NTP_PPS107 ts->ts_raw = ktime_to_timespec64(snap.monoraw);
107 ts->ts_raw = ktime_to_timespec64(snap.raw);108#else
109 ktime_get_real_ts64(&ts->ts_real);
108#endif110#endif
109}111}
110 112
include/linux/ptp_clock_kernel.h+8−7
@@ -12,6 +12,7 @@ · 11 unmodified lines
12#include <linux/pps_kernel.h>12#include <linux/pps_kernel.h>
13#include <linux/ptp_clock.h>13#include <linux/ptp_clock.h>
14#include <linux/timecounter.h>14#include <linux/timecounter.h>
15#include <linux/timekeeping.h>
15#include <linux/skbuff.h>16#include <linux/skbuff.h>
16 17
17#define PTP_CLOCK_NAME_LEN 3218#define PTP_CLOCK_NAME_LEN 32
@@ -45,13 +46,13 @@ struct system_device_crosststamp; · 27 unmodified lines
45 46
46/**47/**
47 * struct ptp_system_timestamp - system time corresponding to a PHC timestamp48 * struct ptp_system_timestamp - system time corresponding to a PHC timestamp
48 * @pre_ts: system timestamp before capturing PHC49 * @pre_sts: system time snapshot before capturing PHC
49 * @post_ts: system timestamp after capturing PHC50 * @post_sts: system time snapshot after capturing PHC
50 * @clockid: clock-base used for capturing the system timestamps51 * @clockid: clock-base used for capturing the system timestamps
51 */52 */
52struct ptp_system_timestamp {53struct ptp_system_timestamp {
53 struct timespec64 pre_ts;54 struct system_time_snapshot pre_sts;
54 struct timespec64 post_ts;55 struct system_time_snapshot post_sts;
55 clockid_t clockid;56 clockid_t clockid;
56};57};
57 58
@@ -510,13 +511,13 @@ static inline ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp, · 452 unmodified lines
510static inline void ptp_read_system_prets(struct ptp_system_timestamp *sts)511static inline void ptp_read_system_prets(struct ptp_system_timestamp *sts)
511{512{
512 if (sts)513 if (sts)
513 ktime_get_clock_ts64(sts->clockid, &sts->pre_ts);514 ktime_get_snapshot_id(sts->clockid, &sts->pre_sts);
514}515}
515 516
516static inline void ptp_read_system_postts(struct ptp_system_timestamp *sts)517static inline void ptp_read_system_postts(struct ptp_system_timestamp *sts)
517{518{
518 if (sts)519 if (sts)
519 ktime_get_clock_ts64(sts->clockid, &sts->post_ts);520 ktime_get_snapshot_id(sts->clockid, &sts->post_sts);
520}521}
521 522
522#endif523#endif
include/linux/timekeeping.h+36−25
@@ -276,37 +276,30 @@ static inline bool ktime_get_aux_ts64(clockid_t id, struct timespec64 *kt) { ret · 275 unmodified lines
276#endif276#endif
277 277
278/**278/**
279 * struct system_time_snapshot - simultaneous raw/real time capture with279 * struct system_time_snapshot - Simultaneous time capture of CLOCK_MONOTONIC_RAW,
280 * counter value280 * a selected CLOCK_* and the clocksource counter value
281 * @cycles: Clocksource counter value to produce the system times281 * @cycles: Clocksource counter value to produce the system times
282 * @real: Realtime system time282 * @hw_cycles: For derived clocksources, the hardware counter value from
283 * @boot: Boot time283 * which @cycles was derived
284 * @raw: Monotonic raw system time284 * @systime: The system time of the selected CLOCK ID
285 * @cs_id: Clocksource ID285 * @monoraw: Monotonic raw system time
286 * @cs_id: Clocksource ID
287 * @hw_csid: Clocksource ID of the underlying hardware counter for derived
288 * clocksources which implement the read_snapshot() callback.
286 * @clock_was_set_seq: The sequence number of clock-was-set events289 * @clock_was_set_seq: The sequence number of clock-was-set events
287 * @cs_was_changed_seq: The sequence number of clocksource change events290 * @cs_was_changed_seq: The sequence number of clocksource change events
291 * @valid: True if the snapshot is valid
288 */292 */
289struct system_time_snapshot {293struct system_time_snapshot {
290 u64 cycles;294 u64 cycles;
291 ktime_t real;295 u64 hw_cycles;
292 ktime_t boot;296 ktime_t systime;
293 ktime_t raw;297 ktime_t monoraw;
294 enum clocksource_ids cs_id;298 enum clocksource_ids cs_id;
299 enum clocksource_ids hw_csid;
295 unsigned int clock_was_set_seq;300 unsigned int clock_was_set_seq;
296 u8 cs_was_changed_seq;301 u8 cs_was_changed_seq;
297};302 u8 valid;
298
299/**
300 * struct system_device_crosststamp - system/device cross-timestamp
301 * (synchronized capture)
302 * @device: Device time
303 * @sys_realtime: Realtime simultaneous with device time
304 * @sys_monoraw: Monotonic raw simultaneous with device time
305 */
306struct system_device_crosststamp {
307 ktime_t device;
308 ktime_t sys_realtime;
309 ktime_t sys_monoraw;
310};303};
311 304
312/**305/**
@@ -325,6 +318,23 @@ struct system_counterval_t { · 12 unmodified lines
325 bool use_nsecs;318 bool use_nsecs;
326};319};
327 320
321/**
322 * struct system_device_crosststamp - system/device cross-timestamp
323 * (synchronized capture)
324 * @clock_id: System time Clock ID to capture
325 * @device: Device time
326 * @sys_counter: Clocksource counter value simultaneous with device time
327 * @sys_systime: System time for @clock_id
328 * @sys_monoraw: Monotonic raw simultaneous with device time
329 */
330struct system_device_crosststamp {
331 clockid_t clock_id;
332 ktime_t device;
333 struct system_counterval_t sys_counter;
334 ktime_t sys_systime;
335 ktime_t sys_monoraw;
336};
337
328extern bool ktime_real_to_base_clock(ktime_t treal,338extern bool ktime_real_to_base_clock(ktime_t treal,
329 enum clocksource_ids base_id, u64 *cycles);339 enum clocksource_ids base_id, u64 *cycles);
330extern bool timekeeping_clocksource_has_base(enum clocksource_ids id);340extern bool timekeeping_clocksource_has_base(enum clocksource_ids id);
@@ -341,9 +351,10 @@ extern int get_device_system_crosststamp( · 10 unmodified lines
341 struct system_device_crosststamp *xtstamp);351 struct system_device_crosststamp *xtstamp);
342 352
343/*353/*
344 * Simultaneously snapshot realtime and monotonic raw clocks354 * Simultaneously snapshot a given clock with MONOTONIC_RAW and the underlying
355 * clocksource counter value.
345 */356 */
346extern void ktime_get_snapshot(struct system_time_snapshot *systime_snapshot);357extern void ktime_get_snapshot_id(clockid_t clock_id, struct system_time_snapshot *systime_snapshot);
347 358
348/*359/*
349 * Persistent clock related interfaces360 * Persistent clock related interfaces
kernel/time/timekeeping.c+158−77
@@ -67,6 +67,7 @@ static inline bool tk_is_aux(const struct timekeeper *tk) · 66 unmodified lines
67{67{
68 return tk->id >= TIMEKEEPER_AUX_FIRST && tk->id <= TIMEKEEPER_AUX_LAST;68 return tk->id >= TIMEKEEPER_AUX_FIRST && tk->id <= TIMEKEEPER_AUX_LAST;
69}69}
70static inline struct tk_data *aux_get_tk_data(clockid_t id);
70#else71#else
71static inline bool tk_get_aux_ts64(unsigned int tkid, struct timespec64 *ts)72static inline bool tk_get_aux_ts64(unsigned int tkid, struct timespec64 *ts)
72{73{
@@ -77,6 +78,10 @@ static inline bool tk_is_aux(const struct timekeeper *tk) · 4 unmodified lines
77{78{
78 return false;79 return false;
79}80}
81static inline struct tk_data *aux_get_tk_data(clockid_t id)
82{
83 return NULL;
84}
80#endif85#endif
81 86
82static inline void tk_update_aux_offs(struct timekeeper *tk, ktime_t offs)87static inline void tk_update_aux_offs(struct timekeeper *tk, ktime_t offs)
@@ -315,6 +320,7 @@ static __always_inline u64 tk_clock_read(const struct tk_read_base *tkr) · 232 unmodified lines
315 320
316 return clock->read(clock);321 return clock->read(clock);
317}322}
323
318static inline void clocksource_disable_inline_read(void) { }324static inline void clocksource_disable_inline_read(void) { }
319static inline void clocksource_enable_inline_read(void) { }325static inline void clocksource_enable_inline_read(void) { }
320#endif326#endif
@@ -1182,44 +1188,107 @@ noinstr time64_t __ktime_get_real_seconds(void) · 861 unmodified lines
1182 return tk->xtime_sec;1188 return tk->xtime_sec;
1183}1189}
1184 1190
1185/**1191static inline u64 tk_clock_read_snapshot(const struct tk_read_base *tkr,
1186 * ktime_get_snapshot - snapshots the realtime/monotonic raw clocks with counter1192 struct clocksource_hw_snapshot *chs)
1187 * @systime_snapshot: pointer to struct receiving the system time snapshot
1188 */
1189void ktime_get_snapshot(struct system_time_snapshot *systime_snapshot)
1190{1193{
1191 struct timekeeper *tk = &tk_core.timekeeper;1194 struct clocksource *clock = READ_ONCE(tkr->clock);
1195
1196 if (unlikely(clock->read_snapshot))
1197 return clock->read_snapshot(clock, chs);
1198
1199 return clock->read(clock);
1200}
1201
1202
1203/**
1204 * ktime_get_snapshot_id - Simultaneously snapshot a given clock ID with
1205 * CLOCK_MONOTONIC_RAW and the underlying
1206 * clocksource counter value.
1207 * @clock_id: The clock ID to snapshot
1208 * @systime_snapshot: Pointer to struct receiving the system time snapshot
1209 */
1210void ktime_get_snapshot_id(clockid_t clock_id, struct system_time_snapshot *systime_snapshot)
1211{
1212 ktime_t base_raw, base_sys, offs_sys, *offs, offs_zero = 0;
1213 u64 nsec_raw, nsec_sys, now;
1214 struct timekeeper *tk;
1215 struct tk_data *tkd;
1192 unsigned int seq;1216 unsigned int seq;
1193 ktime_t base_raw;
1194 ktime_t base_real;
1195 ktime_t base_boot;
1196 u64 nsec_raw;
1197 u64 nsec_real;
1198 u64 now;
1199 1217
1200 WARN_ON_ONCE(timekeeping_suspended);1218 /* Invalidate the snapshot for all failure cases */
1219 systime_snapshot->valid = false;
1220
1221 if (WARN_ON_ONCE(timekeeping_suspended))
1222 return;
1223
1224 switch (clock_id) {
1225 case CLOCK_REALTIME:
1226 tkd = &tk_core;
1227 offs = &tk_core.timekeeper.offs_real;
1228 break;
1229 /* Map RAW to MONOTONIC so the loop below is trivial */
1230 case CLOCK_MONOTONIC_RAW:
1231 case CLOCK_MONOTONIC:
1232 tkd = &tk_core;
1233 offs = &offs_zero;
1234 break;
1235 case CLOCK_BOOTTIME:
1236 tkd = &tk_core;
1237 offs = &tk_core.timekeeper.offs_boot;
1238 break;
1239 case CLOCK_AUX ... CLOCK_AUX_LAST:
1240 tkd = aux_get_tk_data(clock_id);
1241 if (!tkd)
1242 return;
1243 offs = &tkd->timekeeper.offs_aux;
1244 break;
1245 default:
1246 WARN_ON_ONCE(1);
1247 return;
1248 }
1249
1250 tk = &tkd->timekeeper;
1201 1251
1202 do {1252 do {
1203 seq = read_seqcount_begin(&tk_core.seq);1253 struct clocksource_hw_snapshot chs = { };
1204 now = tk_clock_read(&tk->tkr_mono);1254
1255 seq = read_seqcount_begin(&tkd->seq);
1256
1257 /* Aux clocks can be invalid */
1258 if (!tk->clock_valid)
1259 return;
1260
1261 now = tk_clock_read_snapshot(&tk->tkr_mono, &chs);
1205 systime_snapshot->cs_id = tk->tkr_mono.clock->id;1262 systime_snapshot->cs_id = tk->tkr_mono.clock->id;
1263
1264 systime_snapshot->hw_cycles = chs.hw_cycles;
1265 systime_snapshot->hw_csid = chs.hw_csid;
1266
1206 systime_snapshot->cs_was_changed_seq = tk->cs_was_changed_seq;1267 systime_snapshot->cs_was_changed_seq = tk->cs_was_changed_seq;
1207 systime_snapshot->clock_was_set_seq = tk->clock_was_set_seq;1268 systime_snapshot->clock_was_set_seq = tk->clock_was_set_seq;
1208 base_real = ktime_add(tk->tkr_mono.base,1269
1209 tk_core.timekeeper.offs_real);1270 base_sys = tk->tkr_mono.base;
1210 base_boot = ktime_add(tk->tkr_mono.base,1271 offs_sys = *offs;
1211 tk_core.timekeeper.offs_boot);
1212 base_raw = tk->tkr_raw.base;1272 base_raw = tk->tkr_raw.base;
1213 nsec_real = timekeeping_cycles_to_ns(&tk->tkr_mono, now);1273
1214 nsec_raw = timekeeping_cycles_to_ns(&tk->tkr_raw, now);1274 nsec_sys = timekeeping_cycles_to_ns(&tk->tkr_mono, now);
1215 } while (read_seqcount_retry(&tk_core.seq, seq));1275 nsec_raw = timekeeping_cycles_to_ns(&tk->tkr_raw, now);
1276 } while (read_seqcount_retry(&tkd->seq, seq));
1216 1277
1217 systime_snapshot->cycles = now;1278 systime_snapshot->cycles = now;
1218 systime_snapshot->real = ktime_add_ns(base_real, nsec_real);1279 systime_snapshot->systime = ktime_add_ns(base_sys, offs_sys + nsec_sys);
1219 systime_snapshot->boot = ktime_add_ns(base_boot, nsec_real);1280 systime_snapshot->monoraw = ktime_add_ns(base_raw, nsec_raw);
1220 systime_snapshot->raw = ktime_add_ns(base_raw, nsec_raw);1281
1282 /*
1283 * Special case for PTP. Just transfer the raw time into sys,
1284 * so the call sites can consistently use snap::systime.
1285 */
1286 if (clock_id == CLOCK_MONOTONIC_RAW)
1287 systime_snapshot->systime = systime_snapshot->monoraw;
1288 /* Tell the consumer that this snapshot is valid */
1289 systime_snapshot->valid = true;
1221}1290}
1222EXPORT_SYMBOL_GPL(ktime_get_snapshot);1291EXPORT_SYMBOL_GPL(ktime_get_snapshot_id);
1223 1292
1224/* Scale base by mult/div checking for overflow */1293/* Scale base by mult/div checking for overflow */
1225static int scale64_check_overflow(u64 mult, u64 div, u64 *base)1294static int scale64_check_overflow(u64 mult, u64 div, u64 *base)
@@ -1262,7 +1331,7 @@ static int adjust_historical_crosststamp(struct system_time_snapshot *history, · 36 unmodified lines
1262 struct system_device_crosststamp *ts)1331 struct system_device_crosststamp *ts)
1263{1332{
1264 struct timekeeper *tk = &tk_core.timekeeper;1333 struct timekeeper *tk = &tk_core.timekeeper;
1265 u64 corr_raw, corr_real;1334 u64 corr_raw, corr_sys;
1266 bool interp_forward;1335 bool interp_forward;
1267 int ret;1336 int ret;
1268 1337
@@ -1279,8 +1348,7 @@ static int adjust_historical_crosststamp(struct system_time_snapshot *history, · 10 unmodified lines
1279 * Scale the monotonic raw time delta by:1348 * Scale the monotonic raw time delta by:
1280 * partial_history_cycles / total_history_cycles1349 * partial_history_cycles / total_history_cycles
1281 */1350 */
1282 corr_raw = (u64)ktime_to_ns(1351 corr_raw = (u64)ktime_to_ns(ktime_sub(ts->sys_monoraw, history->monoraw));
1283 ktime_sub(ts->sys_monoraw, history->raw));
1284 ret = scale64_check_overflow(partial_history_cycles,1352 ret = scale64_check_overflow(partial_history_cycles,
1285 total_history_cycles, &corr_raw);1353 total_history_cycles, &corr_raw);
1286 if (ret)1354 if (ret)
@@ -1288,30 +1356,29 @@ static int adjust_historical_crosststamp(struct system_time_snapshot *history, · 1 unmodified line
1288 1356
1289 /*1357 /*
1290 * If there is a discontinuity in the history, scale monotonic raw1358 * If there is a discontinuity in the history, scale monotonic raw
1291 * correction by:1359 * correction by:
1292 * mult(real)/mult(raw) yielding the realtime correction1360 * mult(sys)/mult(raw) yielding the system time correction
1293 * Otherwise, calculate the realtime correction similar to monotonic1361 *
1294 * raw calculation1362 * Otherwise, calculate the system time correction similar to monotonic
1363 * raw calculation
1295 */1364 */
1296 if (discontinuity) {1365 if (discontinuity) {
1297 corr_real = mul_u64_u32_div1366 corr_sys = mul_u64_u32_div(corr_raw, tk->tkr_mono.mult, tk->tkr_raw.mult);
1298 (corr_raw, tk->tkr_mono.mult, tk->tkr_raw.mult);
1299 } else {1367 } else {
1300 corr_real = (u64)ktime_to_ns(1368 corr_sys = (u64)ktime_to_ns(ktime_sub(ts->sys_systime, history->systime));
1301 ktime_sub(ts->sys_realtime, history->real));1369 ret = scale64_check_overflow(partial_history_cycles, total_history_cycles,
1302 ret = scale64_check_overflow(partial_history_cycles,1370 &corr_sys);
1303 total_history_cycles, &corr_real);
1304 if (ret)1371 if (ret)
1305 return ret;1372 return ret;
1306 }1373 }
1307 1374
1308 /* Fixup monotonic raw and real time time values */1375 /* Fixup monotonic raw and system time time values */
1309 if (interp_forward) {1376 if (interp_forward) {
1310 ts->sys_monoraw = ktime_add_ns(history->raw, corr_raw);1377 ts->sys_monoraw = ktime_add_ns(history->monoraw, corr_raw);
1311 ts->sys_realtime = ktime_add_ns(history->real, corr_real);1378 ts->sys_systime = ktime_add_ns(history->systime, corr_sys);
1312 } else {1379 } else {
1313 ts->sys_monoraw = ktime_sub_ns(ts->sys_monoraw, corr_raw);1380 ts->sys_monoraw = ktime_sub_ns(ts->sys_monoraw, corr_raw);
1314 ts->sys_realtime = ktime_sub_ns(ts->sys_realtime, corr_real);1381 ts->sys_systime = ktime_sub_ns(ts->sys_systime, corr_sys);
1315 }1382 }
1316 1383
1317 return 0;1384 return 0;
@@ -1368,6 +1435,8 @@ static bool convert_base_to_cs(struct system_counterval_t *scv) · 50 unmodified lines
1368 return false;1435 return false;
1369 1436
1370 scv->cycles += base->offset;1437 scv->cycles += base->offset;
1438 /* Set the clocksource ID as scv::cycles is now clocksource based */
1439 scv->cs_id = cs->id;
1371 return true;1440 return true;
1372}1441}
1373 1442
@@ -1435,11 +1504,11 @@ EXPORT_SYMBOL_GPL(ktime_real_to_base_clock); · 61 unmodified lines
1435 1504
1436/**1505/**
1437 * get_device_system_crosststamp - Synchronously capture system/device timestamp1506 * get_device_system_crosststamp - Synchronously capture system/device timestamp
1438 * @get_time_fn: Callback to get simultaneous device time and1507 * @get_time_fn: Callback to get simultaneous device time and system counter
1439 * system counter from the device driver1508 * from the device driver
1440 * @ctx: Context passed to get_time_fn()1509 * @ctx: Context passed to get_time_fn()
1441 * @history_begin: Historical reference point used to interpolate system1510 * @history_begin: Historical reference point used to interpolate system time when
1442 * time when counter provided by the driver is before the current interval1511 * the counter value provided by the driver is before the current interval
1443 * @xtstamp: Receives simultaneously captured system and device time1512 * @xtstamp: Receives simultaneously captured system and device time
1444 *1513 *
1445 * Reads a timestamp from a device and correlates it to system time1514 * Reads a timestamp from a device and correlates it to system time
@@ -1452,36 +1521,54 @@ int get_device_system_crosststamp(int (*get_time_fn) · 6 unmodified lines
1452 struct system_time_snapshot *history_begin,1521 struct system_time_snapshot *history_begin,
1453 struct system_device_crosststamp *xtstamp)1522 struct system_device_crosststamp *xtstamp)
1454{1523{
1455 struct system_counterval_t system_counterval = {};1524 u64 syscnt_cycles, cycles, now, interval_start;
1456 struct timekeeper *tk = &tk_core.timekeeper;1525 unsigned int seq, clock_was_set_seq = 0;
1457 u64 cycles, now, interval_start;1526 ktime_t base_sys, base_raw, *offs;
1458 unsigned int clock_was_set_seq = 0;1527 u64 nsec_sys, nsec_raw;
1459 ktime_t base_real, base_raw;
1460 u64 nsec_real, nsec_raw;
1461 u8 cs_was_changed_seq;1528 u8 cs_was_changed_seq;
1462 unsigned int seq;
1463 bool do_interp;1529 bool do_interp;
1530 struct timekeeper *tk;
1531 struct tk_data *tkd;
1464 int ret;1532 int ret;
1465 1533
1534 switch (xtstamp->clock_id) {
1535 case CLOCK_REALTIME:
1536 tkd = &tk_core;
1537 offs = &tk_core.timekeeper.offs_real;
1538 break;
1539 case CLOCK_AUX ... CLOCK_AUX_LAST:
1540 tkd = aux_get_tk_data(xtstamp->clock_id);
1541 if (!tkd)
1542 return -ENODEV;
1543 offs = &tkd->timekeeper.offs_aux;
1544 break;
1545 default:
1546 WARN_ON_ONCE(1);
1547 return -ENODEV;
1548 }
1549
1550 tk = &tkd->timekeeper;
1551
1466 do {1552 do {
1467 seq = read_seqcount_begin(&tk_core.seq);1553 seq = read_seqcount_begin(&tkd->seq);
1468 /*1554 /*
1469 * Try to synchronously capture device time and a system1555 * Try to synchronously capture device time and a system
1470 * counter value calling back into the device driver1556 * counter value calling back into the device driver
1471 */1557 */
1472 ret = get_time_fn(&xtstamp->device, &system_counterval, ctx);1558 ret = get_time_fn(&xtstamp->device, &xtstamp->sys_counter, ctx);
1473 if (ret)1559 if (ret)
1474 return ret;1560 return ret;
1475 1561
1476 /*1562 /*
1477 * Verify that the clocksource ID associated with the captured1563 * Verify that the clocksource ID associated with the captured
1478 * system counter value is the same as for the currently1564 * system counter value is the same as for the currently
1479 * installed timekeeper clocksource1565 * installed timekeeper clocksource and convert to it.
1480 */1566 */
1481 if (system_counterval.cs_id == CSID_GENERIC ||1567 if (xtstamp->sys_counter.cs_id == CSID_GENERIC ||
1482 !convert_base_to_cs(&system_counterval))1568 !convert_base_to_cs(&xtstamp->sys_counter))
1483 return -ENODEV;1569 return -ENODEV;
1484 cycles = system_counterval.cycles;1570
1571 cycles = syscnt_cycles = xtstamp->sys_counter.cycles;
1485 1572
1486 /*1573 /*
1487 * Check whether the system counter value provided by the1574 * Check whether the system counter value provided by the
@@ -1498,15 +1585,14 @@ int get_device_system_crosststamp(int (*get_time_fn) · 10 unmodified lines
1498 do_interp = false;1585 do_interp = false;
1499 }1586 }
1500 1587
1501 base_real = ktime_add(tk->tkr_mono.base,1588 base_sys = ktime_add(tk->tkr_mono.base, *offs);
1502 tk_core.timekeeper.offs_real);
1503 base_raw = tk->tkr_raw.base;1589 base_raw = tk->tkr_raw.base;
1504 1590
1505 nsec_real = timekeeping_cycles_to_ns(&tk->tkr_mono, cycles);1591 nsec_sys = timekeeping_cycles_to_ns(&tk->tkr_mono, cycles);
1506 nsec_raw = timekeeping_cycles_to_ns(&tk->tkr_raw, cycles);1592 nsec_raw = timekeeping_cycles_to_ns(&tk->tkr_raw, cycles);
1507 } while (read_seqcount_retry(&tk_core.seq, seq));1593 } while (read_seqcount_retry(&tkd->seq, seq));
1508 1594
1509 xtstamp->sys_realtime = ktime_add_ns(base_real, nsec_real);1595 xtstamp->sys_systime = ktime_add_ns(base_sys, nsec_sys);
1510 xtstamp->sys_monoraw = ktime_add_ns(base_raw, nsec_raw);1596 xtstamp->sys_monoraw = ktime_add_ns(base_raw, nsec_raw);
1511 1597
1512 /*1598 /*
@@ -1523,24 +1609,19 @@ int get_device_system_crosststamp(int (*get_time_fn) · 10 unmodified lines
1523 * clocksource change1609 * clocksource change
1524 */1610 */
1525 if (!history_begin ||1611 if (!history_begin ||
1526 !timestamp_in_interval(history_begin->cycles,1612 !timestamp_in_interval(history_begin->cycles, cycles, syscnt_cycles) ||
1527 cycles, system_counterval.cycles) ||
1528 history_begin->cs_was_changed_seq != cs_was_changed_seq)1613 history_begin->cs_was_changed_seq != cs_was_changed_seq)
1529 return -EINVAL;1614 return -EINVAL;
1530 partial_history_cycles = cycles - system_counterval.cycles;1615
1616 partial_history_cycles = cycles - syscnt_cycles;
1531 total_history_cycles = cycles - history_begin->cycles;1617 total_history_cycles = cycles - history_begin->cycles;
1532 discontinuity =1618 discontinuity = history_begin->clock_was_set_seq != clock_was_set_seq;
1533 history_begin->clock_was_set_seq != clock_was_set_seq;
1534 1619
1535 ret = adjust_historical_crosststamp(history_begin,1620 ret = adjust_historical_crosststamp(history_begin, partial_history_cycles,
1536 partial_history_cycles,1621 total_history_cycles, discontinuity, xtstamp);
1537 total_history_cycles,
1538 discontinuity, xtstamp);
1539 if (ret)
1540 return ret;
1541 }1622 }
1542 1623
1543 return 0;1624 return ret;
1544}1625}
1545EXPORT_SYMBOL_GPL(get_device_system_crosststamp);1626EXPORT_SYMBOL_GPL(get_device_system_crosststamp);
1546 1627
sound/hda/common/controller.c+2−2
@@ -491,9 +491,9 @@ static int azx_get_time_info(struct snd_pcm_substream *substream, · 490 unmodified lines
491 struct snd_pcm_audio_tstamp_config *audio_tstamp_config,491 struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
492 struct snd_pcm_audio_tstamp_report *audio_tstamp_report)492 struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
493{493{
494 struct system_device_crosststamp xtstamp = { .clock_id = CLOCK_REALTIME };
494 struct azx_dev *azx_dev = get_azx_dev(substream);495 struct azx_dev *azx_dev = get_azx_dev(substream);
495 struct snd_pcm_runtime *runtime = substream->runtime;496 struct snd_pcm_runtime *runtime = substream->runtime;
496 struct system_device_crosststamp xtstamp;
497 int ret;497 int ret;
498 u64 nsec;498 u64 nsec;
499 499
@@ -527,7 +527,7 @@ static int azx_get_time_info(struct snd_pcm_substream *substream, · 27 unmodified lines
527 break;527 break;
528 528
529 default:529 default:
530 *system_ts = ktime_to_timespec64(xtstamp.sys_realtime);530 *system_ts = ktime_to_timespec64(xtstamp.sys_systime);
531 break;531 break;
532 532
533 }533 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t