Message ID | 20181109101449.15398-8-mlichvar@redhat.com |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
Series | More accurate PHC<->system clock synchronization | expand |
> -----Original Message----- > From: Miroslav Lichvar [mailto:mlichvar@redhat.com] > Sent: Friday, November 09, 2018 2:15 AM > To: netdev@vger.kernel.org > Cc: Richard Cochran <richardcochran@gmail.com>; Keller, Jacob E > <jacob.e.keller@intel.com>; Miroslav Lichvar <mlichvar@redhat.com>; Kirsher, > Jeffrey T <jeffrey.t.kirsher@intel.com> > Subject: [PATCH net-next 7/8] ixgbe: extend PTP gettime function to read system > clock > > -static int ixgbe_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) > +static int ixgbe_ptp_gettimex(struct ptp_clock_info *ptp, > + struct timespec64 *ts, > + struct ptp_system_timestamp *sts) > { > struct ixgbe_adapter *adapter = > container_of(ptp, struct ixgbe_adapter, ptp_caps); > + struct ixgbe_hw *hw = &adapter->hw; > unsigned long flags; > - u64 ns; > + u64 ns, stamp; > > spin_lock_irqsave(&adapter->tmreg_lock, flags); > - ns = timecounter_read(&adapter->hw_tc); > + > + switch (adapter->hw.mac.type) { > + case ixgbe_mac_X550: > + case ixgbe_mac_X550EM_x: > + case ixgbe_mac_x550em_a: > + /* Upper 32 bits represent billions of cycles, lower 32 bits > + * represent cycles. However, we use timespec64_to_ns for the > + * correct math even though the units haven't been corrected > + * yet. > + */ > + ptp_read_system_prets(sts); > + IXGBE_READ_REG(hw, IXGBE_SYSTIMR); > + ptp_read_system_postts(sts); > + ts->tv_nsec = IXGBE_READ_REG(hw, IXGBE_SYSTIML); > + ts->tv_sec = IXGBE_READ_REG(hw, IXGBE_SYSTIMH); > + stamp = timespec64_to_ns(ts); > + break; > + default: > + ptp_read_system_prets(sts); > + stamp = IXGBE_READ_REG(hw, IXGBE_SYSTIML); > + ptp_read_system_postts(sts); > + stamp |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32; > + break; > + } > + > + ns = timecounter_cyc2time(&adapter->hw_tc, stamp); > + At first, I was confused by this entire block of code, but then realized that we can't update the timecounter_read method, so we instead have to break this out so that our calls to ptp_read_system_prets() and ptp_read_system_postts() can be added between the register reads. Ok, that makes sense. > spin_unlock_irqrestore(&adapter->tmreg_lock, flags); > > *ts = ns_to_timespec64(ns); > @@ -567,10 +597,14 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter > *adapter) > { > bool timeout = time_is_before_jiffies(adapter->last_overflow_check + > IXGBE_OVERFLOW_PERIOD); > - struct timespec64 ts; > + unsigned long flags; > > if (timeout) { > - ixgbe_ptp_gettime(&adapter->ptp_caps, &ts); > + /* Update the timecounter */ > + spin_lock_irqsave(&adapter->tmreg_lock, flags); > + timecounter_read(&adapter->hw_tc); > + spin_unlock_irqrestore(&adapter->tmreg_lock, flags); > + This also explains this change where we now have to update the timecounter during the overflow check. Ok, this makes sense to me. Thanks, Jake
On Fri, 2018-11-09 at 11:14 +0100, Miroslav Lichvar wrote: > This adds support for the PTP_SYS_OFFSET_EXTENDED ioctl. > > Cc: Richard Cochran <richardcochran@gmail.com> > Cc: Jacob Keller <jacob.e.keller@intel.com> > Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com> > Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com> > --- > drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 54 ++++++++++++++++---- > 1 file changed, 44 insertions(+), 10 deletions(-) Acked-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index b3e0d8bb5cbd..d81a50dc9535 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -443,22 +443,52 @@ static int ixgbe_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) } /** - * ixgbe_ptp_gettime + * ixgbe_ptp_gettimex * @ptp: the ptp clock structure - * @ts: timespec structure to hold the current time value + * @ts: timespec to hold the PHC timestamp + * @sts: structure to hold the system time before and after reading the PHC * * read the timecounter and return the correct value on ns, * after converting it into a struct timespec. */ -static int ixgbe_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) +static int ixgbe_ptp_gettimex(struct ptp_clock_info *ptp, + struct timespec64 *ts, + struct ptp_system_timestamp *sts) { struct ixgbe_adapter *adapter = container_of(ptp, struct ixgbe_adapter, ptp_caps); + struct ixgbe_hw *hw = &adapter->hw; unsigned long flags; - u64 ns; + u64 ns, stamp; spin_lock_irqsave(&adapter->tmreg_lock, flags); - ns = timecounter_read(&adapter->hw_tc); + + switch (adapter->hw.mac.type) { + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: + /* Upper 32 bits represent billions of cycles, lower 32 bits + * represent cycles. However, we use timespec64_to_ns for the + * correct math even though the units haven't been corrected + * yet. + */ + ptp_read_system_prets(sts); + IXGBE_READ_REG(hw, IXGBE_SYSTIMR); + ptp_read_system_postts(sts); + ts->tv_nsec = IXGBE_READ_REG(hw, IXGBE_SYSTIML); + ts->tv_sec = IXGBE_READ_REG(hw, IXGBE_SYSTIMH); + stamp = timespec64_to_ns(ts); + break; + default: + ptp_read_system_prets(sts); + stamp = IXGBE_READ_REG(hw, IXGBE_SYSTIML); + ptp_read_system_postts(sts); + stamp |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32; + break; + } + + ns = timecounter_cyc2time(&adapter->hw_tc, stamp); + spin_unlock_irqrestore(&adapter->tmreg_lock, flags); *ts = ns_to_timespec64(ns); @@ -567,10 +597,14 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter) { bool timeout = time_is_before_jiffies(adapter->last_overflow_check + IXGBE_OVERFLOW_PERIOD); - struct timespec64 ts; + unsigned long flags; if (timeout) { - ixgbe_ptp_gettime(&adapter->ptp_caps, &ts); + /* Update the timecounter */ + spin_lock_irqsave(&adapter->tmreg_lock, flags); + timecounter_read(&adapter->hw_tc); + spin_unlock_irqrestore(&adapter->tmreg_lock, flags); + adapter->last_overflow_check = jiffies; } } @@ -1216,7 +1250,7 @@ static long ixgbe_ptp_create_clock(struct ixgbe_adapter *adapter) adapter->ptp_caps.pps = 1; adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq_82599; adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; - adapter->ptp_caps.gettime64 = ixgbe_ptp_gettime; + adapter->ptp_caps.gettimex64 = ixgbe_ptp_gettimex; adapter->ptp_caps.settime64 = ixgbe_ptp_settime; adapter->ptp_caps.enable = ixgbe_ptp_feature_enable; adapter->ptp_setup_sdp = ixgbe_ptp_setup_sdp_x540; @@ -1233,7 +1267,7 @@ static long ixgbe_ptp_create_clock(struct ixgbe_adapter *adapter) adapter->ptp_caps.pps = 0; adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq_82599; adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; - adapter->ptp_caps.gettime64 = ixgbe_ptp_gettime; + adapter->ptp_caps.gettimex64 = ixgbe_ptp_gettimex; adapter->ptp_caps.settime64 = ixgbe_ptp_settime; adapter->ptp_caps.enable = ixgbe_ptp_feature_enable; break; @@ -1249,7 +1283,7 @@ static long ixgbe_ptp_create_clock(struct ixgbe_adapter *adapter) adapter->ptp_caps.pps = 0; adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq_X550; adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; - adapter->ptp_caps.gettime64 = ixgbe_ptp_gettime; + adapter->ptp_caps.gettimex64 = ixgbe_ptp_gettimex; adapter->ptp_caps.settime64 = ixgbe_ptp_settime; adapter->ptp_caps.enable = ixgbe_ptp_feature_enable; adapter->ptp_setup_sdp = NULL;
This adds support for the PTP_SYS_OFFSET_EXTENDED ioctl. Cc: Richard Cochran <richardcochran@gmail.com> Cc: Jacob Keller <jacob.e.keller@intel.com> Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com> --- drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 54 ++++++++++++++++---- 1 file changed, 44 insertions(+), 10 deletions(-)