mlxbf_gige: add support to display pause frame counters
authorDavid Thompson <davthompson@nvidia.com>
Tue, 5 Mar 2024 21:21:37 +0000 (16:21 -0500)
committerJakub Kicinski <kuba@kernel.org>
Thu, 7 Mar 2024 04:39:58 +0000 (20:39 -0800)
This patch updates the mlxbf_gige driver to support the
"get_pause_stats()" callback, which enables display of
pause frame counters via "ethtool -I -a oob_net0".

The pause frame counters are only enabled if the "counters_en"
bit is asserted in the LLU general config register. The driver
will only report stats, and thus overwrite the default stats
state of ETHTOOL_STAT_NOT_SET, if "counters_en" is asserted.

Reviewed-by: Asmaa Mnebhi <asmaa@nvidia.com>
Signed-off-by: David Thompson <davthompson@nvidia.com>
Link: https://lore.kernel.org/r/20240305212137.3525-1-davthompson@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h

index 253d7ad9b80954012970b86df725aba43c87a1b2..8b63968bbee9851a6ebd5d24fa738c220972f2ce 100644 (file)
@@ -124,6 +124,41 @@ static void mlxbf_gige_get_pauseparam(struct net_device *netdev,
        pause->tx_pause = 1;
 }
 
+static bool mlxbf_gige_llu_counters_enabled(struct mlxbf_gige *priv)
+{
+       u32 data;
+
+       if (priv->hw_version == MLXBF_GIGE_VERSION_BF2) {
+               data = readl(priv->llu_base + MLXBF_GIGE_BF2_LLU_GENERAL_CONFIG);
+               if (data & MLXBF_GIGE_BF2_LLU_COUNTERS_EN)
+                       return true;
+       } else {
+               data = readl(priv->llu_base + MLXBF_GIGE_BF3_LLU_GENERAL_CONFIG);
+               if (data & MLXBF_GIGE_BF3_LLU_COUNTERS_EN)
+                       return true;
+       }
+
+       return false;
+}
+
+static void mlxbf_gige_get_pause_stats(struct net_device *netdev,
+                                      struct ethtool_pause_stats *pause_stats)
+{
+       struct mlxbf_gige *priv = netdev_priv(netdev);
+       u64 data_lo, data_hi;
+
+       /* Read LLU counters to provide stats only if counters are enabled */
+       if (mlxbf_gige_llu_counters_enabled(priv)) {
+               data_lo = readl(priv->llu_base + MLXBF_GIGE_TX_PAUSE_CNT_LO);
+               data_hi = readl(priv->llu_base + MLXBF_GIGE_TX_PAUSE_CNT_HI);
+               pause_stats->tx_pause_frames = (data_hi << 32) | data_lo;
+
+               data_lo = readl(priv->llu_base + MLXBF_GIGE_RX_PAUSE_CNT_LO);
+               data_hi = readl(priv->llu_base + MLXBF_GIGE_RX_PAUSE_CNT_HI);
+               pause_stats->rx_pause_frames = (data_hi << 32) | data_lo;
+       }
+}
+
 const struct ethtool_ops mlxbf_gige_ethtool_ops = {
        .get_link               = ethtool_op_get_link,
        .get_ringparam          = mlxbf_gige_get_ringparam,
@@ -134,6 +169,7 @@ const struct ethtool_ops mlxbf_gige_ethtool_ops = {
        .get_ethtool_stats      = mlxbf_gige_get_ethtool_stats,
        .nway_reset             = phy_ethtool_nway_reset,
        .get_pauseparam         = mlxbf_gige_get_pauseparam,
+       .get_pause_stats        = mlxbf_gige_get_pause_stats,
        .get_link_ksettings     = phy_ethtool_get_link_ksettings,
        .set_link_ksettings     = phy_ethtool_set_link_ksettings,
 };
index cd0973229c9bb98eb217a3581c0214c7fed99c20..98a8681c21b9ca8dedf0884435608de55b5feda7 100644 (file)
 #define MLXBF_GIGE_100M_IPG_SIZE                      119
 #define MLXBF_GIGE_10M_IPG_SIZE                       1199
 
+/* Offsets into OOB LLU block for pause frame counters */
+#define MLXBF_GIGE_BF2_TX_PAUSE_CNT_HI                0x33d8
+#define MLXBF_GIGE_BF2_TX_PAUSE_CNT_LO                0x33dc
+#define MLXBF_GIGE_BF2_RX_PAUSE_CNT_HI                0x3210
+#define MLXBF_GIGE_BF2_RX_PAUSE_CNT_LO                0x3214
+
+#define MLXBF_GIGE_BF3_TX_PAUSE_CNT_HI                0x3a88
+#define MLXBF_GIGE_BF3_TX_PAUSE_CNT_LO                0x3a8c
+#define MLXBF_GIGE_BF3_RX_PAUSE_CNT_HI                0x38c0
+#define MLXBF_GIGE_BF3_RX_PAUSE_CNT_LO                0x38c4
+
+#define MLXBF_GIGE_TX_PAUSE_CNT_HI ((priv->hw_version == MLXBF_GIGE_VERSION_BF2) ? \
+                                   MLXBF_GIGE_BF2_TX_PAUSE_CNT_HI :    \
+                                   MLXBF_GIGE_BF3_TX_PAUSE_CNT_HI)
+#define MLXBF_GIGE_TX_PAUSE_CNT_LO ((priv->hw_version == MLXBF_GIGE_VERSION_BF2) ? \
+                                   MLXBF_GIGE_BF2_TX_PAUSE_CNT_LO : \
+                                   MLXBF_GIGE_BF3_TX_PAUSE_CNT_LO)
+#define MLXBF_GIGE_RX_PAUSE_CNT_HI ((priv->hw_version == MLXBF_GIGE_VERSION_BF2) ? \
+                                   MLXBF_GIGE_BF2_RX_PAUSE_CNT_HI : \
+                                   MLXBF_GIGE_BF3_RX_PAUSE_CNT_HI)
+#define MLXBF_GIGE_RX_PAUSE_CNT_LO ((priv->hw_version == MLXBF_GIGE_VERSION_BF2) ? \
+                                   MLXBF_GIGE_BF2_RX_PAUSE_CNT_LO : \
+                                   MLXBF_GIGE_BF3_RX_PAUSE_CNT_LO)
+
+#define MLXBF_GIGE_BF2_LLU_GENERAL_CONFIG             0x2110
+#define MLXBF_GIGE_BF3_LLU_GENERAL_CONFIG             0x2030
+
+#define MLXBF_GIGE_BF2_LLU_COUNTERS_EN                BIT(0)
+#define MLXBF_GIGE_BF3_LLU_COUNTERS_EN                BIT(4)
+
 #endif /* !defined(__MLXBF_GIGE_REGS_H__) */