Commit 92d8f766 authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller

sfc: Rewrite adjustment of PPS event in a clearer way

There is substantial latency in generation and handling of PPS events
from the NIC, which we have to correct for before passing a host
timestamp to the PPS subsystem.  We compare clocks with the MC,
giving us two offsets to subtract from the timestamp generated by
pps_get_ts():

(a) Time from the last good sync (where we got host and NIC timestamps
    for nearly the same instant) to the time we called pps_get_ts()
(b) Time from NIC top of second to the last good sync

We currently calculate (a) + (b) in a quite confusing way.
Instead, calculate (a) completely, then add (b) to it.
Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarShradha Shah <sshah@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ce320f44
...@@ -766,37 +766,36 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), ...@@ -766,37 +766,36 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
return -EAGAIN; return -EAGAIN;
} }
/* Convert the NIC time into kernel time. No correction is required- /* Calculate delay from last good sync (host time) to last_time.
* this time is the output of a firmware process. * It is possible that the seconds rolled over between taking
*/
mc_time = ptp->nic_to_kernel_time(ptp->timeset[last_good].major,
ptp->timeset[last_good].minor, 0);
/* Calculate delay from actual PPS to last_time */
delta = ktime_to_timespec(mc_time);
delta.tv_nsec +=
last_time->ts_real.tv_nsec -
(ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK);
/* It is possible that the seconds rolled over between taking
* the start reading and the last value written by the host. The * the start reading and the last value written by the host. The
* timescales are such that a gap of more than one second is never * timescales are such that a gap of more than one second is never
* expected. * expected. delta is *not* normalised.
*/ */
start_sec = ptp->timeset[last_good].host_start >> MC_NANOSECOND_BITS; start_sec = ptp->timeset[last_good].host_start >> MC_NANOSECOND_BITS;
last_sec = last_time->ts_real.tv_sec & MC_SECOND_MASK; last_sec = last_time->ts_real.tv_sec & MC_SECOND_MASK;
if (start_sec != last_sec) { if (start_sec != last_sec &&
if (((start_sec + 1) & MC_SECOND_MASK) != last_sec) { ((start_sec + 1) & MC_SECOND_MASK) != last_sec) {
netif_warn(efx, hw, efx->net_dev, netif_warn(efx, hw, efx->net_dev,
"PTP bad synchronisation seconds\n"); "PTP bad synchronisation seconds\n");
return -EAGAIN; return -EAGAIN;
} else {
delta.tv_sec = 1;
}
} else {
delta.tv_sec = 0;
} }
delta.tv_sec = (last_sec - start_sec) & 1;
delta.tv_nsec =
last_time->ts_real.tv_nsec -
(ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK);
/* Convert the NIC time at last good sync into kernel time.
* No correction is required - this time is the output of a
* firmware process.
*/
mc_time = ptp->nic_to_kernel_time(ptp->timeset[last_good].major,
ptp->timeset[last_good].minor, 0);
/* Calculate delay from NIC top of second to last_time */
delta.tv_nsec += ktime_to_timespec(mc_time).tv_nsec;
/* Set PPS timestamp to match NIC top of second */
ptp->host_time_pps = *last_time; ptp->host_time_pps = *last_time;
pps_sub_ts(&ptp->host_time_pps, delta); pps_sub_ts(&ptp->host_time_pps, delta);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment