projects/linux·commit 2d6d57f8

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

2d6d57f8 · Linus Torvalds <[email protected]> · 2026-06-15 13:51:27 +05:30

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()
  ...
Commit
2d6d57f889f3a5e7d19009c560ea2002cdde9fb8
Parents
a53fcff8 · bc484a50

Merge commit. Changes below are compared with the first parent: a53fcff8.

Changes

23 files changed · +348 −194

Only the first 600 diff lines are shown. Download the complete patch.

arch/arm64/kvm/hyp_trace.c

View file
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
index c4b3ee5..2411b4c 100644
--- a/arch/arm64/kvm/hyp_trace.c
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -51,8 +51,8 @@ static void __hyp_clock_work(struct work_struct *work)
hyp_clock = container_of(dwork, struct hyp_trace_clock, work);
- ktime_get_snapshot(&snap);
- boot = ktime_to_ns(snap.boot);
+ ktime_get_snapshot_id(CLOCK_BOOTTIME, &snap);
+ boot = ktime_to_ns(snap.systime);
delta_boot = boot - hyp_clock->boot;
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
hyp_clock->running = false;
}
- ktime_get_snapshot(&snap);
+ ktime_get_snapshot_id(CLOCK_BOOTTIME, &snap);
- hyp_clock->boot = ktime_to_ns(snap.boot);
+ hyp_clock->boot = ktime_to_ns(snap.systime);
hyp_clock->cycles = snap.cycles;
hyp_clock->mult = 0;

arch/arm64/kvm/hypercalls.c

View file
diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
index 58c5fe7..b11b882 100644
--- a/arch/arm64/kvm/hypercalls.c
+++ b/arch/arm64/kvm/hypercalls.c
@@ -28,7 +28,7 @@ static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val)
* system time and counter value must captured at the same
* time to keep consistency and precision.
*/
- ktime_get_snapshot(&systime_snapshot);
+ ktime_get_snapshot_id(CLOCK_REALTIME, &systime_snapshot);
/*
* 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)
* in the future (about 292 years from 1970, and at that stage
* nobody will give a damn about it).
*/
- val[0] = upper_32_bits(systime_snapshot.real);
- val[1] = lower_32_bits(systime_snapshot.real);
+ val[0] = upper_32_bits(systime_snapshot.systime);
+ val[1] = lower_32_bits(systime_snapshot.systime);
val[2] = upper_32_bits(cycles);
val[3] = lower_32_bits(cycles);
}

arch/x86/kernel/kvmclock.c

View file
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index b5991d5..cb3d0ca 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -87,6 +87,27 @@ static u64 kvm_clock_get_cycles(struct clocksource *cs)
return kvm_clock_read();
}
+static u64 kvm_clock_get_cycles_snapshot(struct clocksource *cs,
+ struct clocksource_hw_snapshot *chs)
+{
+ struct pvclock_vcpu_time_info *src;
+ unsigned version;
+ u64 ret, tsc;
+
+ preempt_disable_notrace();
+ src = this_cpu_pvti();
+ do {
+ version = pvclock_read_begin(src);
+ tsc = rdtsc_ordered();
+ ret = __pvclock_read_cycles(src, tsc);
+ } while (pvclock_read_retry(src, version));
+ preempt_enable_notrace();
+
+ chs->hw_cycles = tsc;
+ chs->hw_csid = CSID_X86_TSC;
+ return ret;
+}
+
static noinstr u64 kvm_sched_clock_read(void)
{
return pvclock_clocksource_read_nowd(this_cpu_pvti()) - kvm_sched_clock_offset;
@@ -156,13 +177,14 @@ static int kvm_cs_enable(struct clocksource *cs)
}
static struct clocksource kvm_clock = {
- .name = "kvm-clock",
- .read = kvm_clock_get_cycles,
- .rating = 400,
- .mask = CLOCKSOURCE_MASK(64),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
- .id = CSID_X86_KVM_CLK,
- .enable = kvm_cs_enable,
+ .name = "kvm-clock",
+ .read = kvm_clock_get_cycles,
+ .read_snapshot = kvm_clock_get_cycles_snapshot,
+ .rating = 400,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .id = CSID_X86_KVM_CLK,
+ .enable = kvm_cs_enable,
};
static void kvm_register_clock(char *txt)

drivers/clocksource/hyperv_timer.c

