[Intel-wired-lan] [PATCH next-queue v5 4/4] igc: Add support for PTP getcrosststamp()

Paul Menzel pmenzel at molgen.mpg.de
Sat Jun 5 06:36:44 UTC 2021


Dear Vinicius,


Am 05.06.21 um 02:23 schrieb Vinicius Costa Gomes:
> i225 has support for PCIe PTM, which allows us to implement support
> for the PTP_SYS_OFFSET_PRECISE ioctl(), implemented in the driver via
> the getcrosststamp() function.

Maybe:

i225 supports PCIe Precision Time Measurement (PTM), allowing us to 
support the PTP_SYS_OFFSET_PRECISE ioctl() in the driver via the 
getcrosststamp() function.

> The easiest way to expose the PTM registers would be to configure the PTM
> dialogs to run periodically, but the PTP_SYS_OFFSET_PRECISE ioctl()
> semantics are more aligned to using a kind of "one-shot" way of retrieving
> the PTM timestamps. But this causes a bit more code to be written: the

Maybe: But this results in more code:

> trigger registers for the PTM dialogs are not cleared automatically.
> 
> i225 can be configured to send "fake" packets with the PTM
> information, adding support for handling these types of packets is
> left for the future.
> 
> PTM improves the accuracy of time synchronization, for example, using
> phc2sys. Before:
> 
> phc2sys[341.511]: CLOCK_REALTIME phc offset       289 s2 freq    +961 delay   2963
> phc2sys[342.511]: CLOCK_REALTIME phc offset      -984 s2 freq    -225 delay   3517
> phc2sys[343.511]: CLOCK_REALTIME phc offset       427 s2 freq    +891 delay   2312
> phc2sys[344.511]: CLOCK_REALTIME phc offset       104 s2 freq    +696 delay   2575
> phc2sys[345.511]: CLOCK_REALTIME phc offset       149 s2 freq    +772 delay   2388
> phc2sys[346.511]: CLOCK_REALTIME phc offset        33 s2 freq    +701 delay   2359
> phc2sys[347.511]: CLOCK_REALTIME phc offset      -216 s2 freq    +462 delay   2706
> phc2sys[348.512]: CLOCK_REALTIME phc offset       140 s2 freq    +753 delay   2300
> phc2sys[349.512]: CLOCK_REALTIME phc offset       -14 s2 freq    +641 delay   2385
> phc2sys[350.512]: CLOCK_REALTIME phc offset      1048 s2 freq   +1699 delay   4303
> phc2sys[351.512]: CLOCK_REALTIME phc offset     -1296 s2 freq    -331 delay   2846
> phc2sys[352.512]: CLOCK_REALTIME phc offset      -912 s2 freq    -336 delay   4006
> phc2sys[353.512]: CLOCK_REALTIME phc offset       880 s2 freq   +1183 delay   2338
> phc2sys[354.512]: CLOCK_REALTIME phc offset       358 s2 freq    +925 delay   2348
> phc2sys[355.512]: CLOCK_REALTIME phc offset      -211 s2 freq    +463 delay   2941
> phc2sys[356.512]: CLOCK_REALTIME phc offset       234 s2 freq    +845 delay   2519
> phc2sys[357.512]: CLOCK_REALTIME phc offset        45 s2 freq    +726 delay   2357
> phc2sys[358.512]: CLOCK_REALTIME phc offset      -262 s2 freq    +433 delay   2821
> phc2sys[359.512]: CLOCK_REALTIME phc offset      -424 s2 freq    +192 delay   3579
> phc2sys[360.513]: CLOCK_REALTIME phc offset       134 s2 freq    +623 delay   3269
> phc2sys[361.513]: CLOCK_REALTIME phc offset      -213 s2 freq    +316 delay   3999
> phc2sys[362.513]: CLOCK_REALTIME phc offset      1023 s2 freq   +1488 delay   2614
> phc2sys[363.513]: CLOCK_REALTIME phc offset        57 s2 freq    +829 delay   2332
> phc2sys[364.513]: CLOCK_REALTIME phc offset      -126 s2 freq    +663 delay   2315
> phc2sys[365.513]: CLOCK_REALTIME phc offset       -85 s2 freq    +666 delay   2449
> phc2sys[366.513]: CLOCK_REALTIME phc offset      -193 s2 freq    +533 delay   2336
> phc2sys[367.513]: CLOCK_REALTIME phc offset      -645 s2 freq     +23 delay   3870
> phc2sys[368.513]: CLOCK_REALTIME phc offset       483 s2 freq    +957 delay   2342
> phc2sys[369.513]: CLOCK_REALTIME phc offset      -166 s2 freq    +453 delay   3025
> phc2sys[370.513]: CLOCK_REALTIME phc offset       327 s2 freq    +896 delay   2250
> 
> After:
> 
> phc2sys[617.838]: CLOCK_REALTIME phc offset       -25 s2 freq    +309 delay      0
> phc2sys[618.838]: CLOCK_REALTIME phc offset       -43 s2 freq    +284 delay      0
> phc2sys[619.838]: CLOCK_REALTIME phc offset       -12 s2 freq    +302 delay      0
> phc2sys[620.838]: CLOCK_REALTIME phc offset        -2 s2 freq    +308 delay      0
> phc2sys[621.838]: CLOCK_REALTIME phc offset        30 s2 freq    +340 delay      0
> phc2sys[622.838]: CLOCK_REALTIME phc offset        14 s2 freq    +333 delay      0
> phc2sys[623.839]: CLOCK_REALTIME phc offset        -3 s2 freq    +320 delay      0
> phc2sys[624.839]: CLOCK_REALTIME phc offset         9 s2 freq    +331 delay      0
> phc2sys[625.839]: CLOCK_REALTIME phc offset        -1 s2 freq    +324 delay      0
> phc2sys[626.839]: CLOCK_REALTIME phc offset        -6 s2 freq    +318 delay      0
> phc2sys[627.839]: CLOCK_REALTIME phc offset       -10 s2 freq    +313 delay      0
> phc2sys[628.839]: CLOCK_REALTIME phc offset         7 s2 freq    +327 delay      0
> phc2sys[629.839]: CLOCK_REALTIME phc offset         8 s2 freq    +330 delay      0
> phc2sys[630.840]: CLOCK_REALTIME phc offset       -24 s2 freq    +300 delay      0
> phc2sys[631.840]: CLOCK_REALTIME phc offset       -49 s2 freq    +268 delay      0
> phc2sys[632.840]: CLOCK_REALTIME phc offset         6 s2 freq    +308 delay      0
> phc2sys[633.840]: CLOCK_REALTIME phc offset        25 s2 freq    +329 delay      0
> phc2sys[634.840]: CLOCK_REALTIME phc offset         5 s2 freq    +316 delay      0
> phc2sys[635.840]: CLOCK_REALTIME phc offset        10 s2 freq    +323 delay      0
> phc2sys[636.840]: CLOCK_REALTIME phc offset       -13 s2 freq    +303 delay      0
> phc2sys[637.841]: CLOCK_REALTIME phc offset         4 s2 freq    +316 delay      0
> phc2sys[638.841]: CLOCK_REALTIME phc offset        16 s2 freq    +329 delay      0
> phc2sys[639.841]: CLOCK_REALTIME phc offset        31 s2 freq    +349 delay      0
> phc2sys[640.841]: CLOCK_REALTIME phc offset       -21 s2 freq    +306 delay      0
> phc2sys[641.841]: CLOCK_REALTIME phc offset       -14 s2 freq    +307 delay      0
> phc2sys[642.841]: CLOCK_REALTIME phc offset       -24 s2 freq    +293 delay      0
> phc2sys[643.841]: CLOCK_REALTIME phc offset        -6 s2 freq    +304 delay      0
> phc2sys[644.842]: CLOCK_REALTIME phc offset        12 s2 freq    +320 delay      0
> phc2sys[645.842]: CLOCK_REALTIME phc offset        12 s2 freq    +323 delay      0
> phc2sys[646.842]: CLOCK_REALTIME phc offset       -12 s2 freq    +303 delay      0

