diff options
author | Carolina Jubran <cjubran@nvidia.com> | 2025-09-24 12:40:35 +0000 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2025-09-26 16:49:24 -0700 |
commit | 44907e7c8fd0dec2d17ba8011bb7da443a9e4585 (patch) | |
tree | c01026125aa5dd8d05607d07c5b4aa1ff9a7d94f /drivers/net | |
parent | 6b81b8a0b1978284e007566d7a1607b47f92209f (diff) |
net/mlx5e: Add logic to read RS-FEC histogram bin ranges from PPHCR
Introduce support for querying the Ports Phy Histogram Configuration
Register (PPHCR) to retrieve RS-FEC histogram bin ranges. The ranges
are stored in a static array and will be used to map histogram counters
to error levels.
The actual RS-FEC histogram statistics are not yet reported in this
commit and will be handled in a downstream patch.
Co-developed-by: Yael Chemla <ychemla@nvidia.com>
Signed-off-by: Yael Chemla <ychemla@nvidia.com>
Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Reviewed-by: Yael Chemla <ychemla@nvidia.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Link: https://patch.msgid.link/20250924124037.1508846-4-vadim.fedorenko@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net')
5 files changed, 94 insertions, 3 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 4ffbc263d60f..14e3207b14e7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -956,6 +956,7 @@ struct mlx5e_priv { struct mlx5e_mqprio_rl *mqprio_rl; struct dentry *dfs_root; struct mlx5_devcom_comp_dev *devcom; + struct ethtool_fec_hist_range *fec_ranges; }; struct mlx5e_dev { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index bcc3bbb78cc9..fd45384a855b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -1932,7 +1932,7 @@ static void mlx5e_get_fec_stats(struct net_device *netdev, { struct mlx5e_priv *priv = netdev_priv(netdev); - mlx5e_stats_fec_get(priv, fec_stats); + mlx5e_stats_fec_get(priv, fec_stats, hist); } static int mlx5e_get_fecparam(struct net_device *netdev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 5e007bb3bad1..0c79c42ae538 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -6279,8 +6279,15 @@ int mlx5e_priv_init(struct mlx5e_priv *priv, if (!priv->channel_stats) goto err_free_tx_rates; + priv->fec_ranges = kcalloc(ETHTOOL_FEC_HIST_MAX, + sizeof(*priv->fec_ranges), GFP_KERNEL); + if (!priv->fec_ranges) + goto err_free_channel_stats; + return 0; +err_free_channel_stats: + kfree(priv->channel_stats); err_free_tx_rates: kfree(priv->tx_rates); err_free_txq2sq_stats: @@ -6304,6 +6311,7 @@ void mlx5e_priv_cleanup(struct mlx5e_priv *priv) if (!priv->mdev) return; + kfree(priv->fec_ranges); for (i = 0; i < priv->stats_nch; i++) kvfree(priv->channel_stats[i]); kfree(priv->channel_stats); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index 9c45c6e670eb..f1887b9afa3d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -1491,8 +1491,88 @@ static void fec_set_corrected_bits_total(struct mlx5e_priv *priv, phy_corrected_bits); } +#define MLX5_RS_HISTOGRAM_ENTRIES \ + (MLX5_FLD_SZ_BYTES(rs_histogram_cntrs, hist) / \ + MLX5_FLD_SZ_BYTES(rs_histogram_cntrs, hist[0])) + +enum { + MLX5E_HISTOGRAM_FEC_RS_544_514 = 1, + MLX5E_HISTOGRAM_FEC_LLRS = 2, + MLX5E_HISTOGRAM_FEC_RS_528_514 = 3, +}; + +static bool fec_rs_validate_hist_type(int mode, int hist_type) +{ + switch (mode) { + case MLX5E_FEC_RS_528_514: + return hist_type == MLX5E_HISTOGRAM_FEC_RS_528_514; + case MLX5E_FEC_RS_544_514_INTERLEAVED_QUAD: + case MLX5E_FEC_RS_544_514: + return hist_type == MLX5E_HISTOGRAM_FEC_RS_544_514; + case MLX5E_FEC_LLRS_272_257_1: + return hist_type == MLX5E_HISTOGRAM_FEC_LLRS; + default: + break; + } + + return false; +} + +static u8 +fec_rs_histogram_fill_ranges(struct mlx5e_priv *priv, int mode, + const struct ethtool_fec_hist_range **ranges) +{ + struct mlx5_core_dev *mdev = priv->mdev; + u32 out[MLX5_ST_SZ_DW(pphcr_reg)] = {0}; + u32 in[MLX5_ST_SZ_DW(pphcr_reg)] = {0}; + int sz = MLX5_ST_SZ_BYTES(pphcr_reg); + u8 hist_type, num_of_bins; + + memset(priv->fec_ranges, 0, + ETHTOOL_FEC_HIST_MAX * sizeof(*priv->fec_ranges)); + MLX5_SET(pphcr_reg, in, local_port, 1); + if (mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPHCR, 0, 0)) + return 0; + + hist_type = MLX5_GET(pphcr_reg, out, active_hist_type); + if (!fec_rs_validate_hist_type(mode, hist_type)) + return 0; + + num_of_bins = MLX5_GET(pphcr_reg, out, num_of_bins); + if (WARN_ON_ONCE(num_of_bins > MLX5_RS_HISTOGRAM_ENTRIES)) + return 0; + + for (int i = 0; i < num_of_bins; i++) { + void *bin_range = MLX5_ADDR_OF(pphcr_reg, out, bin_range[i]); + + priv->fec_ranges[i].high = MLX5_GET(bin_range_layout, bin_range, + high_val); + priv->fec_ranges[i].low = MLX5_GET(bin_range_layout, bin_range, + low_val); + } + *ranges = priv->fec_ranges; + + return num_of_bins; +} + +static void fec_set_histograms_stats(struct mlx5e_priv *priv, int mode, + struct ethtool_fec_hist *hist) +{ + switch (mode) { + case MLX5E_FEC_RS_528_514: + case MLX5E_FEC_RS_544_514: + case MLX5E_FEC_LLRS_272_257_1: + case MLX5E_FEC_RS_544_514_INTERLEAVED_QUAD: + fec_rs_histogram_fill_ranges(priv, mode, &hist->ranges); + break; + default: + return; + } +} + void mlx5e_stats_fec_get(struct mlx5e_priv *priv, - struct ethtool_fec_stats *fec_stats) + struct ethtool_fec_stats *fec_stats, + struct ethtool_fec_hist *hist) { int mode = fec_active_mode(priv->mdev); @@ -1502,6 +1582,7 @@ void mlx5e_stats_fec_get(struct mlx5e_priv *priv, fec_set_corrected_bits_total(priv, fec_stats); fec_set_block_stats(priv, mode, fec_stats); + fec_set_histograms_stats(priv, mode, hist); } #define PPORT_ETH_EXT_OFF(c) \ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 72dbcc1928ef..09f155acb461 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -117,7 +117,8 @@ void mlx5e_stats_update_ndo_stats(struct mlx5e_priv *priv); void mlx5e_stats_pause_get(struct mlx5e_priv *priv, struct ethtool_pause_stats *pause_stats); void mlx5e_stats_fec_get(struct mlx5e_priv *priv, - struct ethtool_fec_stats *fec_stats); + struct ethtool_fec_stats *fec_stats, + struct ethtool_fec_hist *hist); void mlx5e_stats_eth_phy_get(struct mlx5e_priv *priv, struct ethtool_eth_phy_stats *phy_stats); |