netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/8] gve: Add Rx HW timestamping support
@ 2025-05-17  0:11 Harshitha Ramamurthy
  2025-05-17  0:11 ` [PATCH net-next v2 1/8] gve: Add device option for nic clock synchronization Harshitha Ramamurthy
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Harshitha Ramamurthy @ 2025-05-17  0:11 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, jeroendb, hramamurthy,
	andrew+netdev, willemb, ziweixiao, pkaligineedi, yyd, joshwash,
	shailend, linux, thostet, jfraker, richardcochran, jdamato,
	vadim.fedorenko, horms, linux-kernel

From: Ziwei Xiao <ziweixiao@google.com>

This patch series add the support of Rx HW timestamping, which sends
adminq commands periodically to the device for clock synchronization with
the nic.

Changes:
v2:
  - add initial PTP device support to utilize the ptp's aux_work to
    schedule sending adminq commands periodically (Jakub Kicinski,
    Vadim Fedorenko)
  - add adminq lock patch into this patch series instead of sending out
    to net since it's only needed to resolve the conflicts between the
    upcoming PTP aux_work and the queue creation/destruction adminq
    commands (Jakub Kicinski)
  - add the missing READ_ONCE (Joe Damato)

Harshitha Ramamurthy (1):
  gve: Add initial PTP device support

John Fraker (5):
  gve: Add device option for nic clock synchronization
  gve: Add adminq command to report nic timestamp
  gve: Add rx hardware timestamp expansion
  gve: Add support for SIOC[GS]HWTSTAMP IOCTLs
  gve: Advertise support for rx hardware timestamping

Kevin Yang (1):
  gve: Add support to query the nic clock

Ziwei Xiao (1):
  gve: Add adminq lock for queues creation and destruction

 drivers/net/ethernet/google/Kconfig           |   1 +
 drivers/net/ethernet/google/gve/Makefile      |   4 +-
 drivers/net/ethernet/google/gve/gve.h         |  29 ++++
 drivers/net/ethernet/google/gve/gve_adminq.c  |  98 +++++++++++--
 drivers/net/ethernet/google/gve/gve_adminq.h  |  26 ++++
 .../net/ethernet/google/gve/gve_desc_dqo.h    |   3 +-
 drivers/net/ethernet/google/gve/gve_ethtool.c |  23 ++-
 drivers/net/ethernet/google/gve/gve_main.c    |  47 +++++++
 drivers/net/ethernet/google/gve/gve_ptp.c     | 132 ++++++++++++++++++
 drivers/net/ethernet/google/gve/gve_rx_dqo.c  |  26 ++++
 10 files changed, 373 insertions(+), 16 deletions(-)
 create mode 100644 drivers/net/ethernet/google/gve/gve_ptp.c

-- 
2.49.0.1112.g889b7c5bd8-goog


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH net-next v2 1/8] gve: Add device option for nic clock synchronization
  2025-05-17  0:11 [PATCH net-next v2 0/8] gve: Add Rx HW timestamping support Harshitha Ramamurthy
@ 2025-05-17  0:11 ` Harshitha Ramamurthy
  2025-05-17  0:11 ` [PATCH net-next v2 2/8] gve: Add adminq command to report nic timestamp Harshitha Ramamurthy
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Harshitha Ramamurthy @ 2025-05-17  0:11 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, jeroendb, hramamurthy,
	andrew+netdev, willemb, ziweixiao, pkaligineedi, yyd, joshwash,
	shailend, linux, thostet, jfraker, richardcochran, jdamato,
	vadim.fedorenko, horms, linux-kernel, Jeff Rogers

From: John Fraker <jfraker@google.com>

Add the device option and negotiation with the device for clock
synchronization with the nic. This option is necessary before the driver
will advertise support for hardware timestamping or other related
features.

Signed-off-by: Jeff Rogers <jefrogers@google.com>
Signed-off-by: John Fraker <jfraker@google.com>
Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
---
 drivers/net/ethernet/google/gve/gve.h        |  3 ++
 drivers/net/ethernet/google/gve/gve_adminq.c | 31 +++++++++++++++++++-
 drivers/net/ethernet/google/gve/gve_adminq.h |  9 ++++++
 3 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index 2fab38c8ee78..e9b2c1394b1f 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -870,6 +870,9 @@ struct gve_priv {
 	u16 rss_lut_size;
 	bool cache_rss_config;
 	struct gve_rss_config rss_config;
+
+	/* True if the device supports reading the nic clock */
+	bool nic_timestamp_supported;
 };
 
 enum gve_service_task_flags_bit {
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c
index 3e8fc33cc11f..ae20d2f7e6e1 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.c
+++ b/drivers/net/ethernet/google/gve/gve_adminq.c
@@ -46,6 +46,7 @@ void gve_parse_device_option(struct gve_priv *priv,
 			     struct gve_device_option_buffer_sizes **dev_op_buffer_sizes,
 			     struct gve_device_option_flow_steering **dev_op_flow_steering,
 			     struct gve_device_option_rss_config **dev_op_rss_config,
+			     struct gve_device_option_nic_timestamp **dev_op_nic_timestamp,
 			     struct gve_device_option_modify_ring **dev_op_modify_ring)
 {
 	u32 req_feat_mask = be32_to_cpu(option->required_features_mask);
@@ -225,6 +226,23 @@ void gve_parse_device_option(struct gve_priv *priv,
 				 "RSS config");
 		*dev_op_rss_config = (void *)(option + 1);
 		break;
+	case GVE_DEV_OPT_ID_NIC_TIMESTAMP:
+		if (option_length < sizeof(**dev_op_nic_timestamp) ||
+		    req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_NIC_TIMESTAMP) {
+			dev_warn(&priv->pdev->dev, GVE_DEVICE_OPTION_ERROR_FMT,
+				 "Nic Timestamp",
+				 (int)sizeof(**dev_op_nic_timestamp),
+				 GVE_DEV_OPT_REQ_FEAT_MASK_NIC_TIMESTAMP,
+				 option_length, req_feat_mask);
+			break;
+		}
+
+		if (option_length > sizeof(**dev_op_nic_timestamp))
+			dev_warn(&priv->pdev->dev,
+				 GVE_DEVICE_OPTION_TOO_BIG_FMT,
+				 "Nic Timestamp");
+		*dev_op_nic_timestamp = (void *)(option + 1);
+		break;
 	default:
 		/* If we don't recognize the option just continue
 		 * without doing anything.
@@ -246,6 +264,7 @@ gve_process_device_options(struct gve_priv *priv,
 			   struct gve_device_option_buffer_sizes **dev_op_buffer_sizes,
 			   struct gve_device_option_flow_steering **dev_op_flow_steering,
 			   struct gve_device_option_rss_config **dev_op_rss_config,
+			   struct gve_device_option_nic_timestamp **dev_op_nic_timestamp,
 			   struct gve_device_option_modify_ring **dev_op_modify_ring)
 {
 	const int num_options = be16_to_cpu(descriptor->num_device_options);
@@ -269,6 +288,7 @@ gve_process_device_options(struct gve_priv *priv,
 					dev_op_dqo_rda, dev_op_jumbo_frames,
 					dev_op_dqo_qpl, dev_op_buffer_sizes,
 					dev_op_flow_steering, dev_op_rss_config,
+					dev_op_nic_timestamp,
 					dev_op_modify_ring);
 		dev_opt = next_opt;
 	}
@@ -904,6 +924,8 @@ static void gve_enable_supported_features(struct gve_priv *priv,
 					  *dev_op_flow_steering,
 					  const struct gve_device_option_rss_config
 					  *dev_op_rss_config,
+					  const struct gve_device_option_nic_timestamp
+					  *dev_op_nic_timestamp,
 					  const struct gve_device_option_modify_ring
 					  *dev_op_modify_ring)
 {
@@ -980,10 +1002,15 @@ static void gve_enable_supported_features(struct gve_priv *priv,
 			"RSS device option enabled with key size of %u, lut size of %u.\n",
 			priv->rss_key_size, priv->rss_lut_size);
 	}
+
+	if (dev_op_nic_timestamp &&
+	    (supported_features_mask & GVE_SUP_NIC_TIMESTAMP_MASK))
+		priv->nic_timestamp_supported = true;
 }
 
 int gve_adminq_describe_device(struct gve_priv *priv)
 {
+	struct gve_device_option_nic_timestamp *dev_op_nic_timestamp = NULL;
 	struct gve_device_option_flow_steering *dev_op_flow_steering = NULL;
 	struct gve_device_option_buffer_sizes *dev_op_buffer_sizes = NULL;
 	struct gve_device_option_jumbo_frames *dev_op_jumbo_frames = NULL;
@@ -1024,6 +1051,7 @@ int gve_adminq_describe_device(struct gve_priv *priv)
 					 &dev_op_buffer_sizes,
 					 &dev_op_flow_steering,
 					 &dev_op_rss_config,
+					 &dev_op_nic_timestamp,
 					 &dev_op_modify_ring);
 	if (err)
 		goto free_device_descriptor;
@@ -1088,7 +1116,8 @@ int gve_adminq_describe_device(struct gve_priv *priv)
 	gve_enable_supported_features(priv, supported_features_mask,
 				      dev_op_jumbo_frames, dev_op_dqo_qpl,
 				      dev_op_buffer_sizes, dev_op_flow_steering,
-				      dev_op_rss_config, dev_op_modify_ring);
+				      dev_op_rss_config, dev_op_nic_timestamp,
+				      dev_op_modify_ring);
 
 free_device_descriptor:
 	dma_pool_free(priv->adminq_pool, descriptor, descriptor_bus);
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.h b/drivers/net/ethernet/google/gve/gve_adminq.h
index 228217458275..42466ee640f1 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.h
+++ b/drivers/net/ethernet/google/gve/gve_adminq.h
@@ -174,6 +174,12 @@ struct gve_device_option_rss_config {
 
 static_assert(sizeof(struct gve_device_option_rss_config) == 8);
 
+struct gve_device_option_nic_timestamp {
+	__be32 supported_features_mask;
+};
+
+static_assert(sizeof(struct gve_device_option_nic_timestamp) == 4);
+
 /* Terminology:
  *
  * RDA - Raw DMA Addressing - Buffers associated with SKBs are directly DMA
@@ -192,6 +198,7 @@ enum gve_dev_opt_id {
 	GVE_DEV_OPT_ID_JUMBO_FRAMES		= 0x8,
 	GVE_DEV_OPT_ID_BUFFER_SIZES		= 0xa,
 	GVE_DEV_OPT_ID_FLOW_STEERING		= 0xb,
+	GVE_DEV_OPT_ID_NIC_TIMESTAMP		= 0xd,
 	GVE_DEV_OPT_ID_RSS_CONFIG		= 0xe,
 };
 
@@ -206,6 +213,7 @@ enum gve_dev_opt_req_feat_mask {
 	GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING		= 0x0,
 	GVE_DEV_OPT_REQ_FEAT_MASK_FLOW_STEERING		= 0x0,
 	GVE_DEV_OPT_REQ_FEAT_MASK_RSS_CONFIG		= 0x0,
+	GVE_DEV_OPT_REQ_FEAT_MASK_NIC_TIMESTAMP		= 0x0,
 };
 
 enum gve_sup_feature_mask {
@@ -214,6 +222,7 @@ enum gve_sup_feature_mask {
 	GVE_SUP_BUFFER_SIZES_MASK	= 1 << 4,
 	GVE_SUP_FLOW_STEERING_MASK	= 1 << 5,
 	GVE_SUP_RSS_CONFIG_MASK		= 1 << 7,
+	GVE_SUP_NIC_TIMESTAMP_MASK	= 1 << 8,
 };
 
 #define GVE_DEV_OPT_LEN_GQI_RAW_ADDRESSING 0x0
-- 
2.49.0.1112.g889b7c5bd8-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next v2 2/8] gve: Add adminq command to report nic timestamp
  2025-05-17  0:11 [PATCH net-next v2 0/8] gve: Add Rx HW timestamping support Harshitha Ramamurthy
  2025-05-17  0:11 ` [PATCH net-next v2 1/8] gve: Add device option for nic clock synchronization Harshitha Ramamurthy
