summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/sfc/ptp.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2014-02-12 18:58:46 +0000
committerDavid S. Miller <davem@davemloft.net>2014-02-12 17:53:34 -0500
commit92d8f766ecce190dc2aa5d1aa9a5f5381e831641 (patch)
tree667ccab328087bc603b872f2dd4b8f1e9d4f6f4f /drivers/net/ethernet/sfc/ptp.c
parentce320f44d677549a29ae8d6ae79e66d1c997f87a (diff)
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: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: Shradha Shah <sshah@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/sfc/ptp.c')
-rw-r--r--drivers/net/ethernet/sfc/ptp.c47
1 files changed, 23 insertions, 24 deletions
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index 7d0de5002f41..28275e395cb8 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -766,37 +766,36 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
return -EAGAIN;
}
- /* Convert the NIC time 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 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
+ /* Calculate delay from last good sync (host time) to last_time.
+ * It is possible that the seconds rolled over between taking
* 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
- * expected.
+ * expected. delta is *not* normalised.
*/
start_sec = ptp->timeset[last_good].host_start >> MC_NANOSECOND_BITS;
last_sec = last_time->ts_real.tv_sec & MC_SECOND_MASK;
- if (start_sec != last_sec) {
- if (((start_sec + 1) & MC_SECOND_MASK) != last_sec) {
- netif_warn(efx, hw, efx->net_dev,
- "PTP bad synchronisation seconds\n");
- return -EAGAIN;
- } else {
- delta.tv_sec = 1;
- }
- } else {
- delta.tv_sec = 0;
+ if (start_sec != last_sec &&
+ ((start_sec + 1) & MC_SECOND_MASK) != last_sec) {
+ netif_warn(efx, hw, efx->net_dev,
+ "PTP bad synchronisation seconds\n");
+ return -EAGAIN;
}
+ 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;
pps_sub_ts(&ptp->host_time_pps, delta);