From: Jacob Keller Date: Fri, 1 May 2026 06:37:21 +0000 (-0700) Subject: i40e: only timestamp PTP event packets X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b71fcc5c0bb3347a7441393d6f3657b711efb968;p=thirdparty%2Flinux.git i40e: only timestamp PTP event packets The i40e_ptp_set_timestamp_mode() function is responsible for configuring hardware timestamping. When programming receive timestamping, the logic must determine how to configure the PRTTSYN_CTL1 register for receive timestamping. The i40e hardware does not support timestamping all frames. Instead, timestamps are captured into one of the four PRTTSYN_RXTIME registers. Currently, the driver configures hardware to timestamp all V2 packets on ports 319 and 320, including all message types. This timestamps significantly more packets than is actually requested by the HWTSTAMP_FILTER_PTP_V2_EVENT filter type. The documentation for HWTSTAMP_FILTER_PTP_V2_EVENT indicates that it should timestamp PTP v2 messages on any layer, including any kind of event packets. Timestamping other packets is acceptable, but not required by the filter. Doing so wastes valuable slots in the Rx timestamp registers. For most applications this doesn't cause a problem. However, for extremely high rates of messages, it becomes possible that one of the critical event packets is not timestamped. The PTP protocol only requires timestamps for event messages on port 319, but hardware is timestamping on both 319 and 320, and timestamping message types which do not need a timestamp value. The i40e hardware actually has a more strict filtering option. First, only timestamp layer 4 messages on port 319 instead of both 319 and 320. Second, note that hardware has a specific mode to timestamp only event packets (those with message type < 8). Update the configuration to use the strict mode that only timestamps event messages, switching the TSYNTYPE field from 10b to 11b which limits the timestamping only to eventpackets with a Message Type of < 8. Note that the X700 series datasheet seems to indicate that the V2MSESTYPE field is no longer relevant. However, we only tested and validated with leaving the V2MESSTYPE field set to 0xF for the "wildcard" behavior it documents. This might not be required but it in that case setting it appears harmless, so leave it as is. This avoids wasting the valuable Rx timestamp register slots on non-event frames, and may reduce faults when operating under high event rates. Reviewed-by: Aleksandr Loktionov Tested-by: Rinitha S Signed-off-by: Jacob Keller Link: https://patch.msgid.link/20260430-jk-iwl-net-next-2026-04-30-v1-10-6f27ae1cd073@intel.com Signed-off-by: Jakub Kicinski --- diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index 404a716db8da7..7bcea7d9720ff 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -24,9 +24,6 @@ #define I40E_PTP_1GB_INCVAL_MULT 20 #define I40E_ISGN 0x80000000 -#define I40E_PRTTSYN_CTL1_TSYNTYPE_V1 BIT(I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT) -#define I40E_PRTTSYN_CTL1_TSYNTYPE_V2 (2 << \ - I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT) #define I40E_SUBDEV_ID_25G_PTP_PIN 0xB enum i40e_ptp_pin { @@ -1219,7 +1216,7 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf, pf->ptp_rx = true; tsyntype = I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK | I40E_PRTTSYN_CTL1_TSYNTYPE_V1 | - I40E_PRTTSYN_CTL1_UDP_ENA_MASK; + I40E_PRTTSYN_CTL1_UDP_ENA_319; config->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; break; case HWTSTAMP_FILTER_PTP_V2_EVENT: @@ -1236,9 +1233,9 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf, case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: pf->ptp_rx = true; tsyntype = I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK | - I40E_PRTTSYN_CTL1_TSYNTYPE_V2; + I40E_PRTTSYN_CTL1_TSYNTYPE_V2_EVENT; if (test_bit(I40E_HW_CAP_PTP_L4, pf->hw.caps)) { - tsyntype |= I40E_PRTTSYN_CTL1_UDP_ENA_MASK; + tsyntype |= I40E_PRTTSYN_CTL1_UDP_ENA_319; config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; } else { config->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; diff --git a/drivers/net/ethernet/intel/i40e/i40e_register.h b/drivers/net/ethernet/intel/i40e/i40e_register.h index 432afbb642013..d426d83e02144 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_register.h +++ b/drivers/net/ethernet/intel/i40e/i40e_register.h @@ -788,8 +788,18 @@ #define I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT 16 #define I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT) #define I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT 24 +#define I40E_PRTTSYN_CTL1_TSYNTYPE_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT) +/* Timestamp UDP v1 packets */ +#define I40E_PRTTSYN_CTL1_TSYNTYPE_V1 \ + FIELD_PREP(I40E_PRTTSYN_CTL1_TSYNTYPE_MASK, 1) +/* Timestamp L2 and UDP v2 packets with message type < 8 */ +#define I40E_PRTTSYN_CTL1_TSYNTYPE_V2_EVENT \ + FIELD_PREP(I40E_PRTTSYN_CTL1_TSYNTYPE_MASK, 3) #define I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT 26 #define I40E_PRTTSYN_CTL1_UDP_ENA_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT) +/* Timestamp UDP packets on port 319 */ +#define I40E_PRTTSYN_CTL1_UDP_ENA_319 \ + FIELD_PREP(I40E_PRTTSYN_CTL1_UDP_ENA_MASK, 1) #define I40E_PRTTSYN_CTL1_TSYNENA_SHIFT 31 #define I40E_PRTTSYN_CTL1_TSYNENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL1_TSYNENA_SHIFT) #define I40E_PRTTSYN_INC_H 0x001E4060 /* Reset: GLOBR */