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