i40e: save PTP time before a device reset
authorJacob Keller <jacob.e.keller@intel.com>
Tue, 12 Feb 2019 21:56:24 +0000 (13:56 -0800)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Tue, 16 Apr 2019 22:10:38 +0000 (15:10 -0700)
commitbf4bf09bdd91a75bb175c172b3f7251a4845f591
tree228509a0e10cbaf4543c723bb9e3f7c12d61ef9a
parentbfb0ebed53857cfc57f11c63fa3689940d71c1c8
i40e: save PTP time before a device reset

In the case where PTP is running on the hardware clock, but the kernel
system time is not being synced, a device reset can mess up the clock
time.

This occurs because we reset the clock time based on the kernel time
every reset. This causes us to potentially completely reset the PTP
time, and can cause unexpected behavior in programs like ptp4l.

Avoid this by saving the PTP time prior to device reset, and then
restoring using that time after the reset.

Directly restoring the PTP time we saved isn't perfect, because time
should have continued running, but the clock will essentially be stopped
during the reset. This is still better than the current solution of
assuming that the PTP HW clock is synced to the CLOCK_REALTIME.

We can do even better, by saving the ktime and calculating
a differential, using ktime_get(). This is based on CLOCK_MONOTONIC, and
allows us to get a fairly precise measure of the time difference between
saving and restoring the time.

Using this, we can update the saved PTP time, and use that as the value
to write to the hardware clock registers. This, of course is not perfect.
However, it does help ensure that the PTP time is restored as close as
feasible to the time it should have been if the reset had not occurred.

During device initialization, continue using the system time as the
source for the creation of the PTP clock, since this is the best known
current time source at driver load.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_ptp.c