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> Reviewed-by: Michael Kelley <mikelley@microsoft.com> Link: https://lore.kernel.org/r/20200821152523.99364-1-viremana@linux.microsoft.com Signed-off-by: Wei Liu <wei.liu@kernel.org>
This commit is contained in:
Родитель
b9d8cf2eb3
Коммит
90b125f4cd
|
@ -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
|
||||
*/
|
||||
static const u64 HOST_TIMESYNC_DELAY_THRESH = 600 * (u64)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_once("TIMESYNC IC: Stale time stamp, %llu nsecs old\n",
|
||||
(timediff_adj * 100));
|
||||
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 = {
|
||||
|
|
Загрузка…
Ссылка в новой задаче