@ 2025-05-17  0:11 ` Harshitha Ramamurthy
  2025-05-17  0:11 ` [PATCH net-next v2 3/8] gve: Add initial PTP device support Harshitha Ramamurthy
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Harshitha Ramamurthy @ 2025-05-17  0:11 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, jeroendb, hramamurthy,
	andrew+netdev, willemb, ziweixiao, pkaligineedi, yyd, joshwash,
	shailend, linux, thostet, jfraker, richardcochran, jdamato,
	vadim.fedorenko, horms, linux-kernel, Jeff Rogers

From: John Fraker <jfraker@google.com>

Add an adminq command to read NIC's hardware clock. The driver
allocates dma memory and passes that dma memory address to the device.
The device then writes the clock to the given address.

Signed-off-by: Jeff Rogers <jefrogers@google.com>
Signed-off-by: John Fraker <jfraker@google.com>
Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
---
 drivers/net/ethernet/google/gve/gve.h         |  1 +
 drivers/net/ethernet/google/gve/gve_adminq.c  | 20 +++++++++++++++++++
 drivers/net/ethernet/google/gve/gve_adminq.h  | 17 ++++++++++++++++
 drivers/net/ethernet/google/gve/gve_ethtool.c |  3 ++-
 4 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index e9b2c1394b1f..cf6947731a9b 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -813,6 +813,7 @@ struct gve_priv {
 	u32 adminq_set_driver_parameter_cnt;
 	u32 adminq_report_stats_cnt;
 	u32 adminq_report_link_speed_cnt;
+	u32 adminq_report_nic_timestamp_cnt;
 	u32 adminq_get_ptype_map_cnt;
 	u32 adminq_verify_driver_compatibility_cnt;
 	u32 adminq_query_flow_rules_cnt;
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c
index ae20d2f7e6e1..f57913a673b4 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.c
+++ b/drivers/net/ethernet/google/gve/gve_adminq.c
@@ -326,6 +326,7 @@ int gve_adminq_alloc(struct device *dev, struct gve_priv *priv)
 	priv->adminq_set_driver_parameter_cnt = 0;
 	priv->adminq_report_stats_cnt = 0;
 	priv->adminq_report_link_speed_cnt = 0;
+	priv->adminq_report_nic_timestamp_cnt = 0;
 	priv->adminq_get_ptype_map_cnt = 0;
 	priv->adminq_query_flow_rules_cnt = 0;
 	priv->adminq_cfg_flow_rule_cnt = 0;
@@ -564,6 +565,9 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv,
 	case GVE_ADMINQ_REPORT_LINK_SPEED:
 		priv->adminq_report_link_speed_cnt++;
 		break;
+	case GVE_ADMINQ_REPORT_NIC_TIMESTAMP:
+		priv->adminq_report_nic_timestamp_cnt++;
+		break;
 	case GVE_ADMINQ_GET_PTYPE_MAP:
 		priv->adminq_get_ptype_map_cnt++;
 		break;
@@ -1229,6 +1233,22 @@ int gve_adminq_report_link_speed(struct gve_priv *priv)
 	return err;
 }
 