Please (additionally) summarize the findings by stating the min/max/avg?

> One possible explanation is that when PTM is not enabled, and there's a lot
> of traffic in the PCIe fabric, some register reads will take more time than
> the others (see the variation in the delay values "before").

Can you please document the datasheet name and revision used to 
implement this?

> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes at intel.com>
> ---
>   drivers/net/ethernet/intel/igc/igc.h         |   1 +
>   drivers/net/ethernet/intel/igc/igc_defines.h |  31 ++++
>   drivers/net/ethernet/intel/igc/igc_ptp.c     | 182 +++++++++++++++++++
>   drivers/net/ethernet/intel/igc/igc_regs.h    |  23 +++
>   4 files changed, 237 insertions(+)
> 
> diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
> index 5901ed9fb545..36ef4ba10e2c 100644
> --- a/drivers/net/ethernet/intel/igc/igc.h
> +++ b/drivers/net/ethernet/intel/igc/igc.h
> @@ -225,6 +225,7 @@ struct igc_adapter {
>   	struct timecounter tc;
>   	struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */
>   	ktime_t ptp_reset_start; /* Reset time in clock mono */
> +	struct system_time_snapshot snapshot;
>   
>   	char fw_version[32];
>   
> diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
> index 71fe5b5ad2ed..0432ba26192e 100644
> --- a/drivers/net/ethernet/intel/igc/igc_defines.h
> +++ b/drivers/net/ethernet/intel/igc/igc_defines.h
> @@ -481,6 +481,37 @@
>   #define IGC_RXCSUM_CRCOFL	0x00000800   /* CRC32 offload enable */
>   #define IGC_RXCSUM_PCSD		0x00002000   /* packet checksum disabled */
>   
> +/* PCIe PTM Control */
> +#define IGC_PTM_CTRL_START_NOW	BIT(29) /* Start PTM Now */
> +#define IGC_PTM_CTRL_EN		BIT(30) /* Enable PTM */
> +#define IGC_PTM_CTRL_TRIG	BIT(31) /* PTM Cycle trigger */
> +#define IGC_PTM_CTRL_SHRT_CYC(usec)	(((usec) & 0x2f) << 2)
> +#define IGC_PTM_CTRL_PTM_TO(usec)	(((usec) & 0xff) << 8)
> +
> +#define IGC_PTM_SHORT_CYC_DEFAULT	10  /* Default Short/interrupted cycle interval */
> +#define IGC_PTM_CYC_TIME_DEFAULT	5   /* Default PTM cycle time */
> +#define IGC_PTM_TIMEOUT_DEFAULT		255 /* Default timeout for PTM errors */
> +
> +/* PCIe Digital Delay */
> +#define IGC_PCIE_DIG_DELAY_DEFAULT	0x01440000
> +
> +/* PCIe PHY Delay */
> +#define IGC_PCIE_PHY_DELAY_DEFAULT	0x40900000
> +
> +#define IGC_TIMADJ_ADJUST_METH		0x40000000
> +
> +/* PCIe PTM Status */
> +#define IGC_PTM_STAT_VALID		BIT(0) /* PTM Status */
> +#define IGC_PTM_STAT_RET_ERR		BIT(1) /* Root port timeout */
> +#define IGC_PTM_STAT_BAD_PTM_RES	BIT(2) /* PTM Response msg instead of PTM Response Data */
> +#define IGC_PTM_STAT_T4M1_OVFL		BIT(3) /* T4 minus T1 overflow */
> +#define IGC_PTM_STAT_ADJUST_1ST		BIT(4) /* 1588 timer adjusted during 1st PTM cycle */
> +#define IGC_PTM_STAT_ADJUST_CYC		BIT(5) /* 1588 timer adjusted during non-1st PTM cycle */
> +
> +/* PCIe PTM Cycle Control */
> +#define IGC_PTM_CYCLE_CTRL_CYC_TIME(msec)	((msec) & 0x3ff) /* PTM Cycle Time (msec) */
> +#define IGC_PTM_CYCLE_CTRL_AUTO_CYC_EN		BIT(31) /* PTM Cycle Control */
> +
>   /* GPY211 - I225 defines */
>   #define GPY_MMD_MASK		0xFFFF0000
>   #define GPY_MMD_SHIFT		16
> diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c
> index 69617d2c1be2..1683b2f7cc8c 100644
> --- a/drivers/net/ethernet/intel/igc/igc_ptp.c
> +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c
> @@ -9,6 +9,8 @@
>   #include <linux/ptp_classify.h>
>   #include <linux/clocksource.h>
>   #include <linux/ktime.h>
> +#include <linux/delay.h>
> +#include <linux/iopoll.h>
>   
>   #define INCVALUE_MASK		0x7fffffff
>   #define ISGN			0x80000000
> @@ -16,6 +18,9 @@
>   #define IGC_SYSTIM_OVERFLOW_PERIOD	(HZ * 60 * 9)
>   #define IGC_PTP_TX_TIMEOUT		(HZ * 15)
>   
> +#define IGC_PTM_STAT_SLEEP		2
> +#define IGC_PTM_STAT_TIMEOUT		100
> +
>   /* SYSTIM read access for I225 */
>   void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts)
>   {
> @@ -752,6 +757,150 @@ int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr)
>   		-EFAULT : 0;
>   }
>   
> +/* Support for cross timestamping via PCIe PTM is only supported if
> + * two conditions are met:

Maybe: The two conditions below must be met for cross timestamping via 
PCIe PTM

> + *
> + * 1. We have an way to convert the timestamps in the PTM messages

s/an way/a way/

> + *    to something related to the system clocks (right now, only
> + *    X86 systems with support for the Always Running Timer allow that);
> + *
> + * 2. We have PTM enabled in the path from the device to the PCIe root port.
> + */
> +static bool igc_is_crosststamp_supported(struct igc_adapter *adapter)
> +{
> +#if IS_ENABLED(CONFIG_X86_TSC)
> +	return pcie_ptm_enabled(adapter->pdev);
> +#endif
> +	return false;

I’d also add the preprocessor else branch as below (despite the compiler 
opitimzing it away) for readability. Also, I’d do the check in C and not 
the preprocessor.

     return IS_ENABLED(CONFIG_X86_TSC) ? pcie_ptm_enabled(adapter->pdev) 
: false;

> +}
> +
> +static struct system_counterval_t igc_device_tstamp_to_system(u64 tstamp)
> +{
> +#if IS_ENABLED(CONFIG_X86_TSC)
> +	return convert_art_ns_to_tsc(tstamp);
> +#else
> +	return (struct system_counterval_t) { };
> +#endif
> +}
> +
> +static void igc_ptm_log_error(struct igc_adapter *adapter, u32 ptm_stat)
> +{
> +	struct net_device *netdev = adapter->netdev;
> +
> +	switch (ptm_stat) {
> +	case IGC_PTM_STAT_RET_ERR:
> +		netdev_err(netdev, "PTM Error: Root port timeout\n");
> +		break;
> +	case IGC_PTM_STAT_BAD_PTM_RES:
> +		netdev_err(netdev, "PTM Error: Bad response, PTM Response Data expected\n");
> +		break;
> +	case IGC_PTM_STAT_T4M1_OVFL:
> +		netdev_err(netdev, "PTM Error: T4 minus T1 overflow\n");
> +		break;
> +	case IGC_PTM_STAT_ADJUST_1ST:
> +		netdev_err(netdev, "PTM Error: 1588 timer adjusted during first PTM cycle\n");
> +		break;
> +	case IGC_PTM_STAT_ADJUST_CYC:
> +		netdev_err(netdev, "PTM Error: 1588 timer adjusted during non-first PTM cycle\n");
> +		break;
> +	default:
> +		netdev_err(netdev, "PTM Error: Unknown error (%#x)\n", ptm_stat);
> +		break;
> +	}
> +}
> +
> +static int igc_phc_get_syncdevicetime(ktime_t *device,
> +				      struct system_counterval_t *system,
> +				      void *ctx)
> +{
> +	struct igc_adapter *adapter = ctx;
> +	struct igc_hw *hw = &adapter->hw;
> +	u32 stat, t2_curr_h, t2_curr_l, ctrl;
> +	u32 t4mt1_prev, t3mt2_prev, delay;
> +	ktime_t t1, t2_curr;
> +	int err;
> +
> +	/* Get a snapshot of system clocks to use as historic value. */
> +	ktime_get_snapshot(&adapter->snapshot);
> +
> +	do {
> +		/* Doing this in a loop because in the event of a
> +		 * badly timed (ha!) system clock adjustment, we may
> +		 * get PTM Errors from the PCI root, but these errors

PTM errors

> +		 * are transitory. Repeating the process returns valid
> +		 * data eventually.
> +		 */
> +
> +		/* To "manually" start the PTM cycle we need to clear and
> +		 * then set again the TRIG bit.
> +		 */
> +		ctrl = rd32(IGC_PTM_CTRL);
> +		ctrl &= ~IGC_PTM_CTRL_TRIG;
> +		wr32(IGC_PTM_CTRL, ctrl);
> +		ctrl |= IGC_PTM_CTRL_TRIG;
> +		wr32(IGC_PTM_CTRL, ctrl);
> +
> +		/* The cycle only starts "for real" when software notifies
> +		 * that it has read the registers, this is done by setting
> +		 * VALID bit.
> +		 */
> +		wr32(IGC_PTM_STAT, IGC_PTM_STAT_VALID);
> +
> +		err = readx_poll_timeout(rd32, IGC_PTM_STAT, stat,
> +					 stat, IGC_PTM_STAT_SLEEP,
> +					 IGC_PTM_STAT_TIMEOUT);
> +		if (err < 0)
> +			return err;

Should this be logged?

> +
> +		if ((stat & IGC_PTM_STAT_VALID) == IGC_PTM_STAT_VALID)
> +			break;
> +
> +		if (stat & ~IGC_PTM_STAT_VALID) {
> +			/* An error occurred, log it. */
> +			igc_ptm_log_error(adapter, stat);
> +			/* The STAT register is write-1-to-clear (W1C),
> +			 * so write the previous error status to clear it.
> +			 */
> +			wr32(IGC_PTM_STAT, stat);
> +			continue;
> +		}
> +	} while (true);

I personally prefer to write at least one condition in the loop condition.

> +
> +	t1 = ktime_set(rd32(IGC_PTM_T1_TIM0_H),
> +		       rd32(IGC_PTM_T1_TIM0_L));

Why not put it into one line?

> +
> +	t2_curr_l = rd32(IGC_PTM_CURR_T2_L);
> +	t2_curr_h = rd32(IGC_PTM_CURR_T2_H);
> +
> +	/* FIXME: When the register that tells the endianness of the
> +	 * PTM registers are implemented, check them here and add the
> +	 * appropriate conversion.
> +	 */
> +	t2_curr_h = swab32(t2_curr_h);
> +
> +	t2_curr = ((s64)t2_curr_h << 32 | t2_curr_l);
> +
> +	t4mt1_prev = rd32(IGC_PTM_PREV_T4M1);
> +	t3mt2_prev = rd32(IGC_PTM_PREV_T3M2);
> +
> +	delay = (t4mt1_prev - t3mt2_prev) / 2;
> +
> +	*device = t1 + delay;
> +	*system = igc_device_tstamp_to_system(t2_curr);
> +
> +	return 0;
> +}
> +
> +static int igc_ptp_getcrosststamp(struct ptp_clock_info *ptp,
> +				  struct system_device_crosststamp *cts)
> +{
> +	struct igc_adapter *adapter = container_of(ptp, struct igc_adapter,
> +						   ptp_caps);
> +
> +	return get_device_system_crosststamp(igc_phc_get_syncdevicetime,
> +					     adapter, &adapter->snapshot, cts);
> +}
> +
>   /**
>    * igc_ptp_init - Initialize PTP functionality
>    * @adapter: Board private structure
> @@ -788,6 +937,11 @@ void igc_ptp_init(struct igc_adapter *adapter)
>   		adapter->ptp_caps.n_per_out = IGC_N_PEROUT;
>   		adapter->ptp_caps.n_pins = IGC_N_SDP;
>   		adapter->ptp_caps.verify = igc_ptp_verify_pin;
> +
> +		if (!igc_is_crosststamp_supported(adapter))
> +			break;
> +
> +		adapter->ptp_caps.getcrosststamp = igc_ptp_getcrosststamp;
>   		break;
>   	default:
>   		adapter->ptp_clock = NULL;
> @@ -878,7 +1032,9 @@ void igc_ptp_stop(struct igc_adapter *adapter)
>   void igc_ptp_reset(struct igc_adapter *adapter)
>   {
>   	struct igc_hw *hw = &adapter->hw;
> +	u32 cycle_ctrl, ctrl;
>   	unsigned long flags;
> +	u32 timadj;
>   
>   	/* reset the tstamp_config */
>   	igc_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config);
> @@ -887,12 +1043,38 @@ void igc_ptp_reset(struct igc_adapter *adapter)
>   
>   	switch (adapter->hw.mac.type) {
>   	case igc_i225:
> +		timadj = rd32(IGC_TIMADJ);
> +		timadj |= IGC_TIMADJ_ADJUST_METH;
> +		wr32(IGC_TIMADJ, timadj);
> +
>   		wr32(IGC_TSAUXC, 0x0);
>   		wr32(IGC_TSSDP, 0x0);
>   		wr32(IGC_TSIM,
>   		     IGC_TSICR_INTERRUPTS |
>   		     (adapter->pps_sys_wrap_on ? IGC_TSICR_SYS_WRAP : 0));
>   		wr32(IGC_IMS, IGC_IMS_TS);
> +
> +		if (!igc_is_crosststamp_supported(adapter))
> +			break;
> +
> +		wr32(IGC_PCIE_DIG_DELAY, IGC_PCIE_DIG_DELAY_DEFAULT);
> +		wr32(IGC_PCIE_PHY_DELAY, IGC_PCIE_PHY_DELAY_DEFAULT);
> +
> +		cycle_ctrl = IGC_PTM_CYCLE_CTRL_CYC_TIME(IGC_PTM_CYC_TIME_DEFAULT);
> +
> +		wr32(IGC_PTM_CYCLE_CTRL, cycle_ctrl);
> +
> +		ctrl = IGC_PTM_CTRL_EN |
> +			IGC_PTM_CTRL_START_NOW |
> +			IGC_PTM_CTRL_SHRT_CYC(IGC_PTM_SHORT_CYC_DEFAULT) |
> +			IGC_PTM_CTRL_PTM_TO(IGC_PTM_TIMEOUT_DEFAULT) |
> +			IGC_PTM_CTRL_TRIG;
> +
> +		wr32(IGC_PTM_CTRL, ctrl);
> +
> +		/* Force the first cycle to run. */
> +		wr32(IGC_PTM_STAT, IGC_PTM_STAT_VALID);
> +
>   		break;
>   	default:
>   		/* No work to do. */
> diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h
> index 0f82990567d9..4499a6f7c577 100644
> --- a/drivers/net/ethernet/intel/igc/igc_regs.h
> +++ b/drivers/net/ethernet/intel/igc/igc_regs.h
> @@ -229,6 +229,29 @@
>   #define IGC_TXSTMPL	0x0B618  /* Tx timestamp value Low - RO */
>   #define IGC_TXSTMPH	0x0B61C  /* Tx timestamp value High - RO */
>   
> +#define IGC_TIMADJ	0x0B60C  /* Time Adjustment Offset Register */
> +
> +/* PCIe Registers */
> +#define IGC_PTM_CTRL		0x12540  /* PTM Control */
> +#define IGC_PTM_STAT		0x12544  /* PTM Status */
> +#define IGC_PTM_CYCLE_CTRL	0x1254C  /* PTM Cycle Control */
> +
> +/* PTM Time registers */
> +#define IGC_PTM_T1_TIM0_L	0x12558  /* T1 on Timer 0 Low */
> +#define IGC_PTM_T1_TIM0_H	0x1255C  /* T1 on Timer 0 High */
> +
> +#define IGC_PTM_CURR_T2_L	0x1258C  /* Current T2 Low */
> +#define IGC_PTM_CURR_T2_H	0x12590  /* Current T2 High */
> +#define IGC_PTM_PREV_T2_L	0x12584  /* Previous T2 Low */
> +#define IGC_PTM_PREV_T2_H	0x12588  /* Previous T2 High */
> +#define IGC_PTM_PREV_T4M1	0x12578  /* T4 Minus T1 on previous PTM Cycle */
> +#define IGC_PTM_CURR_T4M1	0x1257C  /* T4 Minus T1 on this PTM Cycle */
> +#define IGC_PTM_PREV_T3M2	0x12580  /* T3 Minus T2 on previous PTM Cycle */
> +#define IGC_PTM_TDELAY		0x12594  /* PTM PCIe Link Delay */
> +
> +#define IGC_PCIE_DIG_DELAY	0x12550  /* PCIe Digital Delay */
> +#define IGC_PCIE_PHY_DELAY	0x12554  /* PCIe PHY Delay */
> +
>   /* Management registers */
>   #define IGC_MANC	0x05820  /* Management Control - RW */
>   

How can the user find out, that PTP grecroosstamp() is used?


Kind regards,

Paul


More information about the Intel-wired-lan mailing list