View file
diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c
index e9f5034..df56779 100644
--- a/drivers/clocksource/hyperv_timer.c
+++ b/drivers/clocksource/hyperv_timer.c
@@ -444,6 +444,22 @@ static u64 notrace read_hv_clock_tsc_cs(struct clocksource *arg)
return read_hv_clock_tsc();
}
+static u64 notrace read_hv_clock_tsc_cs_snapshot(struct clocksource *arg,
+ struct clocksource_hw_snapshot *chs)
+{
+ u64 time;
+
+ if (hv_read_tsc_page_tsc(tsc_page, &chs->hw_cycles, &time)) {
+ chs->hw_csid = CSID_X86_TSC;
+ } else {
+ chs->hw_cycles = 0;
+ chs->hw_csid = CSID_GENERIC;
+ time = read_hv_clock_msr();
+ }
+
+ return time;
+}
+
static u64 noinstr read_hv_sched_clock_tsc(void)
{
return (read_hv_clock_tsc() - hv_sched_clock_offset) *
@@ -492,18 +508,19 @@ static int hv_cs_enable(struct clocksource *cs)
#endif
static struct clocksource hyperv_cs_tsc = {
- .name = "hyperv_clocksource_tsc_page",
- .rating = 500,
- .read = read_hv_clock_tsc_cs,
- .mask = CLOCKSOURCE_MASK(64),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
- .suspend= suspend_hv_clock_tsc,
- .resume = resume_hv_clock_tsc,
+ .name = "hyperv_clocksource_tsc_page",
+ .rating = 500,
+ .read = read_hv_clock_tsc_cs,
+ .read_snapshot = read_hv_clock_tsc_cs_snapshot,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .suspend = suspend_hv_clock_tsc,
+ .resume = resume_hv_clock_tsc,
#ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK
- .enable = hv_cs_enable,
- .vdso_clock_mode = VDSO_CLOCKMODE_HVCLOCK,
+ .enable = hv_cs_enable,
+ .vdso_clock_mode = VDSO_CLOCKMODE_HVCLOCK,
#else
- .vdso_clock_mode = VDSO_CLOCKMODE_NONE,
+ .vdso_clock_mode = VDSO_CLOCKMODE_NONE,
#endif
};

drivers/net/dsa/sja1105/sja1105_main.c

View file
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index c72c2bf..2697073 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -2310,10 +2310,10 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
goto out;
}
- t1 = timespec64_to_ns(&ptp_sts_before.pre_ts);
- t2 = timespec64_to_ns(&ptp_sts_before.post_ts);
- t3 = timespec64_to_ns(&ptp_sts_after.pre_ts);
- t4 = timespec64_to_ns(&ptp_sts_after.post_ts);
+ t1 = ktime_to_ns(ptp_sts_before.pre_sts.systime);
+ t2 = ktime_to_ns(ptp_sts_before.post_sts.systime);
+ t3 = ktime_to_ns(ptp_sts_after.pre_sts.systime);
+ t4 = ktime_to_ns(ptp_sts_after.post_sts.systime);
/* Mid point, corresponds to pre-reset PTPCLKVAL */
t12 = t1 + (t2 - t1) / 2;
/* Mid point, corresponds to post-reset PTPCLKVAL, aka 0 */

drivers/net/ethernet/intel/ice/ice_ptp.c

