Skip to content
Permalink
Browse files
hv_utils: return error if host timesysnc update is stale
If for any reason, host timesync messages were not processed by
the guest, hv_ptp_gettime() returns a stale value and the
caller (clock_gettime, PTP ioctl etc) has no means to know this
now. Return an error so that the caller knows about this.

Signed-off-by: Vineeth Pillai <viremana@linux.microsoft.com>
  • Loading branch information
Vineeth Pillai authored and intel-lab-lkp committed Aug 19, 2020
1 parent 18445bf commit 89495ac7e3c97f1a96ba77a67b532cdeaddc624c
Showing 1 changed file with 35 additions and 11 deletions.
@@ -282,26 +282,52 @@ static struct {
spinlock_t lock;
} host_ts;

static struct timespec64 hv_get_adj_host_time(void)
static inline u64 reftime_to_ns(u64 reftime)
{
struct timespec64 ts;
u64 newtime, reftime;
return (reftime - WLTIMEDELTA) * 100;
}

/*
* Hard coded threshold for host timesync delay: 600 seconds
*/
const u64 HOST_TIMESYNC_DELAY_THRESH = 600 * NSEC_PER_SEC;

static int hv_get_adj_host_time(struct timespec64 *ts)
{
u64 newtime, reftime, timediff_adj;
unsigned long flags;
int ret = 0;

spin_lock_irqsave(&host_ts.lock, flags);
reftime = hv_read_reference_counter();
newtime = host_ts.host_time + (reftime - host_ts.ref_time);
ts = ns_to_timespec64((newtime - WLTIMEDELTA) * 100);

/*
* We need to let the caller know that last update from host
* is older than the max allowable threshold. clock_gettime()
* and PTP ioctl do not have a documented error that we could
* return for this specific case. Use ESTALE to report this.
*/
timediff_adj = reftime - host_ts.ref_time;
if (timediff_adj * 100 > HOST_TIMESYNC_DELAY_THRESH) {
pr_warn("TIMESYNC IC: Stale time stamp, %llu nsecs old\n",
HOST_TIMESYNC_DELAY_THRESH);
ret = -ESTALE;
}

newtime = host_ts.host_time + timediff_adj;
*ts = ns_to_timespec64(reftime_to_ns(newtime));
spin_unlock_irqrestore(&host_ts.lock, flags);

return ts;
return ret;
}

static void hv_set_host_time(struct work_struct *work)
{
struct timespec64 ts = hv_get_adj_host_time();

do_settimeofday64(&ts);
struct timespec64 ts;

if (!hv_get_adj_host_time(&ts))
do_settimeofday64(&ts);
}

/*
@@ -622,9 +648,7 @@ static int hv_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)

static int hv_ptp_gettime(struct ptp_clock_info *info, struct timespec64 *ts)
{
*ts = hv_get_adj_host_time();

return 0;
return hv_get_adj_host_time(ts);
}

static struct ptp_clock_info ptp_hyperv_info = {

0 comments on commit 89495ac

Please sign in to comment.