+int gve_adminq_report_nic_ts(struct gve_priv *priv,
+			     dma_addr_t nic_ts_report_addr)
+{
+	union gve_adminq_command cmd;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.opcode = cpu_to_be32(GVE_ADMINQ_REPORT_NIC_TIMESTAMP);
+	cmd.report_nic_ts = (struct gve_adminq_report_nic_ts) {
+		.nic_ts_report_len =
+			cpu_to_be64(sizeof(struct gve_nic_ts_report)),
+		.nic_ts_report_addr = cpu_to_be64(nic_ts_report_addr),
+	};
+
+	return gve_adminq_execute_cmd(priv, &cmd);
+}
+
 int gve_adminq_get_ptype_map_dqo(struct gve_priv *priv,
 				 struct gve_ptype_lut *ptype_lut)
 {
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.h b/drivers/net/ethernet/google/gve/gve_adminq.h
index 42466ee640f1..9360b84536d5 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.h
+++ b/drivers/net/ethernet/google/gve/gve_adminq.h
@@ -27,6 +27,7 @@ enum gve_adminq_opcodes {
 	GVE_ADMINQ_GET_PTYPE_MAP		= 0xE,
 	GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY	= 0xF,
 	GVE_ADMINQ_QUERY_FLOW_RULES		= 0x10,
+	GVE_ADMINQ_REPORT_NIC_TIMESTAMP		= 0x11,
 	GVE_ADMINQ_QUERY_RSS			= 0x12,
 
 	/* For commands that are larger than 56 bytes */
@@ -401,6 +402,19 @@ struct gve_adminq_report_link_speed {
 
 static_assert(sizeof(struct gve_adminq_report_link_speed) == 8);
 
+struct gve_adminq_report_nic_ts {
+	__be64 nic_ts_report_len;
+	__be64 nic_ts_report_addr;
+};
+
+static_assert(sizeof(struct gve_adminq_report_nic_ts) == 16);
+
+struct gve_nic_ts_report {
+	__be64 nic_timestamp; /* NIC clock in nanoseconds */
+	__be64 reserved1;
+	__be64 reserved2;
+};
+
 struct stats {
 	__be32 stat_name;
 	__be32 queue_id;
@@ -594,6 +608,7 @@ union gve_adminq_command {
 			struct gve_adminq_query_flow_rules query_flow_rules;
 			struct gve_adminq_configure_rss configure_rss;
 			struct gve_adminq_query_rss query_rss;
+			struct gve_adminq_report_nic_ts report_nic_ts;
 			struct gve_adminq_extended_command extended_command;
 		};
 	};
@@ -633,6 +648,8 @@ int gve_adminq_reset_flow_rules(struct gve_priv *priv);
 int gve_adminq_query_flow_rules(struct gve_priv *priv, u16 query_opcode, u32 starting_loc);
 int gve_adminq_configure_rss(struct gve_priv *priv, struct ethtool_rxfh_param *rxfh);
 int gve_adminq_query_rss_config(struct gve_priv *priv, struct ethtool_rxfh_param *rxfh);
+int gve_adminq_report_nic_ts(struct gve_priv *priv,
+			     dma_addr_t nic_ts_report_addr);
 
 struct gve_ptype_lut;
 int gve_adminq_get_ptype_map_dqo(struct gve_priv *priv,
diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c
index 3c1da0cf3f61..d0628e25a82d 100644
--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
+++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
@@ -76,7 +76,7 @@ static const char gve_gstrings_adminq_stats[][ETH_GSTRING_LEN] __nonstring_array
 	"adminq_dcfg_device_resources_cnt", "adminq_set_driver_parameter_cnt",
 	"adminq_report_stats_cnt", "adminq_report_link_speed_cnt", "adminq_get_ptype_map_cnt",
 	"adminq_query_flow_rules", "adminq_cfg_flow_rule", "adminq_cfg_rss_cnt",
-	"adminq_query_rss_cnt",
+	"adminq_query_rss_cnt", "adminq_report_nic_timestamp_cnt",
 };
 
 static const char gve_gstrings_priv_flags[][ETH_GSTRING_LEN] = {
@@ -456,6 +456,7 @@ gve_get_ethtool_stats(struct net_device *netdev,
 	data[i++] = priv->adminq_cfg_flow_rule_cnt;
 	data[i++] = priv->adminq_cfg_rss_cnt;
 	data[i++] = priv->adminq_query_rss_cnt;
+	data[i++] = priv->adminq_report_nic_timestamp_cnt;
 }
 
 static void gve_get_channels(struct net_device *netdev,
-- 
2.49.0.1112.g889b7c5bd8-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next v2 3/8] gve: Add initial PTP device support
  2025-05-17  0:11 [PATCH net-next v2 0/8] gve: Add Rx HW timestamping support Harshitha Ramamurthy
  2025-05-17  0:11 ` [PATCH net-next v2 1/8] gve: Add device option for nic clock synchronization Harshitha Ramamurthy
  2025-05-17  0:11 ` [PATCH net-next v2 2/8] gve: Add adminq command to report nic timestamp Harshitha Ramamurthy
@ 2025-05-17  0:11 ` Harshitha Ramamurthy
  2025-05-17  0:11 ` [PATCH net-next v2 4/8] gve: Add adminq lock for queues creation and destruction Harshitha Ramamurthy
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Harshitha Ramamurthy @ 2025-05-17  0:11 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, jeroendb, hramamurthy,
	andrew+netdev, willemb, ziweixiao, pkaligineedi, yyd, joshwash,
	shailend, linux, thostet, jfraker, richardcochran, jdamato,
	vadim.fedorenko, horms, linux-kernel

If the device supports reading of the nic clock, add support
to initialize and register the PTP clock.

Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
---
 drivers/net/ethernet/google/Kconfig       |  1 +
 drivers/net/ethernet/google/gve/Makefile  |  4 +-
 drivers/net/ethernet/google/gve/gve.h     |  8 +++
 drivers/net/ethernet/google/gve/gve_ptp.c | 59 +++++++++++++++++++++++
 4 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/google/gve/gve_ptp.c

diff --git a/drivers/net/ethernet/google/Kconfig b/drivers/net/ethernet/google/Kconfig
index 564862a57124..14c9431e15e5 100644
--- a/drivers/net/ethernet/google/Kconfig
+++ b/drivers/net/ethernet/google/Kconfig
@@ -18,6 +18,7 @@ if NET_VENDOR_GOOGLE
 config GVE
 	tristate "Google Virtual NIC (gVNIC) support"
 	depends on (PCI_MSI && (X86 || CPU_LITTLE_ENDIAN))
+	depends on PTP_1588_CLOCK_OPTIONAL
 	select PAGE_POOL
 	help
 	  This driver supports Google Virtual NIC (gVNIC)"
diff --git a/drivers/net/ethernet/google/gve/Makefile b/drivers/net/ethernet/google/gve/Makefile
index 4520f1c07a63..e0ec227a50f7 100644
--- a/drivers/net/ethernet/google/gve/Makefile
+++ b/drivers/net/ethernet/google/gve/Makefile
@@ -1,5 +1,7 @@
 # Makefile for the Google virtual Ethernet (gve) driver
 
 obj-$(CONFIG_GVE) += gve.o
-gve-objs := gve_main.o gve_tx.o gve_tx_dqo.o gve_rx.o gve_rx_dqo.o gve_ethtool.o gve_adminq.o gve_utils.o gve_flow_rule.o \
+gve-y := gve_main.o gve_tx.o gve_tx_dqo.o gve_rx.o gve_rx_dqo.o gve_ethtool.o gve_adminq.o gve_utils.o gve_flow_rule.o \
 	    gve_buffer_mgmt_dqo.o
+
+gve-$(CONFIG_PTP_1588_CLOCK) += gve_ptp.o
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index cf6947731a9b..8d2aa654fd4c 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -12,6 +12,7 @@
 #include <linux/ethtool_netlink.h>
 #include <linux/netdevice.h>
 #include <linux/pci.h>
+#include <linux/ptp_clock_kernel.h>
 #include <linux/u64_stats_sync.h>
 #include <net/page_pool/helpers.h>
 #include <net/xdp.h>
@@ -750,6 +751,12 @@ struct gve_rss_config {
 	u32 *hash_lut;
 };
 
+struct gve_ptp {
+	struct ptp_clock_info info;
+	struct ptp_clock *clock;
+	struct gve_priv *priv;
+};
+
 struct gve_priv {
 	struct net_device *dev;
 	struct gve_tx_ring *tx; /* array of tx_cfg.num_queues */
@@ -874,6 +881,7 @@ struct gve_priv {
 
 	/* True if the device supports reading the nic clock */
 	bool nic_timestamp_supported;
+	struct gve_ptp *ptp;
 };
 
 enum gve_service_task_flags_bit {
diff --git a/drivers/net/ethernet/google/gve/gve_ptp.c b/drivers/net/ethernet/google/gve/gve_ptp.c
new file mode 100644
index 000000000000..293f8dd49afe
--- /dev/null
+++ b/drivers/net/ethernet/google/gve/gve_ptp.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Google virtual Ethernet (gve) driver
+ *
+ * Copyright (C) 2025 Google LLC
+ */
+
+#include "gve.h"
+
+static const struct ptp_clock_info gve_ptp_caps = {
+	.owner          = THIS_MODULE,
+	.name		= "gve clock",
+};
+
+static int __maybe_unused gve_ptp_init(struct gve_priv *priv)
+{
+	struct gve_ptp *ptp;
+	int err;
+
+	if (!priv->nic_timestamp_supported) {
+		dev_dbg(&priv->pdev->dev, "Device does not support PTP\n");
+		return -EOPNOTSUPP;
+	}
+
+	priv->ptp = kzalloc(sizeof(*priv->ptp), GFP_KERNEL);
+	if (!priv->ptp)
+		return -ENOMEM;
+
+	ptp = priv->ptp;
+	ptp->info = gve_ptp_caps;
+	ptp->clock = ptp_clock_register(&ptp->info, &priv->pdev->dev);
+
+	if (IS_ERR(ptp->clock)) {
+		dev_err(&priv->pdev->dev, "PTP clock registration failed\n");
+		err  = PTR_ERR(ptp->clock);
+		goto free_ptp;
+	}
+
+	ptp->priv = priv;
+	return 0;
+
+free_ptp:
+	kfree(ptp);
+	priv->ptp = NULL;
+	return err;
+}
+
+static void __maybe_unused gve_ptp_release(struct gve_priv *priv)
+{
+	struct gve_ptp *ptp = priv->ptp;
+
+	if (!ptp)
+		return;
+
+	if (ptp->clock)
+		ptp_clock_unregister(ptp->clock);
+
+	kfree(ptp);
+	priv->ptp = NULL;
+}
-- 
2.49.0.1112.g889b7c5bd8-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next v2 4/8] gve: Add adminq lock for queues creation and destruction
  2025-05-17  0:11 [PATCH net-next v2 0/8] gve: Add Rx HW timestamping support Harshitha Ramamurthy
                   ` (2 preceding siblings ...)
  2025-05-17  0:11 ` [PATCH net-next v2 3/8] gve: Add initial PTP device support Harshitha Ramamurthy
@ 2025-05-17  0:11 ` Harshitha Ramamurthy
  2025-05-17  0:11 ` [PATCH net-next v2 5/8] gve: Add support to query the nic clock Harshitha Ramamurthy
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Harshitha Ramamurthy @ 2025-05-17  0:11 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, jeroendb, hramamurthy,
	andrew+netdev, willemb, ziweixiao, pkaligineedi, yyd, joshwash,
	shailend, linux, thostet, jfraker, richardcochran, jdamato,
	vadim.fedorenko, horms, linux-kernel

From: Ziwei Xiao <ziweixiao@google.com>

Adminq commands for queues creation and destruction were not
consistently protected by the driver's adminq_lock. This was previously
benign as these operations were always initiated from contexts holding
kernel-level locks (e.g., rtnl_lock, netdev_lock), which provided
serialization.

Upcoming PTP aux_work will issue adminq commands directly from the
driver to read the NIC clock, without such kernel lock protection.
To prevent race conditions with this new PTP work, this patch ensures
the adminq_lock is held during queues creation and destruction.

Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
---
 Changes in v2:
 - Send this patch together with the rx timestamping patches to net-next
   instead of sending it to net (Jakub Kicinski)
 - Remove the unnecessary cleanup (Jakub Kicinski)
---
 drivers/net/ethernet/google/gve/gve_adminq.c | 47 +++++++++++++++-----
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c
index f57913a673b4..a0cc05a9eefc 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.c
+++ b/drivers/net/ethernet/google/gve/gve_adminq.c
@@ -463,6 +463,8 @@ static int gve_adminq_kick_and_wait(struct gve_priv *priv)
 	int tail, head;
 	int i;
 
+	lockdep_assert_held(&priv->adminq_lock);
+
 	tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
 	head = priv->adminq_prod_cnt;
 
@@ -488,9 +490,6 @@ static int gve_adminq_kick_and_wait(struct gve_priv *priv)
 	return 0;
 }
 
-/* This function is not threadsafe - the caller is responsible for any
- * necessary locks.
- */
 static int gve_adminq_issue_cmd(struct gve_priv *priv,
 				union gve_adminq_command *cmd_orig)
 {
@@ -498,6 +497,8 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv,
 	u32 opcode;
 	u32 tail;
 
+	lockdep_assert_held(&priv->adminq_lock);
+
 	tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
 
 	// Check if next command will overflow the buffer.
@@ -733,13 +734,19 @@ int gve_adminq_create_tx_queues(struct gve_priv *priv, u32 start_id, u32 num_que
 	int err;
 	int i;
 
+	mutex_lock(&priv->adminq_lock);
+
 	for (i = start_id; i < start_id + num_queues; i++) {
 		err = gve_adminq_create_tx_queue(priv, i);
 		if (err)
-			return err;
+			goto out;
 	}
 
-	return gve_adminq_kick_and_wait(priv);
+	err = gve_adminq_kick_and_wait(priv);
+
+out:
+	mutex_unlock(&priv->adminq_lock);
+	return err;
 }
 
 static void gve_adminq_get_create_rx_queue_cmd(struct gve_priv *priv,
@@ -812,13 +819,19 @@ int gve_adminq_create_rx_queues(struct gve_priv *priv, u32 num_queues)
 	int err;
 	int i;
 
+	mutex_lock(&priv->adminq_lock);
+
 	for (i = 0; i < num_queues; i++) {
 		err = gve_adminq_create_rx_queue(priv, i);
 		if (err)
-			return err;
+			goto out;
 	}
 
-	return gve_adminq_kick_and_wait(priv);
+	err = gve_adminq_kick_and_wait(priv);
+
+out:
+	mutex_unlock(&priv->adminq_lock);
+	return err;
 }
 
 static int gve_adminq_destroy_tx_queue(struct gve_priv *priv, u32 queue_index)
@@ -844,13 +857,19 @@ int gve_adminq_destroy_tx_queues(struct gve_priv *priv, u32 start_id, u32 num_qu
 	int err;
 	int i;
 
+	mutex_lock(&priv->adminq_lock);
+
 	for (i = start_id; i < start_id + num_queues; i++) {
 		err = gve_adminq_destroy_tx_queue(priv, i);
 		if (err)
-			return err;
+			goto out;
 	}
 
-	return gve_adminq_kick_and_wait(priv);
+	err = gve_adminq_kick_and_wait(priv);
+
+out:
+	mutex_unlock(&priv->adminq_lock);
+	return err;
 }
 
 static void gve_adminq_make_destroy_rx_queue_cmd(union gve_adminq_command *cmd,
@@ -885,13 +904,19 @@ int gve_adminq_destroy_rx_queues(struct gve_priv *priv, u32 num_queues)
 	int err;
 	int i;
 
+	mutex_lock(&priv->adminq_lock);
+
 	for (i = 0; i < num_queues; i++) {
 		err = gve_adminq_destroy_rx_queue(priv, i);
 		if (err)
-			return err;
+			goto out;
 	}
 
-	return gve_adminq_kick_and_wait(priv);
+	err = gve_adminq_kick_and_wait(priv);
+
+out:
+	mutex_unlock(&priv->adminq_lock);
+	return err;
 }
 
 static void gve_set_default_desc_cnt(struct gve_priv *priv,
-- 
2.49.0.1112.g889b7c5bd8-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next v2 5/8] gve: Add support to query the nic clock
  2025-05-17  0:11 [PATCH net-next v2 0/8] gve: Add Rx HW timestamping support Harshitha Ramamurthy
                   ` (3 preceding siblings ...)
  2025-05-17  0:11 ` [PATCH net-next v2 4/8] gve: Add adminq lock for queues creation and destruction Harshitha Ramamurthy
@ 2025-05-17  0:11 ` Harshitha Ramamurthy
  2025-05-17  0:11 ` [PATCH net-next v2 6/8] gve: Add rx hardware timestamp expansion Harshitha Ramamurthy
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Harshitha Ramamurthy @ 2025-05-17  0:11 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, jeroendb, hramamurthy,
	andrew+netdev, willemb, ziweixiao, pkaligineedi, yyd, joshwash,
	shailend, linux, thostet, jfraker, richardcochran, jdamato,
	vadim.fedorenko, horms, linux-kernel

From: Kevin Yang <yyd@google.com>

Query the nic clock and store the results. The timestamp delivered
in descriptors has a wraparound time of ~4 seconds so 250ms is chosen
as the sync cadence to provide a balance between performance, and
drift potential when we do start associating host time and nic time.

Leverage PTP's aux_work to query the nic clock periodically.

Signed-off-by: Kevin Yang <yyd@google.com>
Signed-off-by: John Fraker <jfraker@google.com>
Signed-off-by: Tim Hostetler <thostet@google.com>
Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
---
 Changes in v2:
 - Utilize the ptp's aux_work instead of delayed_work (Jakub Kicinski,
   Vadim Fedorenko)
---
 drivers/net/ethernet/google/gve/gve.h     | 15 +++++
 drivers/net/ethernet/google/gve/gve_ptp.c | 77 ++++++++++++++++++++++-
 2 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index 8d2aa654fd4c..97054b272e40 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -882,6 +882,9 @@ struct gve_priv {
 	/* True if the device supports reading the nic clock */
 	bool nic_timestamp_supported;
 	struct gve_ptp *ptp;
+	struct gve_nic_ts_report *nic_ts_report;
+	dma_addr_t nic_ts_report_bus;
+	u64 last_sync_nic_counter; /* Clock counter from last NIC TS report */
 };
 
 enum gve_service_task_flags_bit {
@@ -1261,6 +1264,18 @@ int gve_del_flow_rule(struct gve_priv *priv, struct ethtool_rxnfc *cmd);
 int gve_flow_rules_reset(struct gve_priv *priv);
 /* RSS config */
 int gve_init_rss_config(struct gve_priv *priv, u16 num_queues);
+/* PTP and timestamping */
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+int gve_init_clock(struct gve_priv *priv);
+void gve_teardown_clock(struct gve_priv *priv);
+#else /* CONFIG_PTP_1588_CLOCK */
+static inline int gve_init_clock(struct gve_priv *priv)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline void gve_teardown_clock(struct gve_priv *priv) { }
+#endif /* CONFIG_PTP_1588_CLOCK */
 /* report stats handling */
 void gve_handle_report_stats(struct gve_priv *priv);
 /* exported by ethtool.c */
diff --git a/drivers/net/ethernet/google/gve/gve_ptp.c b/drivers/net/ethernet/google/gve/gve_ptp.c
index 293f8dd49afe..b6e18ad20fa9 100644
--- a/drivers/net/ethernet/google/gve/gve_ptp.c
+++ b/drivers/net/ethernet/google/gve/gve_ptp.c
@@ -5,13 +5,52 @@
  */
 
 #include "gve.h"
+#include "gve_adminq.h"
+
+/* Interval to schedule a nic timestamp calibration, 250ms. */
+#define GVE_NIC_TS_SYNC_INTERVAL_MS 250
+
+/* Read the nic timestamp from hardware via the admin queue. */
+static int gve_clock_nic_ts_read(struct gve_priv *priv)
+{
+	u64 nic_raw;
+	int err;
+
+	err = gve_adminq_report_nic_ts(priv, priv->nic_ts_report_bus);
+	if (err)
+		return err;
+
+	nic_raw = be64_to_cpu(priv->nic_ts_report->nic_timestamp);
+	WRITE_ONCE(priv->last_sync_nic_counter, nic_raw);
+
+	return 0;
+}
+
+static long gve_ptp_do_aux_work(struct ptp_clock_info *info)
+{
+	const struct gve_ptp *ptp = container_of(info, struct gve_ptp, info);
+	struct gve_priv *priv = ptp->priv;
+	int err;
+
+	if (gve_get_reset_in_progress(priv) || !gve_get_admin_queue_ok(priv))
+		goto out;
+
+	err = gve_clock_nic_ts_read(priv);
+	if (err && net_ratelimit())
+		dev_err(&priv->pdev->dev,
+			"%s read err %d\n", __func__, err);
+
+out:
+	return msecs_to_jiffies(GVE_NIC_TS_SYNC_INTERVAL_MS);
+}
 
 static const struct ptp_clock_info gve_ptp_caps = {
 	.owner          = THIS_MODULE,
 	.name		= "gve clock",
+	.do_aux_work	= gve_ptp_do_aux_work,
 };
 
-static int __maybe_unused gve_ptp_init(struct gve_priv *priv)
+static int gve_ptp_init(struct gve_priv *priv)
 {
 	struct gve_ptp *ptp;
 	int err;
@@ -44,7 +83,29 @@ static int __maybe_unused gve_ptp_init(struct gve_priv *priv)
 	return err;
 }
 
-static void __maybe_unused gve_ptp_release(struct gve_priv *priv)
+int gve_init_clock(struct gve_priv *priv)
+{
+	int err;
+
+	err = gve_ptp_init(priv);
+	if (err)
+		return err;
+
+	priv->nic_ts_report =
+		dma_alloc_coherent(&priv->pdev->dev,
+				   sizeof(struct gve_nic_ts_report),
+				   &priv->nic_ts_report_bus,
+				   GFP_KERNEL);
+	if (!priv->nic_ts_report) {
+		dev_err(&priv->pdev->dev, "%s dma alloc error\n", __func__);
+		return -ENOMEM;
+	}
+
+	ptp_schedule_worker(priv->ptp->clock, 0);
+	return 0;
+}
+
+static void gve_ptp_release(struct gve_priv *priv)
 {
 	struct gve_ptp *ptp = priv->ptp;
 
@@ -57,3 +118,15 @@ static void __maybe_unused gve_ptp_release(struct gve_priv *priv)
 	kfree(ptp);
 	priv->ptp = NULL;
 }
+
+void gve_teardown_clock(struct gve_priv *priv)
+{
+	gve_ptp_release(priv);
+
+	if (priv->nic_ts_report) {
+		dma_free_coherent(&priv->pdev->dev,
+				  sizeof(struct gve_nic_ts_report),
+				  priv->nic_ts_report, priv->nic_ts_report_bus);
+		priv->nic_ts_report = NULL;
+	}
+}
-- 
2.49.0.1112.g889b7c5bd8-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next v2 6/8] gve: Add rx hardware timestamp expansion
  2025-05-17  0:11 [PATCH net-next v2 0/8] gve: Add Rx HW timestamping support Harshitha Ramamurthy
                   ` (4 preceding siblings ...)
  2025-05-17  0:11 ` [PATCH net-next v2 5/8] gve: Add support to query the nic clock Harshitha Ramamurthy
@ 2025-05-17  0:11 ` Harshitha Ramamurthy
  2025-05-18 21:45   ` Vadim Fedorenko
  2025-05-17  0:11 ` [PATCH net-next v2 7/8] gve: Add support for SIOC[GS]HWTSTAMP IOCTLs Harshitha Ramamurthy
  2025-05-17  0:11 ` [PATCH net-next v2 8/8] gve: Advertise support for rx hardware timestamping Harshitha Ramamurthy
  7 siblings, 1 reply; 15+ messages in thread
From: Harshitha Ramamurthy @ 2025-05-17  0:11 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, jeroendb, hramamurthy,
	andrew+netdev, willemb, ziweixiao, pkaligineedi, yyd, joshwash,
	shailend, linux, thostet, jfraker, richardcochran, jdamato,
	vadim.fedorenko, horms, linux-kernel

From: John Fraker <jfraker@google.com>

Allow the rx path to recover the high 32 bits of the full 64 bit rx
timestamp.

Use the low 32 bits of the last synced nic time and the 32 bits of the
timestamp provided in the rx descriptor to generate a difference, which
is then applied to the last synced nic time to reconstruct the complete
64-bit timestamp.

This scheme remains accurate as long as no more than ~2 seconds have
passed between the last read of the nic clock and the timestamping
application of the received packet.

Signed-off-by: John Fraker <jfraker@google.com>
Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
---
 Changes in v2:
 - Add the missing READ_ONCE (Joe Damato)
---
 drivers/net/ethernet/google/gve/gve_rx_dqo.c | 23 ++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
index dcb0545baa50..c03c3741e0d4 100644
--- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
@@ -437,6 +437,29 @@ static void gve_rx_skb_hash(struct sk_buff *skb,
 	skb_set_hash(skb, le32_to_cpu(compl_desc->hash), hash_type);
 }
 
+/* Expand the hardware timestamp to the full 64 bits of width, and add it to the
+ * skb.
+ *
+ * This algorithm works by using the passed hardware timestamp to generate a
+ * diff relative to the last read of the nic clock. This diff can be positive or
+ * negative, as it is possible that we have read the clock more recently than
+ * the hardware has received this packet. To detect this, we use the high bit of
+ * the diff, and assume that the read is more recent if the high bit is set. In
+ * this case we invert the process.
+ *
+ * Note that this means if the time delta between packet reception and the last
+ * clock read is greater than ~2 seconds, this will provide invalid results.
+ */
+static void __maybe_unused gve_rx_skb_hwtstamp(struct gve_rx_ring *rx, u32 hwts)
+{
+	s64 last_read = READ_ONCE(rx->gve->last_sync_nic_counter);
+	struct sk_buff *skb = rx->ctx.skb_head;
+	u32 low = (u32)last_read;
+	s32 diff = hwts - low;
+
+	skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(last_read + diff);
+}
+
 static void gve_rx_free_skb(struct napi_struct *napi, struct gve_rx_ring *rx)
 {
 	if (!rx->ctx.skb_head)
-- 
2.49.0.1112.g889b7c5bd8-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next v2 7/8] gve: Add support for SIOC[GS]HWTSTAMP IOCTLs
  2025-05-17  0:11 [PATCH net-next v2 0/8] gve: Add Rx HW timestamping support Harshitha Ramamurthy
                   ` (5 preceding siblings ...)
  2025-05-17  0:11 ` [PATCH net-next v2 6/8] gve: Add rx hardware timestamp expansion Harshitha Ramamurthy
@ 2025-05-17  0:11 ` Harshitha Ramamurthy
  2025-05-17  1:52   ` Jakub Kicinski
  2025-05-17  0:11 ` [PATCH net-next v2 8/8] gve: Advertise support for rx hardware timestamping Harshitha Ramamurthy
  7 siblings, 1 reply; 15+ messages in thread
From: Harshitha Ramamurthy @ 2025-05-17  0:11 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, jeroendb, hramamurthy,
	andrew+netdev, willemb, ziweixiao, pkaligineedi, yyd, joshwash,
	shailend, linux, thostet, jfraker, richardcochran, jdamato,
	vadim.fedorenko, horms, linux-kernel

From: John Fraker <jfraker@google.com>

Add support for the SIOCSHWTSTAMP and SIOCGHWTSTAMP IOCTL methods using
gve_get_ts_config and gve_set_ts_config. Included with this support is
the small change necessary to read the rx timestamp out of the rx
descriptor, now that timestamps start being enabled. The gve clock is
only used for hardware timestamps, so started when timestamps are
requested and stopped when not needed.

This version only supports RX hardware timestamping with the rx filter
HWTSTAMP_FILTER_ALL. If the user attempts to configure a more
restrictive filter, the filter will be set to HWTSTAMP_FILTER_ALL in the
returned structure.

Signed-off-by: John Fraker <jfraker@google.com>
Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
---
 drivers/net/ethernet/google/gve/gve.h         |  2 +
 .../net/ethernet/google/gve/gve_desc_dqo.h    |  3 +-
 drivers/net/ethernet/google/gve/gve_main.c    | 47 +++++++++++++++++++
 drivers/net/ethernet/google/gve/gve_rx_dqo.c  |  5 +-
 4 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index 97054b272e40..a812612c52ba 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -11,6 +11,7 @@
 #include <linux/dmapool.h>
 #include <linux/ethtool_netlink.h>
 #include <linux/netdevice.h>
+#include <linux/net_tstamp.h>
 #include <linux/pci.h>
 #include <linux/ptp_clock_kernel.h>
 #include <linux/u64_stats_sync.h>
@@ -882,6 +883,7 @@ struct gve_priv {
 	/* True if the device supports reading the nic clock */
 	bool nic_timestamp_supported;
 	struct gve_ptp *ptp;
+	struct kernel_hwtstamp_config ts_config;
 	struct gve_nic_ts_report *nic_ts_report;
 	dma_addr_t nic_ts_report_bus;
 	u64 last_sync_nic_counter; /* Clock counter from last NIC TS report */
diff --git a/drivers/net/ethernet/google/gve/gve_desc_dqo.h b/drivers/net/ethernet/google/gve/gve_desc_dqo.h
index f79cd0591110..d17da841b5a0 100644
--- a/drivers/net/ethernet/google/gve/gve_desc_dqo.h
+++ b/drivers/net/ethernet/google/gve/gve_desc_dqo.h
@@ -247,7 +247,8 @@ struct gve_rx_compl_desc_dqo {
 	};
 	__le32 hash;
 	__le32 reserved6;
-	__le64 reserved7;
+	__le32 reserved7;
+	__le32 ts; /* timestamp in nanosecs */
 } __packed;
 
 static_assert(sizeof(struct gve_rx_compl_desc_dqo) == 32);
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index e1ffbd561fac..b5234ef9c6a0 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -721,6 +721,7 @@ static void gve_teardown_device_resources(struct gve_priv *priv)
 	gve_free_counter_array(priv);
 	gve_free_notify_blocks(priv);
 	gve_free_stats_report(priv);
+	gve_teardown_clock(priv);
 	gve_clear_device_resources_ok(priv);
 }
 
@@ -2041,6 +2042,47 @@ static int gve_set_features(struct net_device *netdev,
 	return err;
 }
 
+static int gve_get_ts_config(struct net_device *dev,
+			     struct kernel_hwtstamp_config *kernel_config)
+{
+	struct gve_priv *priv = netdev_priv(dev);
+
+	*kernel_config = priv->ts_config;
+	return 0;
+}
+
+static int gve_set_ts_config(struct net_device *dev,
+			     struct kernel_hwtstamp_config *kernel_config,
+			     struct netlink_ext_ack *extack)
+{
+	struct gve_priv *priv = netdev_priv(dev);
+	int err;
+
+	if (kernel_config->tx_type != HWTSTAMP_TX_OFF) {
+		dev_err(&priv->pdev->dev, "TX timestamping is not supported\n");
+		return -ERANGE;
+	}
+
+	if (kernel_config->rx_filter != HWTSTAMP_FILTER_NONE) {
+		kernel_config->rx_filter = HWTSTAMP_FILTER_ALL;
+		if (!priv->nic_ts_report) {
+			err = gve_init_clock(priv);
+			if (err) {
+				dev_err(&priv->pdev->dev,
+					"Failed to initialize GVE clock\n");
+				kernel_config->rx_filter = HWTSTAMP_FILTER_NONE;
+				return err;
+			}
+		}
+	} else {
+		gve_teardown_clock(priv);
+	}
+
+	priv->ts_config.rx_filter = kernel_config->rx_filter;
+
+	return 0;
+}
+
 static const struct net_device_ops gve_netdev_ops = {
 	.ndo_start_xmit		=	gve_start_xmit,
 	.ndo_features_check	=	gve_features_check,
@@ -2052,6 +2094,8 @@ static const struct net_device_ops gve_netdev_ops = {
 	.ndo_bpf		=	gve_xdp,
 	.ndo_xdp_xmit		=	gve_xdp_xmit,
 	.ndo_xsk_wakeup		=	gve_xsk_wakeup,
+	.ndo_hwtstamp_get	=	gve_get_ts_config,
+	.ndo_hwtstamp_set	=	gve_set_ts_config,
 };
 
 static void gve_handle_status(struct gve_priv *priv, u32 status)
@@ -2271,6 +2315,9 @@ static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
 		priv->rx_coalesce_usecs = GVE_RX_IRQ_RATELIMIT_US_DQO;
 	}
 
+	priv->ts_config.tx_type = HWTSTAMP_TX_OFF;
+	priv->ts_config.rx_filter = HWTSTAMP_FILTER_NONE;
+
 setup_device:
 	gve_set_netdev_xdp_features(priv);
 	err = gve_setup_device_resources(priv);
diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
index c03c3741e0d4..15d3c414b33c 100644
--- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
@@ -450,7 +450,7 @@ static void gve_rx_skb_hash(struct sk_buff *skb,
  * Note that this means if the time delta between packet reception and the last
  * clock read is greater than ~2 seconds, this will provide invalid results.
  */
-static void __maybe_unused gve_rx_skb_hwtstamp(struct gve_rx_ring *rx, u32 hwts)
+static void gve_rx_skb_hwtstamp(struct gve_rx_ring *rx, u32 hwts)
 {
 	s64 last_read = READ_ONCE(rx->gve->last_sync_nic_counter);
 	struct sk_buff *skb = rx->ctx.skb_head;
@@ -790,6 +790,9 @@ static int gve_rx_complete_skb(struct gve_rx_ring *rx, struct napi_struct *napi,
 	if (feat & NETIF_F_RXCSUM)
 		gve_rx_skb_csum(rx->ctx.skb_head, desc, ptype);
 
+	if (rx->gve->ts_config.rx_filter == HWTSTAMP_FILTER_ALL)
+		gve_rx_skb_hwtstamp(rx, le32_to_cpu(desc->ts));
+
 	/* RSC packets must set gso_size otherwise the TCP stack will complain
 	 * that packets are larger than MTU.
 	 */
-- 
2.49.0.1112.g889b7c5bd8-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next v2 8/8] gve: Advertise support for rx hardware timestamping
  2025-05-17  0:11 [PATCH net-next v2 0/8] gve: Add Rx HW timestamping support Harshitha Ramamurthy
                   ` (6 preceding siblings ...)
  2025-05-17  0:11 ` [PATCH net-next v2 7/8] gve: Add support for SIOC[GS]HWTSTAMP IOCTLs Harshitha Ramamurthy
@ 2025-05-17  0:11 ` Harshitha Ramamurthy
  7 siblings, 0 replies; 15+ messages in thread
From: Harshitha Ramamurthy @ 2025-05-17  0:11 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, jeroendb, hramamurthy,
	andrew+netdev, willemb, ziweixiao, pkaligineedi, yyd, joshwash,
	shailend, linux, thostet, jfraker, richardcochran, jdamato,
	vadim.fedorenko, horms, linux-kernel

From: John Fraker <jfraker@google.com>

Expand the get_ts_info ethtool handler with the new gve_get_ts_info
which advertises support for rx hardware timestamping.

With this patch, the driver now fully supports rx hardware timestamping.

Signed-off-by: John Fraker <jfraker@google.com>
Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
---
 drivers/net/ethernet/google/gve/gve_ethtool.c | 20 ++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c
index d0628e25a82d..043d1959fb9d 100644
--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
+++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
@@ -929,6 +929,24 @@ static int gve_set_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rx
 	return 0;
 }
 
+static int gve_get_ts_info(struct net_device *netdev,
+			   struct kernel_ethtool_ts_info *info)
+{
+	struct gve_priv *priv = netdev_priv(netdev);
+
+	ethtool_op_get_ts_info(netdev, info);
+
+	if (priv->nic_timestamp_supported) {
+		info->so_timestamping |= SOF_TIMESTAMPING_RX_HARDWARE |
+					 SOF_TIMESTAMPING_RAW_HARDWARE;
+
+		info->rx_filters |= BIT(HWTSTAMP_FILTER_NONE) |
+				    BIT(HWTSTAMP_FILTER_ALL);
+	}
+
+	return 0;
+}
+
 const struct ethtool_ops gve_ethtool_ops = {
 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS,
 	.supported_ring_params = ETHTOOL_RING_USE_TCP_DATA_SPLIT,
@@ -957,5 +975,5 @@ const struct ethtool_ops gve_ethtool_ops = {
 	.get_priv_flags = gve_get_priv_flags,
 	.set_priv_flags = gve_set_priv_flags,
 	.get_link_ksettings = gve_get_link_ksettings,
-	.get_ts_info = ethtool_op_get_ts_info,
+	.get_ts_info = gve_get_ts_info,
 };
-- 
2.49.0.1112.g889b7c5bd8-goog


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next v2 7/8] gve: Add support for SIOC[GS]HWTSTAMP IOCTLs
  2025-05-17  0:11 ` [PATCH net-next v2 7/8] gve: Add support for SIOC[GS]HWTSTAMP IOCTLs Harshitha Ramamurthy
@ 2025-05-17  1:52   ` Jakub Kicinski
  2025-05-19 18:32     ` Ziwei Xiao
  0 siblings, 1 reply; 15+ messages in thread
From: Jakub Kicinski @ 2025-05-17  1:52 UTC (permalink / raw)
  To: Harshitha Ramamurthy
  Cc: netdev, davem, edumazet, pabeni, jeroendb, andrew+netdev, willemb,
	ziweixiao, pkaligineedi, yyd, joshwash, shailend, linux, thostet,
	jfraker, richardcochran, jdamato, vadim.fedorenko, horms,
	linux-kernel

On Sat, 17 May 2025 00:11:09 +0000 Harshitha Ramamurthy wrote:
> Subject: [PATCH net-next v2 7/8] gve: Add support for SIOC[GS]HWTSTAMP IOCTLs

Sorry for the very shallow review, the subject jumped out at me.
You're not implementing the shouty ioctl, you're adding ndos.

> +	if (kernel_config->tx_type != HWTSTAMP_TX_OFF) {
> +		dev_err(&priv->pdev->dev, "TX timestamping is not supported\n");

please use extack

> +		return -ERANGE;
> +	}
> +
> +	if (kernel_config->rx_filter != HWTSTAMP_FILTER_NONE) {
> +		kernel_config->rx_filter = HWTSTAMP_FILTER_ALL;
> +		if (!priv->nic_ts_report) {
> +			err = gve_init_clock(priv);
> +			if (err) {
> +				dev_err(&priv->pdev->dev,
> +					"Failed to initialize GVE clock\n");

and here. Remember to remove the \n when converting.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next v2 6/8] gve: Add rx hardware timestamp expansion
  2025-05-17  0:11 ` [PATCH net-next v2 6/8] gve: Add rx hardware timestamp expansion Harshitha Ramamurthy
@ 2025-05-18 21:45   ` Vadim Fedorenko
  2025-05-19 18:45     ` Ziwei Xiao
  0 siblings, 1 reply; 15+ messages in thread
From: Vadim Fedorenko @ 2025-05-18 21:45 UTC (permalink / raw)
  To: Harshitha Ramamurthy, netdev
  Cc: davem, edumazet, kuba, pabeni, jeroendb, andrew+netdev, willemb,
	ziweixiao, pkaligineedi, yyd, joshwash, shailend, linux, thostet,
	jfraker, richardcochran, jdamato, horms, linux-kernel

On 17.05.2025 01:11, Harshitha Ramamurthy wrote:
> From: John Fraker <jfraker@google.com>
> 
> Allow the rx path to recover the high 32 bits of the full 64 bit rx
> timestamp.
> 
> Use the low 32 bits of the last synced nic time and the 32 bits of the
> timestamp provided in the rx descriptor to generate a difference, which
> is then applied to the last synced nic time to reconstruct the complete
> 64-bit timestamp.
> 
> This scheme remains accurate as long as no more than ~2 seconds have
> passed between the last read of the nic clock and the timestamping
> application of the received packet.
> 
> Signed-off-by: John Fraker <jfraker@google.com>
> Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
> Reviewed-by: Willem de Bruijn <willemb@google.com>
> Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
> ---
>   Changes in v2:
>   - Add the missing READ_ONCE (Joe Damato)
> ---
>   drivers/net/ethernet/google/gve/gve_rx_dqo.c | 23 ++++++++++++++++++++
>   1 file changed, 23 insertions(+)
> 
> diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
> index dcb0545baa50..c03c3741e0d4 100644
> --- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
> +++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
> @@ -437,6 +437,29 @@ static void gve_rx_skb_hash(struct sk_buff *skb,
>   	skb_set_hash(skb, le32_to_cpu(compl_desc->hash), hash_type);
>   }
>   
> +/* Expand the hardware timestamp to the full 64 bits of width, and add it to the
> + * skb.
> + *
> + * This algorithm works by using the passed hardware timestamp to generate a
> + * diff relative to the last read of the nic clock. This diff can be positive or
> + * negative, as it is possible that we have read the clock more recently than
> + * the hardware has received this packet. To detect this, we use the high bit of
> + * the diff, and assume that the read is more recent if the high bit is set. In
> + * this case we invert the process.
> + *
> + * Note that this means if the time delta between packet reception and the last
> + * clock read is greater than ~2 seconds, this will provide invalid results.
> + */
> +static void __maybe_unused gve_rx_skb_hwtstamp(struct gve_rx_ring *rx, u32 hwts)
> +{
> +	s64 last_read = READ_ONCE(rx->gve->last_sync_nic_counter);

I believe last_read should be u64 as last_sync_nic_counter is u64 and
ns_to_ktime expects u64.

> +	struct sk_buff *skb = rx->ctx.skb_head;
> +	u32 low = (u32)last_read;
> +	s32 diff = hwts - low;
> +
> +	skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(last_read + diff);
> +}
> +
>   static void gve_rx_free_skb(struct napi_struct *napi, struct gve_rx_ring *rx)
>   {
>   	if (!rx->ctx.skb_head)


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next v2 7/8] gve: Add support for SIOC[GS]HWTSTAMP IOCTLs
  2025-05-17  1:52   ` Jakub Kicinski
@ 2025-05-19 18:32     ` Ziwei Xiao
  0 siblings, 0 replies; 15+ messages in thread
From: Ziwei Xiao @ 2025-05-19 18:32 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Harshitha Ramamurthy, netdev, davem, edumazet, pabeni, jeroendb,
	andrew+netdev, willemb, pkaligineedi, yyd, joshwash, shailend,
	linux, thostet, jfraker, richardcochran, jdamato, vadim.fedorenko,
	horms, linux-kernel

On Fri, May 16, 2025 at 6:52 PM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Sat, 17 May 2025 00:11:09 +0000 Harshitha Ramamurthy wrote:
> > Subject: [PATCH net-next v2 7/8] gve: Add support for SIOC[GS]HWTSTAMP IOCTLs
>
> Sorry for the very shallow review, the subject jumped out at me.
> You're not implementing the shouty ioctl, you're adding ndos.
>
I see, I will change the title and commit message to be more related
with the ndos.
> > +     if (kernel_config->tx_type != HWTSTAMP_TX_OFF) {
> > +             dev_err(&priv->pdev->dev, "TX timestamping is not supported\n");
>
> please use extack
>
> > +             return -ERANGE;
> > +     }
> > +
> > +     if (kernel_config->rx_filter != HWTSTAMP_FILTER_NONE) {
> > +             kernel_config->rx_filter = HWTSTAMP_FILTER_ALL;
> > +             if (!priv->nic_ts_report) {
> > +                     err = gve_init_clock(priv);
> > +                     if (err) {
> > +                             dev_err(&priv->pdev->dev,
> > +                                     "Failed to initialize GVE clock\n");
>
> and here. Remember to remove the \n when converting.
Thanks, I will update these to use extack in V3.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next v2 6/8] gve: Add rx hardware timestamp expansion
  2025-05-18 21:45   ` Vadim Fedorenko
@ 2025-05-19 18:45     ` Ziwei Xiao
  2025-05-20 19:53       ` Vadim Fedorenko
  0 siblings, 1 reply; 15+ messages in thread
From: Ziwei Xiao @ 2025-05-19 18:45 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Harshitha Ramamurthy, netdev, davem, edumazet, kuba, pabeni,
	jeroendb, andrew+netdev, willemb, pkaligineedi, yyd, joshwash,
	shailend, linux, thostet, jfraker, richardcochran, jdamato, horms,
	linux-kernel

.


On Sun, May 18, 2025 at 2:45 PM Vadim Fedorenko
<vadim.fedorenko@linux.dev> wrote:
>
> On 17.05.2025 01:11, Harshitha Ramamurthy wrote:
> > From: John Fraker <jfraker@google.com>
> >
> > Allow the rx path to recover the high 32 bits of the full 64 bit rx
> > timestamp.
> >
> > Use the low 32 bits of the last synced nic time and the 32 bits of the
> > timestamp provided in the rx descriptor to generate a difference, which
> > is then applied to the last synced nic time to reconstruct the complete
> > 64-bit timestamp.
> >
> > This scheme remains accurate as long as no more than ~2 seconds have
> > passed between the last read of the nic clock and the timestamping
> > application of the received packet.
> >
> > Signed-off-by: John Fraker <jfraker@google.com>
> > Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
> > Reviewed-by: Willem de Bruijn <willemb@google.com>
> > Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
> > ---
> >   Changes in v2:
> >   - Add the missing READ_ONCE (Joe Damato)
> > ---
> >   drivers/net/ethernet/google/gve/gve_rx_dqo.c | 23 ++++++++++++++++++++
> >   1 file changed, 23 insertions(+)
> >
> > diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
> > index dcb0545baa50..c03c3741e0d4 100644
> > --- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
> > +++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
> > @@ -437,6 +437,29 @@ static void gve_rx_skb_hash(struct sk_buff *skb,
> >       skb_set_hash(skb, le32_to_cpu(compl_desc->hash), hash_type);
> >   }
> >
> > +/* Expand the hardware timestamp to the full 64 bits of width, and add it to the
> > + * skb.
> > + *
> > + * This algorithm works by using the passed hardware timestamp to generate a
> > + * diff relative to the last read of the nic clock. This diff can be positive or
> > + * negative, as it is possible that we have read the clock more recently than
> > + * the hardware has received this packet. To detect this, we use the high bit of
> > + * the diff, and assume that the read is more recent if the high bit is set. In
> > + * this case we invert the process.
> > + *
> > + * Note that this means if the time delta between packet reception and the last
> > + * clock read is greater than ~2 seconds, this will provide invalid results.
> > + */
> > +static void __maybe_unused gve_rx_skb_hwtstamp(struct gve_rx_ring *rx, u32 hwts)
> > +{
> > +     s64 last_read = READ_ONCE(rx->gve->last_sync_nic_counter);
>
> I believe last_read should be u64 as last_sync_nic_counter is u64 and
> ns_to_ktime expects u64.
>
Thanks for the suggestion. The reason to choose s64 for `last_read`
here is to use signed addition explicitly with `last_read +
(s32)diff`. This allows diff (which can be positive or negative,
depending on whether hwts is ahead of or behind low(last_read)) to
directly adjust last_read without a conditional branch, which makes
the intent clear IMO. The s64 nanosecond value is not at risk of
overflow, and the positive s64 result is then safely converted to u64
for ns_to_ktime.

I'm happy to change last_read to u64 if that's preferred for type
consistency, or I can add a comment to clarify the rationale for the
current s64 approach. Please let me know what you think. Thanks!

> > +     struct sk_buff *skb = rx->ctx.skb_head;
> > +     u32 low = (u32)last_read;
> > +     s32 diff = hwts - low;
> > +
> > +     skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(last_read + diff);
> > +}
> > +
> >   static void gve_rx_free_skb(struct napi_struct *napi, struct gve_rx_ring *rx)
> >   {
> >       if (!rx->ctx.skb_head)
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next v2 6/8] gve: Add rx hardware timestamp expansion
  2025-05-19 18:45     ` Ziwei Xiao
@ 2025-05-20 19:53       ` Vadim Fedorenko
  2025-05-21  5:22         ` Ziwei Xiao
  0 siblings, 1 reply; 15+ messages in thread
From: Vadim Fedorenko @ 2025-05-20 19:53 UTC (permalink / raw)
  To: Ziwei Xiao
  Cc: Harshitha Ramamurthy, netdev, davem, edumazet, kuba, pabeni,
	jeroendb, andrew+netdev, willemb, pkaligineedi, yyd, joshwash,
	shailend, linux, thostet, jfraker, richardcochran, jdamato, horms,
	linux-kernel

On 19.05.2025 19:45, Ziwei Xiao wrote:
> .
> 
> 
> On Sun, May 18, 2025 at 2:45 PM Vadim Fedorenko
> <vadim.fedorenko@linux.dev> wrote:
>>
>> On 17.05.2025 01:11, Harshitha Ramamurthy wrote:
>>> From: John Fraker <jfraker@google.com>
>>>
>>> Allow the rx path to recover the high 32 bits of the full 64 bit rx
>>> timestamp.
>>>
>>> Use the low 32 bits of the last synced nic time and the 32 bits of the
>>> timestamp provided in the rx descriptor to generate a difference, which
>>> is then applied to the last synced nic time to reconstruct the complete
>>> 64-bit timestamp.
>>>
>>> This scheme remains accurate as long as no more than ~2 seconds have
>>> passed between the last read of the nic clock and the timestamping
>>> application of the received packet.
>>>
>>> Signed-off-by: John Fraker <jfraker@google.com>
>>> Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
>>> Reviewed-by: Willem de Bruijn <willemb@google.com>
>>> Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
>>> ---
>>>    Changes in v2:
>>>    - Add the missing READ_ONCE (Joe Damato)
>>> ---
>>>    drivers/net/ethernet/google/gve/gve_rx_dqo.c | 23 ++++++++++++++++++++
>>>    1 file changed, 23 insertions(+)
>>>
>>> diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
>>> index dcb0545baa50..c03c3741e0d4 100644
>>> --- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
>>> +++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
>>> @@ -437,6 +437,29 @@ static void gve_rx_skb_hash(struct sk_buff *skb,
>>>        skb_set_hash(skb, le32_to_cpu(compl_desc->hash), hash_type);
>>>    }
>>>
>>> +/* Expand the hardware timestamp to the full 64 bits of width, and add it to the
>>> + * skb.
>>> + *
>>> + * This algorithm works by using the passed hardware timestamp to generate a
>>> + * diff relative to the last read of the nic clock. This diff can be positive or
>>> + * negative, as it is possible that we have read the clock more recently than
>>> + * the hardware has received this packet. To detect this, we use the high bit of
>>> + * the diff, and assume that the read is more recent if the high bit is set. In
>>> + * this case we invert the process.
>>> + *
>>> + * Note that this means if the time delta between packet reception and the last
>>> + * clock read is greater than ~2 seconds, this will provide invalid results.
>>> + */
>>> +static void __maybe_unused gve_rx_skb_hwtstamp(struct gve_rx_ring *rx, u32 hwts)
>>> +{
>>> +     s64 last_read = READ_ONCE(rx->gve->last_sync_nic_counter);
>>
>> I believe last_read should be u64 as last_sync_nic_counter is u64 and
>> ns_to_ktime expects u64.
>>
> Thanks for the suggestion. The reason to choose s64 for `last_read`
> here is to use signed addition explicitly with `last_read +
> (s32)diff`. This allows diff (which can be positive or negative,
> depending on whether hwts is ahead of or behind low(last_read)) to
> directly adjust last_read without a conditional branch, which makes
> the intent clear IMO. The s64 nanosecond value is not at risk of
> overflow, and the positive s64 result is then safely converted to u64
> for ns_to_ktime.
> 
> I'm happy to change last_read to u64 if that's preferred for type
> consistency, or I can add a comment to clarify the rationale for the
> current s64 approach. Please let me know what you think. Thanks!

I didn't get where is the conditional branch expected? AFAIU, you can do
direct addition u64 + s32 without any branches. The assembly is also pretty
clean in this case (used simplified piece of code):

         movl    -12(%rbp), %eax
         movslq  %eax, %rdx
         movq    -8(%rbp), %rax
         addq    %rax, %rdx


> 
>>> +     struct sk_buff *skb = rx->ctx.skb_head;
>>> +     u32 low = (u32)last_read;
>>> +     s32 diff = hwts - low;
>>> +
>>> +     skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(last_read + diff);
>>> +}
>>> +
>>>    static void gve_rx_free_skb(struct napi_struct *napi, struct gve_rx_ring *rx)
>>>    {
>>>        if (!rx->ctx.skb_head)
>>


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next v2 6/8] gve: Add rx hardware timestamp expansion
  2025-05-20 19:53       ` Vadim Fedorenko
@ 2025-05-21  5:22         ` Ziwei Xiao
  0 siblings, 0 replies; 15+ messages in thread
From: Ziwei Xiao @ 2025-05-21  5:22 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Harshitha Ramamurthy, netdev, davem, edumazet, kuba, pabeni,
	jeroendb, andrew+netdev, willemb, pkaligineedi, yyd, joshwash,
	shailend, linux, thostet, jfraker, richardcochran, jdamato, horms,
	linux-kernel

On Tue, May 20, 2025 at 12:53 PM Vadim Fedorenko
<vadim.fedorenko@linux.dev> wrote:
>
> On 19.05.2025 19:45, Ziwei Xiao wrote:
> > .
> >
> >
> > On Sun, May 18, 2025 at 2:45 PM Vadim Fedorenko
> > <vadim.fedorenko@linux.dev> wrote:
> >>
> >> On 17.05.2025 01:11, Harshitha Ramamurthy wrote:
> >>> From: John Fraker <jfraker@google.com>
> >>>
> >>> Allow the rx path to recover the high 32 bits of the full 64 bit rx
> >>> timestamp.
> >>>
> >>> Use the low 32 bits of the last synced nic time and the 32 bits of the
> >>> timestamp provided in the rx descriptor to generate a difference, which
> >>> is then applied to the last synced nic time to reconstruct the complete
> >>> 64-bit timestamp.
> >>>
> >>> This scheme remains accurate as long as no more than ~2 seconds have
> >>> passed between the last read of the nic clock and the timestamping
> >>> application of the received packet.
> >>>
> >>> Signed-off-by: John Fraker <jfraker@google.com>
> >>> Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
> >>> Reviewed-by: Willem de Bruijn <willemb@google.com>
> >>> Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
> >>> ---
> >>>    Changes in v2:
> >>>    - Add the missing READ_ONCE (Joe Damato)
> >>> ---
> >>>    drivers/net/ethernet/google/gve/gve_rx_dqo.c | 23 ++++++++++++++++++++
> >>>    1 file changed, 23 insertions(+)
> >>>
> >>> diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
> >>> index dcb0545baa50..c03c3741e0d4 100644
> >>> --- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
> >>> +++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
> >>> @@ -437,6 +437,29 @@ static void gve_rx_skb_hash(struct sk_buff *skb,
> >>>        skb_set_hash(skb, le32_to_cpu(compl_desc->hash), hash_type);
> >>>    }
> >>>
> >>> +/* Expand the hardware timestamp to the full 64 bits of width, and add it to the
> >>> + * skb.
> >>> + *
> >>> + * This algorithm works by using the passed hardware timestamp to generate a
> >>> + * diff relative to the last read of the nic clock. This diff can be positive or
> >>> + * negative, as it is possible that we have read the clock more recently than
> >>> + * the hardware has received this packet. To detect this, we use the high bit of
> >>> + * the diff, and assume that the read is more recent if the high bit is set. In
> >>> + * this case we invert the process.
> >>> + *
> >>> + * Note that this means if the time delta between packet reception and the last
> >>> + * clock read is greater than ~2 seconds, this will provide invalid results.
> >>> + */
> >>> +static void __maybe_unused gve_rx_skb_hwtstamp(struct gve_rx_ring *rx, u32 hwts)
> >>> +{
> >>> +     s64 last_read = READ_ONCE(rx->gve->last_sync_nic_counter);
> >>
> >> I believe last_read should be u64 as last_sync_nic_counter is u64 and
> >> ns_to_ktime expects u64.
> >>
> > Thanks for the suggestion. The reason to choose s64 for `last_read`
> > here is to use signed addition explicitly with `last_read +
> > (s32)diff`. This allows diff (which can be positive or negative,
> > depending on whether hwts is ahead of or behind low(last_read)) to
> > directly adjust last_read without a conditional branch, which makes
> > the intent clear IMO. The s64 nanosecond value is not at risk of
> > overflow, and the positive s64 result is then safely converted to u64
> > for ns_to_ktime.
> >
> > I'm happy to change last_read to u64 if that's preferred for type
> > consistency, or I can add a comment to clarify the rationale for the
> > current s64 approach. Please let me know what you think. Thanks!
>
> I didn't get where is the conditional branch expected? AFAIU, you can do
> direct addition u64 + s32 without any branches. The assembly is also pretty
> clean in this case (used simplified piece of code):
>
>          movl    -12(%rbp), %eax
>          movslq  %eax, %rdx
>          movq    -8(%rbp), %rax
>          addq    %rax, %rdx
>
>
Thanks for the analysis. I will update it and send in the v3 series.
> >
> >>> +     struct sk_buff *skb = rx->ctx.skb_head;
> >>> +     u32 low = (u32)last_read;
> >>> +     s32 diff = hwts - low;
> >>> +
> >>> +     skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(last_read + diff);
> >>> +}
> >>> +
> >>>    static void gve_rx_free_skb(struct napi_struct *napi, struct gve_rx_ring *rx)
> >>>    {
> >>>        if (!rx->ctx.skb_head)
> >>
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2025-05-21  5:22 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-17  0:11 [PATCH net-next v2 0/8] gve: Add Rx HW timestamping support Harshitha Ramamurthy
2025-05-17  0:11 ` [PATCH net-next v2 1/8] gve: Add device option for nic clock synchronization Harshitha Ramamurthy
2025-05-17  0:11 ` [PATCH net-next v2 2/8] gve: Add adminq command to report nic timestamp Harshitha Ramamurthy
2025-05-17  0:11 ` [PATCH net-next v2 3/8] gve: Add initial PTP device support Harshitha Ramamurthy
2025-05-17  0:11 ` [PATCH net-next v2 4/8] gve: Add adminq lock for queues creation and destruction Harshitha Ramamurthy
2025-05-17  0:11 ` [PATCH net-next v2 5/8] gve: Add support to query the nic clock Harshitha Ramamurthy
2025-05-17  0:11 ` [PATCH net-next v2 6/8] gve: Add rx hardware timestamp expansion Harshitha Ramamurthy
2025-05-18 21:45   ` Vadim Fedorenko
2025-05-19 18:45     ` Ziwei Xiao
2025-05-20 19:53       ` Vadim Fedorenko
2025-05-21  5:22         ` Ziwei Xiao
2025-05-17  0:11 ` [PATCH net-next v2 7/8] gve: Add support for SIOC[GS]HWTSTAMP IOCTLs Harshitha Ramamurthy
2025-05-17  1:52   ` Jakub Kicinski
2025-05-19 18:32     ` Ziwei Xiao
2025-05-17  0:11 ` [PATCH net-next v2 8/8] gve: Advertise support for rx hardware timestamping Harshitha Ramamurthy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).