mlx5: implement ethtool::get_fec_stats
authorJakub Kicinski <kuba@kernel.org>
Thu, 15 Apr 2021 22:53:18 +0000 (15:53 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 16 Apr 2021 00:08:29 +0000 (17:08 -0700)
Report corrected bits.

v2: catch reg access errors (Saeed)

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Acked-by: Saeed Mahameed <saeedm@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.h

index c8057a4..f17690c 100644 (file)
@@ -1602,6 +1602,14 @@ static int mlx5e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        return mlx5_set_port_wol(mdev, mlx5_wol_mode);
 }
 
+static void mlx5e_get_fec_stats(struct net_device *netdev,
+                               struct ethtool_fec_stats *fec_stats)
+{
+       struct mlx5e_priv *priv = netdev_priv(netdev);
+
+       mlx5e_stats_fec_get(priv, fec_stats);
+}
+
 static int mlx5e_get_fecparam(struct net_device *netdev,
                              struct ethtool_fecparam *fecparam)
 {
@@ -2209,6 +2217,7 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
        .self_test         = mlx5e_self_test,
        .get_msglevel      = mlx5e_get_msglevel,
        .set_msglevel      = mlx5e_set_msglevel,
+       .get_fec_stats     = mlx5e_get_fec_stats,
        .get_fecparam      = mlx5e_get_fecparam,
        .set_fecparam      = mlx5e_set_fecparam,
 };
index ae0570e..353513b 100644 (file)
@@ -768,10 +768,10 @@ static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(802_3)
        mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0);
 }
 
-#define MLX5E_READ_CTR64_BE_F(ptr, c)                  \
+#define MLX5E_READ_CTR64_BE_F(ptr, set, c)             \
        be64_to_cpu(*(__be64 *)((char *)ptr +           \
                MLX5_BYTE_OFF(ppcnt_reg,                \
-                       counter_set.eth_802_3_cntrs_grp_data_layout.c##_high)))
+                             counter_set.set.c##_high)))
 
 void mlx5e_stats_pause_get(struct mlx5e_priv *priv,
                           struct ethtool_pause_stats *pause_stats)
@@ -791,9 +791,11 @@ void mlx5e_stats_pause_get(struct mlx5e_priv *priv,
 
        pause_stats->tx_pause_frames =
                MLX5E_READ_CTR64_BE_F(ppcnt_ieee_802_3,
+                                     eth_802_3_cntrs_grp_data_layout,
                                      a_pause_mac_ctrl_frames_transmitted);
        pause_stats->rx_pause_frames =
                MLX5E_READ_CTR64_BE_F(ppcnt_ieee_802_3,
+                                     eth_802_3_cntrs_grp_data_layout,
                                      a_pause_mac_ctrl_frames_received);
 }
 
@@ -1015,6 +1017,29 @@ static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(phy)
        mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0);
 }
 
+void mlx5e_stats_fec_get(struct mlx5e_priv *priv,
+                        struct ethtool_fec_stats *fec_stats)
+{
+       u32 ppcnt_phy_statistical[MLX5_ST_SZ_DW(ppcnt_reg)];
+       struct mlx5_core_dev *mdev = priv->mdev;
+       u32 in[MLX5_ST_SZ_DW(ppcnt_reg)] = {0};
+       int sz = MLX5_ST_SZ_BYTES(ppcnt_reg);
+
+       if (!MLX5_CAP_PCAM_FEATURE(mdev, ppcnt_statistical_group))
+               return;
+
+       MLX5_SET(ppcnt_reg, in, local_port, 1);
+       MLX5_SET(ppcnt_reg, in, grp, MLX5_PHYSICAL_LAYER_STATISTICAL_GROUP);
+       if (mlx5_core_access_reg(mdev, in, sz, ppcnt_phy_statistical,
+                                sz, MLX5_REG_PPCNT, 0, 0))
+               return;
+
+       fec_stats->corrected_bits.total =
+               MLX5E_READ_CTR64_BE_F(ppcnt_phy_statistical,
+                                     phys_layer_statistical_cntrs,
+                                     phy_corrected_bits);
+}
+
 #define PPORT_ETH_EXT_OFF(c) \
        MLX5_BYTE_OFF(ppcnt_reg, \
                      counter_set.eth_extended_cntrs_grp_data_layout.c##_high)
index 21d3b87..3f0789e 100644 (file)
@@ -114,6 +114,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);
 
 /* Concrete NIC Stats */