diff mbox series

[RFC,net-next,v1,4/6] net/mlx5e: Implement ethtool hardware timestamping statistics

Message ID 20240223192658.45893-5-rrameshbabu@nvidia.com (mailing list archive)
State RFC
Delegated to: Netdev Maintainers
Headers show
Series ethtool HW timestamping statistics | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 941 this patch: 941
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers warning 2 maintainers not CCed: saeedm@nvidia.com linux-rdma@vger.kernel.org
netdev/build_clang success Errors and warnings before: 957 this patch: 957
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 958 this patch: 958
netdev/checkpatch warning WARNING: line length of 82 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Rahul Rameshbabu Feb. 23, 2024, 7:24 p.m. UTC
Feed driver statistics counters related to hardware timestamping to
standardized ethtool hardware timestamping statistics group.

Signed-off-by: Rahul Rameshbabu <rrameshbabu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
---
 .../ethernet/mellanox/mlx5/core/en_ethtool.c  |  9 +++
 .../ethernet/mellanox/mlx5/core/en_stats.c    | 68 +++++++++++++++++++
 .../ethernet/mellanox/mlx5/core/en_stats.h    |  2 +
 3 files changed, 79 insertions(+)

Comments

Kory Maincent Feb. 26, 2024, 9:26 a.m. UTC | #1
On Fri, 23 Feb 2024 11:24:48 -0800
Rahul Rameshbabu <rrameshbabu@nvidia.com> wrote:

> Feed driver statistics counters related to hardware timestamping to
> standardized ethtool hardware timestamping statistics group.
> 
> Signed-off-by: Rahul Rameshbabu <rrameshbabu@nvidia.com>
> Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>

> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index
> bc31196d348a..836198445726 100644 ---
> a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++
> b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -1155,6 +1155,74 @@
> void mlx5e_stats_rmon_get(struct mlx5e_priv *priv, *ranges =
> mlx5e_rmon_ranges; }
>  
> +void mlx5e_stats_ts_get(struct mlx5e_priv *priv,
> +			struct ethtool_ts_stats *ts_stats)
> +{
> +	enum ethtool_ts_stats_layer layer;
> +	struct mlx5e_ptp *ptp;
> +	bool tx_ptp_opened;
> +	int i, j;
> +
> +	mutex_lock(&priv->state_lock);
> +
> +	tx_ptp_opened = priv->tx_ptp_opened;
> +
> +	/* NOTE: this needs to be changed whenever ethtool timestamping
> +	 * layer selection is implemented.
> +	 */
> +	if (ts_stats->layer == ETHTOOL_TS_STATS_LAYER_ACTIVE)
> +		layer = tx_ptp_opened ? ETHTOOL_TS_STATS_LAYER_PHY :
> +					ETHTOOL_TS_STATS_LAYER_DMA;
> +	else
> +		layer = ts_stats->layer;
> +
> +	switch (layer) {
> +	case ETHTOOL_TS_STATS_LAYER_PHY:
> +		if (!tx_ptp_opened)
> +			return;
> +
> +		ptp = priv->channels.ptp;
> +
> +		ts_stats->pkts = 0;
> +		ts_stats->err = 0;
> +		ts_stats->late = 0;
> +		ts_stats->lost = 0;
> +
> +		/* Aggregate stats across all TCs */
> +		for (i = 0; i < ptp->num_tc; i++) {
> +			struct mlx5e_ptp_cq_stats *stats =
> ptp->ptpsq[i].cq_stats; +
> +			ts_stats->pkts += stats->cqe;
> +			ts_stats->err += stats->abort + stats->err_cqe;
> +			ts_stats->late += stats->late_cqe;
> +			ts_stats->lost += stats->lost_cqe;
> +		}
> +		break;
> +	case ETHTOOL_TS_STATS_LAYER_DMA:
> +		/* DMA layer will always successfully timestamp packets.
> Other
> +		 * counters do not make sense for this layer.
> +		 */
> +		ts_stats->pkts = 0;
> +
> +		/* Aggregate stats across all SQs */
> +		mutex_lock(&priv->state_lock);
> +		for (j = 0; j < priv->channels.num; j++) {
> +			struct mlx5e_channel *c = priv->channels.c[j];
> +
> +			for (i = 0; i < c->num_tc; i++) {
> +				struct mlx5e_sq_stats *stats =
> c->sq[i].stats; +
> +				ts_stats->pkts += stats->timestamps;
> +			}
> +		}
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	mutex_unlock(&priv->state_lock);
> +}
> +

To follow the same logic as my patch series you should use phc qualifier instead
of the layer. See patch 9 of my series.
With HWTSTAMP_PROVIDER_QUALIFIER_PRECISE for the IEEE 1588 which mean the PHY
layer on your case and HWTSTAMP_PROVIDER_QUALIFIER_APPROX for the DMA layer.

Even if the timestamp is made physically on the PHY, this driver does not
register any phy device. The NIC manages all the network architecture by
itself. We decided to use the phc qualifier to fit this use case.

The layer description should only be used internally in the kernel when we are
registering a PHY device and using the phy tsinfo/hwtstamp/rxtstamp/tstsamp
callbacks.

Regards,
diff mbox series

Patch

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index cc51ce16df14..d3b77054c30a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -2381,6 +2381,14 @@  static void mlx5e_get_rmon_stats(struct net_device *netdev,
 	mlx5e_stats_rmon_get(priv, rmon_stats, ranges);
 }
 
+static void mlx5e_get_ts_stats(struct net_device *netdev,
+			       struct ethtool_ts_stats *ts_stats)
+{
+	struct mlx5e_priv *priv = netdev_priv(netdev);
+
+	mlx5e_stats_ts_get(priv, ts_stats);
+}
+
 const struct ethtool_ops mlx5e_ethtool_ops = {
 	.cap_rss_ctx_supported	= true,
 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
@@ -2430,5 +2438,6 @@  const struct ethtool_ops mlx5e_ethtool_ops = {
 	.get_eth_mac_stats = mlx5e_get_eth_mac_stats,
 	.get_eth_ctrl_stats = mlx5e_get_eth_ctrl_stats,
 	.get_rmon_stats    = mlx5e_get_rmon_stats,
+	.get_ts_stats      = mlx5e_get_ts_stats,
 	.get_link_ext_stats = mlx5e_get_link_ext_stats
 };
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
index bc31196d348a..836198445726 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
@@ -1155,6 +1155,74 @@  void mlx5e_stats_rmon_get(struct mlx5e_priv *priv,
 	*ranges = mlx5e_rmon_ranges;
 }
 
+void mlx5e_stats_ts_get(struct mlx5e_priv *priv,
+			struct ethtool_ts_stats *ts_stats)
+{
+	enum ethtool_ts_stats_layer layer;
+	struct mlx5e_ptp *ptp;
+	bool tx_ptp_opened;
+	int i, j;
+
+	mutex_lock(&priv->state_lock);
+
+	tx_ptp_opened = priv->tx_ptp_opened;
+
+	/* NOTE: this needs to be changed whenever ethtool timestamping
+	 * layer selection is implemented.
+	 */
+	if (ts_stats->layer == ETHTOOL_TS_STATS_LAYER_ACTIVE)
+		layer = tx_ptp_opened ? ETHTOOL_TS_STATS_LAYER_PHY :
+					ETHTOOL_TS_STATS_LAYER_DMA;
+	else
+		layer = ts_stats->layer;
+
+	switch (layer) {
+	case ETHTOOL_TS_STATS_LAYER_PHY:
+		if (!tx_ptp_opened)
+			return;
+
+		ptp = priv->channels.ptp;
+
+		ts_stats->pkts = 0;
+		ts_stats->err = 0;
+		ts_stats->late = 0;
+		ts_stats->lost = 0;
+
+		/* Aggregate stats across all TCs */
+		for (i = 0; i < ptp->num_tc; i++) {
+			struct mlx5e_ptp_cq_stats *stats = ptp->ptpsq[i].cq_stats;
+
+			ts_stats->pkts += stats->cqe;
+			ts_stats->err += stats->abort + stats->err_cqe;
+			ts_stats->late += stats->late_cqe;
+			ts_stats->lost += stats->lost_cqe;
+		}
+		break;
+	case ETHTOOL_TS_STATS_LAYER_DMA:
+		/* DMA layer will always successfully timestamp packets. Other
+		 * counters do not make sense for this layer.
+		 */
+		ts_stats->pkts = 0;
+
+		/* Aggregate stats across all SQs */
+		mutex_lock(&priv->state_lock);
+		for (j = 0; j < priv->channels.num; j++) {
+			struct mlx5e_channel *c = priv->channels.c[j];
+
+			for (i = 0; i < c->num_tc; i++) {
+				struct mlx5e_sq_stats *stats = c->sq[i].stats;
+
+				ts_stats->pkts += stats->timestamps;
+			}
+		}
+		break;
+	default:
+		break;
+	}
+
+	mutex_unlock(&priv->state_lock);
+}
+
 #define PPORT_PHY_STATISTICAL_OFF(c) \
 	MLX5_BYTE_OFF(ppcnt_reg, \
 		      counter_set.phys_layer_statistical_cntrs.c##_high)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
index 3c634c5fd420..7b3e6cf1229a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
@@ -126,6 +126,8 @@  void mlx5e_stats_eth_ctrl_get(struct mlx5e_priv *priv,
 void mlx5e_stats_rmon_get(struct mlx5e_priv *priv,
 			  struct ethtool_rmon_stats *rmon,
 			  const struct ethtool_rmon_hist_range **ranges);
+void mlx5e_stats_ts_get(struct mlx5e_priv *priv,
+			struct ethtool_ts_stats *ts_stats);
 void mlx5e_get_link_ext_stats(struct net_device *dev,
 			      struct ethtool_link_ext_stats *stats);