View file
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 36df742..f9e4ec6 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -2065,11 +2065,13 @@ static const struct ice_crosststamp_cfg ice_crosststamp_cfg_e830 = {
/**
* struct ice_crosststamp_ctx - Device cross timestamp context
* @snapshot: snapshot of system clocks for historic interpolation
+ * @snapshot_clock_id: System clock ID for @snapshot
* @pf: pointer to the PF private structure
* @cfg: pointer to hardware configuration for cross timestamp
*/
struct ice_crosststamp_ctx {
struct system_time_snapshot snapshot;
+ clockid_t snapshot_clock_id;
struct ice_pf *pf;
const struct ice_crosststamp_cfg *cfg;
};
@@ -2115,7 +2117,7 @@ static int ice_capture_crosststamp(ktime_t *device,
}
/* Snapshot system time for historic interpolation */
- ktime_get_snapshot(&ctx->snapshot);
+ ktime_get_snapshot_id(ctx->snapshot_clock_id, &ctx->snapshot);
/* Program cmd to master timer */
ice_ptp_src_cmd(hw, ICE_PTP_READ_TIME);
@@ -2176,6 +2178,7 @@ static int ice_ptp_getcrosststamp(struct ptp_clock_info *info,
{
struct ice_pf *pf = ptp_info_to_pf(info);
struct ice_crosststamp_ctx ctx = {
+ .snapshot_clock_id = cts->clock_id,
.pf = pf,
};

drivers/net/ethernet/intel/igc/igc.h

View file
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index 1723681..46d625b 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -326,6 +326,7 @@ struct igc_adapter {
struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */
ktime_t ptp_reset_start; /* Reset time in clock mono */
struct system_time_snapshot snapshot;
+ clockid_t snapshot_clock_id;
struct mutex ptm_lock; /* Only allow one PTM transaction at a time */
char fw_version[32];

drivers/net/ethernet/intel/igc/igc_ptp.c

View file
diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c
index 3d6b226..b40aba9 100644
--- a/drivers/net/ethernet/intel/igc/igc_ptp.c
+++ b/drivers/net/ethernet/intel/igc/igc_ptp.c
@@ -1049,7 +1049,7 @@ static int igc_phc_get_syncdevicetime(ktime_t *device,
*/
do {
/* Get a snapshot of system clocks to use as historic value. */
- ktime_get_snapshot(&adapter->snapshot);
+ ktime_get_snapshot_id(adapter->snapshot_clock_id, &adapter->snapshot);
igc_ptm_trigger(hw);
@@ -1103,6 +1103,8 @@ static int igc_ptp_getcrosststamp(struct ptp_clock_info *ptp,
/* This blocks until any in progress PTM transactions complete */
mutex_lock(&adapter->ptm_lock);
+ adapter->snapshot_clock_id = cts->clock_id;
+
ret = get_device_system_crosststamp(igc_phc_get_syncdevicetime,
adapter, &adapter->snapshot, cts);
mutex_unlock(&adapter->ptm_lock);

drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c

View file
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
index d785f1b..5df7861 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
@@ -340,7 +340,7 @@ static int mlx5_ptp_getcrosststamp(struct ptp_clock_info *ptp,
goto unlock;
}
- ktime_get_snapshot(&history_begin);
+ ktime_get_snapshot_id(cts->clock_id, &history_begin);
err = get_device_system_crosststamp(mlx5_mtctr_syncdevicetime, mdev,
&history_begin, cts);
@@ -366,7 +366,7 @@ static int mlx5_ptp_getcrosscycles(struct ptp_clock_info *ptp,
goto unlock;
}
- ktime_get_snapshot(&history_begin);
+ ktime_get_snapshot_id(cts->clock_id, &history_begin);
err = get_device_system_crosststamp(mlx5_mtctr_syncdevicecyclestime,
mdev, &history_begin, cts);

drivers/net/wireless/intel/iwlwifi/mld/ptp.c

View file
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ptp.c b/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
index c65f4b5..f829156 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
@@ -250,7 +250,8 @@ iwl_mld_phc_get_crosstimestamp(struct ptp_clock_info *ptp,
/* System (wall) time */
ktime_t sys_time;
- memset(xtstamp, 0, sizeof(struct system_device_crosststamp));
+ if (xtstamp->clock_id != CLOCK_REALTIME)
+ return -ENOTSUPP;
ret = iwl_mld_get_crosstimestamp_fw(mld, &gp2, &sys_time);
if (ret) {
@@ -270,7 +271,7 @@ iwl_mld_phc_get_crosstimestamp(struct ptp_clock_info *ptp,
/* System monotonic raw time is not used */
xtstamp->device = ns_to_ktime(gp2_ns);
- xtstamp->sys_realtime = sys_time;
+ xtstamp->sys_systime = sys_time;
return ret;
}

drivers/net/wireless/intel/iwlwifi/mvm/ptp.c

View file
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c b/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
index f7b6201..bcd6f7c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
@@ -160,13 +160,14 @@ iwl_mvm_phc_get_crosstimestamp(struct ptp_clock_info *ptp,
/* System (wall) time */
ktime_t sys_time;
- memset(xtstamp, 0, sizeof(struct system_device_crosststamp));
-
if (!mvm->ptp_data.ptp_clock) {
IWL_ERR(mvm, "No PHC clock registered\n");
return -ENODEV;
}
+ if (xtstamp->clock_id != CLOCK_REALTIME)
+ return -ENOTSUPP;
+
mutex_lock(&mvm->mutex);
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SYNCED_TIME)) {
ret = iwl_mvm_get_crosstimestamp_fw(mvm, &gp2, &sys_time);
@@ -184,7 +185,7 @@ iwl_mvm_phc_get_crosstimestamp(struct ptp_clock_info *ptp,
/* System monotonic raw time is not used */
xtstamp->device = (ktime_t)gp2_ns;
- xtstamp->sys_realtime = sys_time;
+ xtstamp->sys_systime = sys_time;
out:
mutex_unlock(&mvm->mutex);

drivers/pps/generators/pps_gen-dummy.c

View file
diff --git a/drivers/pps/generators/pps_gen-dummy.c b/drivers/pps/generators/pps_gen-dummy.c
index 547fa7f..a439554 100644
--- a/drivers/pps/generators/pps_gen-dummy.c
+++ b/drivers/pps/generators/pps_gen-dummy.c
@@ -39,11 +39,7 @@ static void pps_gen_ktimer_event(struct timer_list *unused)
static int pps_gen_dummy_get_time(struct pps_gen_device *pps_gen,
struct timespec64 *time)
{
- struct system_time_snapshot snap;
-
- ktime_get_snapshot(&snap);
- *time = ktime_to_timespec64(snap.real);
-
+ ktime_get_real_ts64(time);
return 0;
}

drivers/pps/generators/pps_gen_tio.c

View file
diff --git a/drivers/pps/generators/pps_gen_tio.c b/drivers/pps/generators/pps_gen_tio.c
index de00a85..9483d12 100644
--- a/drivers/pps/generators/pps_gen_tio.c
+++ b/drivers/pps/generators/pps_gen_tio.c
@@ -189,11 +189,7 @@ static int pps_tio_gen_enable(struct pps_gen_device *pps_gen, bool enable)
static int pps_tio_get_time(struct pps_gen_device *pps_gen,
struct timespec64 *time)
{
- struct system_time_snapshot snap;
-
- ktime_get_snapshot(&snap);
- *time = ktime_to_timespec64(snap.real);
-
+ ktime_get_real_ts64(time);
return 0;
}

drivers/ptp/ptp_chardev.c

View file
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index c61cf9e..dc23cd7 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -317,8 +317,8 @@ typedef int (*ptp_crosststamp_fn)(struct ptp_clock_info *,
static long ptp_sys_offset_precise(struct ptp_clock *ptp, void __user *arg,
ptp_crosststamp_fn crosststamp_fn)
{
+ struct system_device_crosststamp xtstamp = { .clock_id = CLOCK_REALTIME };
struct ptp_sys_offset_precise precise_offset;
- struct system_device_crosststamp xtstamp;
struct timespec64 ts;
int err;
@@ -333,7 +333,7 @@ static long ptp_sys_offset_precise(struct ptp_clock *ptp, void __user *arg,
ts = ktime_to_timespec64(xtstamp.device);
precise_offset.device.sec = ts.tv_sec;
precise_offset.device.nsec = ts.tv_nsec;
- ts = ktime_to_timespec64(xtstamp.sys_realtime);
+ ts = ktime_to_timespec64(xtstamp.sys_systime);
precise_offset.sys_realtime.sec = ts.tv_sec;
precise_offset.sys_realtime.nsec = ts.tv_nsec;
ts = ktime_to_timespec64(xtstamp.sys_monoraw);
@@ -386,15 +386,19 @@ static long ptp_sys_offset_extended(struct ptp_clock *ptp, void __user *arg,
return err;
/* Filter out disabled or unavailable clocks */
- if (sts.pre_ts.tv_sec < 0 || sts.post_ts.tv_sec < 0)
+ if (!sts.pre_sts.valid || !sts.post_sts.valid)
return -EINVAL;
- extoff->ts[i][0].sec = sts.pre_ts.tv_sec;
- extoff->ts[i][0].nsec = sts.pre_ts.tv_nsec;
extoff->ts[i][1].sec = ts.tv_sec;
extoff->ts[i][1].nsec = ts.tv_nsec;
- extoff->ts[i][2].sec = sts.post_ts.tv_sec;
- extoff->ts[i][2].nsec = sts.post_ts.tv_nsec;
+
+ ts = ktime_to_timespec64(sts.pre_sts.systime);
+ extoff->ts[i][0].sec = ts.tv_sec;
+ extoff->ts[i][0].nsec = ts.tv_nsec;
+
+ ts = ktime_to_timespec64(sts.post_sts.systime);
+ extoff->ts[i][2].sec = ts.tv_sec;
+ extoff->ts[i][2].nsec = ts.tv_nsec;
}
return copy_to_user(arg, extoff, sizeof(*extoff)) ? -EFAULT : 0;

drivers/ptp/ptp_ocp.c

View file
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index 7353855..8231c2d 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -1491,11 +1491,8 @@ __ptp_ocp_gettime_locked(struct ptp_ocp *bp, struct timespec64 *ts,
}
ptp_read_system_postts(sts);
- if (sts && bp->ts_window_adjust) {
- s64 ns = timespec64_to_ns(&sts->post_ts);
-
- sts->post_ts = ns_to_timespec64(ns - bp->ts_window_adjust);
- }
+ if (sts && bp->ts_window_adjust)
+ sts->post_sts.systime -= bp->ts_window_adjust;
time_ns = ioread32(&bp->reg->time_ns);
time_sec = ioread32(&bp->reg->time_sec);
@@ -4600,8 +4597,8 @@ ptp_ocp_summary_show(struct seq_file *s, void *data)
struct timespec64 sys_ts;
s64 pre_ns, post_ns, ns;
- pre_ns = timespec64_to_ns(&sts.pre_ts);
- post_ns = timespec64_to_ns(&sts.post_ts);
+ pre_ns = ktime_to_ns(sts.pre_sts.systime);
+ post_ns = ktime_to_ns(sts.post_sts.systime);
ns = (pre_ns + post_ns) / 2;
ns += (s64)bp->utc_tai_offset * NSEC_PER_SEC;
sys_ts = ns_to_timespec64(ns);

drivers/ptp/ptp_vmclock.c

View file
diff --git a/drivers/ptp/ptp_vmclock.c b/drivers/ptp/ptp_vmclock.c
index 8b630eb..eebdcd5 100644
--- a/drivers/ptp/ptp_vmclock.c
+++ b/drivers/ptp/ptp_vmclock.c
@@ -101,7 +101,6 @@ static int vmclock_get_crosststamp(struct vmclock_state *st,
struct timespec64 *tspec)
{
ktime_t deadline = ktime_add(ktime_get(), VMCLOCK_MAX_WAIT);
- struct system_time_snapshot systime_snapshot;
uint64_t cycle, delta, seq, frac_sec;
#ifdef CONFIG_X86
@@ -132,17 +131,19 @@ static int vmclock_get_crosststamp(struct vmclock_state *st,
* will be derived from the *same* counter value.
*
* If the system isn't using the same counter, then the value
- * from ktime_get_snapshot() will still be used as pre_ts, and
- * ptp_read_system_postts() is called to populate postts after
- * calling get_cycles().
- *
- * The conversion to timespec64 happens further down, outside
- * the seq_count loop.
+ * from ptp_read_system_prets() will still be used as pre_ts,
+ * and ptp_read_system_postts() is called to populate postts
+ * after calling get_cycles().
*/
if (sts) {
- ktime_get_snapshot(&systime_snapshot);
- if (systime_snapshot.cs_id == st->cs_id) {
- cycle = systime_snapshot.cycles;
+ ptp_read_system_prets(sts);
+ if (sts->pre_sts.cs_id == st->cs_id) {
+ cycle = sts->pre_sts.cycles;
+ sts->post_sts = sts->pre_sts;
+ } else if (sts->pre_sts.hw_csid == st->cs_id &&
+ sts->pre_sts.hw_cycles) {
+ cycle = sts->pre_sts.hw_cycles;
+ sts->post_sts = sts->pre_sts;
} else {
cycle = get_cycles();
ptp_read_system_postts(sts);
@@ -180,12 +181,6 @@ static int vmclock_get_crosststamp(struct vmclock_state *st,
system_counter->cs_id = st->cs_id;
}
- if (sts) {
- sts->pre_ts = ktime_to_timespec64(systime_snapshot.real);
- if (systime_snapshot.cs_id == st->cs_id)
- sts->post_ts = sts->pre_ts;
- }
-
return 0;
}
@@ -272,7 +267,7 @@ static int ptp_vmclock_getcrosststamp(struct ptp_clock_info *ptp,
if (ret == -ENODEV) {
struct system_time_snapshot systime_snapshot;
- ktime_get_snapshot(&systime_snapshot);
+ ktime_get_snapshot_id(CLOCK_REALTIME, &systime_snapshot);
if (systime_snapshot.cs_id == CSID_X86_TSC ||
systime_snapshot.cs_id == CSID_X86_KVM_CLK) {

drivers/virtio/virtio_rtc_ptp.c

View file
diff --git a/drivers/virtio/virtio_rtc_ptp.c b/drivers/virtio/virtio_rtc_ptp.c
index f845999..ff8d834 100644
--- a/drivers/virtio/virtio_rtc_ptp.c
+++ b/drivers/virtio/virtio_rtc_ptp.c
@@ -139,7 +139,7 @@ static int viortc_ptp_getcrosststamp(struct ptp_clock_info *ptp,
if (ret)
return ret;
- ktime_get_snapshot(&history_begin);
+ ktime_get_snapshot_id(xtstamp->clock_id, &history_begin);
if (history_begin.cs_id != cs_id)
return -EOPNOTSUPP;

include/linux/clocksource.h

View file
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index b12a6d1..283d729 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -32,6 +32,21 @@ struct module;
#include <vdso/clocksource.h>
/**
+ * struct clocksource_hw_snapshot - Snapshot for the underlying hardware counter of derived
+ * clocksources like kvmclock or Hyper-V scaled TSC
+ * @hw_cycles: The hardware counter value
+ * @hw_csid: Clocksource ID of the hardware counter
+ *
+ * Such clocksources must implement the read_snapshot() callback and fill in the
+ * hardware counter value, the clocksource ID of the hardware counter and derive
+ * the actual clocksource cycles from @hw_cycles to provide an atomic snapshot
+ */
+struct clocksource_hw_snapshot {
+ u64 hw_cycles;
+ enum clocksource_ids hw_csid;
+};
+
+/**
* struct clocksource - hardware abstraction for a free running counter
* Provides mostly state-free accessors to the underlying hardware.
* This is the structure used for system time.
@@ -72,6 +87,14 @@ struct module;
* @flags: Flags describing special properties
* @base: Hardware abstraction for clock on which a clocksource
* is based
+ * @read_snapshot: Extended @read() function for clocksources such as
+ * kvmclock or the Hyper-V scaled TSC where the actual
+ * clocksource value for timekeeping is calculated from an
+ * underlying hardware counter. Returns the timekeeping
+ * relevant cycle value and stores the raw value of the
+ * underlying counter from which it was calculated
+ * including the clocksource ID of that counter in the
+ * clocksource hardware snapshot.
* @enable: Optional function to enable the clocksource
* @disable: Optional function to disable the clocksource
* @suspend: Optional suspend function for the clocksource
@@ -113,6 +136,7 @@ struct clocksource {
unsigned long flags;
struct clocksource_base *base;
+ u64 (*read_snapshot)(struct clocksource *cs, struct clocksource_hw_snapshot *chs);
int (*enable)(struct clocksource *cs);
void (*disable)(struct clocksource *cs);
void (*suspend)(struct clocksource *cs);

include/linux/pps_kernel.h

View file
diff --git a/include/linux/pps_kernel.h b/include/linux/pps_kernel.h
index aab0aeb..9f088c9 100644
--- a/include/linux/pps_kernel.h
+++ b/include/linux/pps_kernel.h
@@ -99,12 +99,14 @@ static inline void timespec_to_pps_ktime(struct pps_ktime *kt,
static inline void pps_get_ts(struct pps_event_time *ts)
{
+#ifdef CONFIG_NTP_PPS
struct system_time_snapshot snap;
- ktime_get_snapshot(&snap);
- ts->ts_real = ktime_to_timespec64(snap.real);
-#ifdef CONFIG_NTP_PPS
- ts->ts_raw = ktime_to_timespec64(snap.raw);
+ ktime_get_snapshot_id(CLOCK_REALTIME, &snap);
+ ts->ts_real = ktime_to_timespec64(snap.systime);
+ ts->ts_raw = ktime_to_timespec64(snap.monoraw);
+#else
+ ktime_get_real_ts64(&ts->ts_real);
#endif
}

include/linux/ptp_clock_kernel.h

View file
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index 8843645..36a27a9 100644
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -12,6 +12,7 @@
#include <linux/pps_kernel.h>
#include <linux/ptp_clock.h>
#include <linux/timecounter.h>
+#include <linux/timekeeping.h>
#include <linux/skbuff.h>
#define PTP_CLOCK_NAME_LEN 32
@@ -45,13 +46,13 @@ struct system_device_crosststamp;
/**
* struct ptp_system_timestamp - system time corresponding to a PHC timestamp

This diff is incomplete. Download the complete patch.

include/linux/timekeeping.h

View file

This diff is incomplete. Download the complete patch.

kernel/time/timekeeping.c

View file

This diff is incomplete. Download the complete patch.

sound/hda/common/controller.c

View file

This diff is incomplete. Download the complete patch.