From: Vikas Gupta <vikas.gupta@broadcom.com>
To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
michael.chan@broadcom.com, pavan.chebbi@broadcom.com,
vsrama-krishna.nemani@broadcom.com,
rajashekar.hudumula@broadcom.com, ajit.khaparde@broadcom.com,
Bhargava Marreddy <bhargava.marreddy@broadcom.com>,
Vikas Gupta <vikas.gupta@broadcom.com>
Subject: [PATCH net-next v7 10/10] bng_en: add support for ethtool -S stats display
Date: Sun, 15 Mar 2026 19:46:05 +0530 [thread overview]
Message-ID: <20260315141605.410878-11-vikas.gupta@broadcom.com> (raw)
In-Reply-To: <20260315141605.410878-1-vikas.gupta@broadcom.com>
From: Bhargava Marreddy <bhargava.marreddy@broadcom.com>
Implement the legacy ethtool statistics interface (get_sset_count,
get_strings, get_ethtool_stats) to expose hardware counters not
available through standard kernel stats APIs.
Ex:
a) Per-queue ring stats
rxq0_ucast_packets: 2
rxq0_mcast_packets: 0
rxq0_bcast_packets: 15
rxq0_ucast_bytes: 120
rxq0_mcast_bytes: 0
rxq0_bcast_bytes: 900
txq0_ucast_packets: 0
txq0_mcast_packets: 0
txq0_bcast_packets: 0
txq0_ucast_bytes: 0
txq0_mcast_bytes: 0
txq0_bcast_bytes: 0
b) Per-queue TPA(LRO/GRO) stats
rxq4_tpa_eligible_pkt: 0
rxq4_tpa_eligible_bytes: 0
rxq4_tpa_pkt: 0
rxq4_tpa_bytes: 0
rxq4_tpa_errors: 0
rxq4_tpa_events: 0
c) Port level stats
rxp_good_vlan_frames: 0
rxp_mtu_err_frames: 0
rxp_tagged_frames: 0
rxp_double_tagged_frames: 0
rxp_pfc_ena_frames_pri0: 0
rxp_pfc_ena_frames_pri1: 0
rxp_pfc_ena_frames_pri2: 0
rxp_pfc_ena_frames_pri3: 0
rxp_pfc_ena_frames_pri4: 0
rxp_pfc_ena_frames_pri5: 0
rxp_pfc_ena_frames_pri6: 0
rxp_pfc_ena_frames_pri7: 0
rxp_eee_lpi_events: 0
rxp_eee_lpi_duration: 0
rxp_runt_bytes: 0
rxp_runt_frames: 0
txp_good_vlan_frames: 0
txp_jabber_frames: 0
txp_fcs_err_frames: 0
txp_pfc_ena_frames_pri0: 0
txp_pfc_ena_frames_pri1: 0
txp_pfc_ena_frames_pri2: 0
txp_pfc_ena_frames_pri3: 0
txp_pfc_ena_frames_pri4: 0
txp_pfc_ena_frames_pri5: 0
txp_pfc_ena_frames_pri6: 0
txp_pfc_ena_frames_pri7: 0
txp_eee_lpi_events: 0
txp_eee_lpi_duration: 0
txp_xthol_frames: 0
d) Per-priority stats
rx_bytes_pri0: 4182650
rx_bytes_pri1: 4182650
rx_bytes_pri2: 4182650
rx_bytes_pri3: 4182650
rx_bytes_pri4: 4182650
rx_bytes_pri5: 4182650
rx_bytes_pri6: 4182650
rx_bytes_pri7: 4182650
Signed-off-by: Bhargava Marreddy <bhargava.marreddy@broadcom.com>
Reviewed-by: Vikas Gupta <vikas.gupta@broadcom.com>
---
.../net/ethernet/broadcom/bnge/bnge_ethtool.c | 481 ++++++++++++++++++
1 file changed, 481 insertions(+)
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c b/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c
index 2ae13f18e2d7..1a0eb987ef6f 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c
@@ -31,6 +31,271 @@ static int bnge_nway_reset(struct net_device *dev)
return rc;
}
+static const char * const bnge_ring_q_stats_str[] = {
+ "ucast_packets",
+ "mcast_packets",
+ "bcast_packets",
+ "ucast_bytes",
+ "mcast_bytes",
+ "bcast_bytes",
+};
+
+static const char * const bnge_ring_tpa2_stats_str[] = {
+ "tpa_eligible_pkt",
+ "tpa_eligible_bytes",
+ "tpa_pkt",
+ "tpa_bytes",
+ "tpa_errors",
+ "tpa_events",
+};
+
+#define BNGE_RX_PORT_STATS_ENTRY(suffix) \
+ { BNGE_RX_STATS_OFFSET(rx_##suffix), "rxp_" __stringify(suffix) }
+
+#define BNGE_TX_PORT_STATS_ENTRY(suffix) \
+ { BNGE_TX_STATS_OFFSET(tx_##suffix), "txp_" __stringify(suffix) }
+
+#define BNGE_RX_STATS_EXT_ENTRY(counter) \
+ { BNGE_RX_STATS_EXT_OFFSET(counter), __stringify(counter) }
+
+#define BNGE_TX_STATS_EXT_ENTRY(counter) \
+ { BNGE_TX_STATS_EXT_OFFSET(counter), __stringify(counter) }
+
+#define BNGE_RX_STATS_EXT_PFC_ENTRY(n) \
+ BNGE_RX_STATS_EXT_ENTRY(pfc_pri##n##_rx_duration_us), \
+ BNGE_RX_STATS_EXT_ENTRY(pfc_pri##n##_rx_transitions)
+
+#define BNGE_TX_STATS_EXT_PFC_ENTRY(n) \
+ BNGE_TX_STATS_EXT_ENTRY(pfc_pri##n##_tx_duration_us), \
+ BNGE_TX_STATS_EXT_ENTRY(pfc_pri##n##_tx_transitions)
+
+#define BNGE_RX_STATS_EXT_PFC_ENTRIES \
+ BNGE_RX_STATS_EXT_PFC_ENTRY(0), \
+ BNGE_RX_STATS_EXT_PFC_ENTRY(1), \
+ BNGE_RX_STATS_EXT_PFC_ENTRY(2), \
+ BNGE_RX_STATS_EXT_PFC_ENTRY(3), \
+ BNGE_RX_STATS_EXT_PFC_ENTRY(4), \
+ BNGE_RX_STATS_EXT_PFC_ENTRY(5), \
+ BNGE_RX_STATS_EXT_PFC_ENTRY(6), \
+ BNGE_RX_STATS_EXT_PFC_ENTRY(7)
+
+#define BNGE_TX_STATS_EXT_PFC_ENTRIES \
+ BNGE_TX_STATS_EXT_PFC_ENTRY(0), \
+ BNGE_TX_STATS_EXT_PFC_ENTRY(1), \
+ BNGE_TX_STATS_EXT_PFC_ENTRY(2), \
+ BNGE_TX_STATS_EXT_PFC_ENTRY(3), \
+ BNGE_TX_STATS_EXT_PFC_ENTRY(4), \
+ BNGE_TX_STATS_EXT_PFC_ENTRY(5), \
+ BNGE_TX_STATS_EXT_PFC_ENTRY(6), \
+ BNGE_TX_STATS_EXT_PFC_ENTRY(7)
+
+#define BNGE_RX_STATS_EXT_COS_ENTRY(n) \
+ BNGE_RX_STATS_EXT_ENTRY(rx_bytes_cos##n), \
+ BNGE_RX_STATS_EXT_ENTRY(rx_packets_cos##n)
+
+#define BNGE_TX_STATS_EXT_COS_ENTRY(n) \
+ BNGE_TX_STATS_EXT_ENTRY(tx_bytes_cos##n), \
+ BNGE_TX_STATS_EXT_ENTRY(tx_packets_cos##n)
+
+#define BNGE_RX_STATS_EXT_COS_ENTRIES \
+ BNGE_RX_STATS_EXT_COS_ENTRY(0), \
+ BNGE_RX_STATS_EXT_COS_ENTRY(1), \
+ BNGE_RX_STATS_EXT_COS_ENTRY(2), \
+ BNGE_RX_STATS_EXT_COS_ENTRY(3), \
+ BNGE_RX_STATS_EXT_COS_ENTRY(4), \
+ BNGE_RX_STATS_EXT_COS_ENTRY(5), \
+ BNGE_RX_STATS_EXT_COS_ENTRY(6), \
+ BNGE_RX_STATS_EXT_COS_ENTRY(7) \
+
+#define BNGE_TX_STATS_EXT_COS_ENTRIES \
+ BNGE_TX_STATS_EXT_COS_ENTRY(0), \
+ BNGE_TX_STATS_EXT_COS_ENTRY(1), \
+ BNGE_TX_STATS_EXT_COS_ENTRY(2), \
+ BNGE_TX_STATS_EXT_COS_ENTRY(3), \
+ BNGE_TX_STATS_EXT_COS_ENTRY(4), \
+ BNGE_TX_STATS_EXT_COS_ENTRY(5), \
+ BNGE_TX_STATS_EXT_COS_ENTRY(6), \
+ BNGE_TX_STATS_EXT_COS_ENTRY(7) \
+
+#define BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(n) \
+ BNGE_RX_STATS_EXT_ENTRY(rx_discard_bytes_cos##n), \
+ BNGE_RX_STATS_EXT_ENTRY(rx_discard_packets_cos##n)
+
+#define BNGE_RX_STATS_EXT_DISCARD_COS_ENTRIES \
+ BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(0), \
+ BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(1), \
+ BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(2), \
+ BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(3), \
+ BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(4), \
+ BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(5), \
+ BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(6), \
+ BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(7)
+
+#define BNGE_RX_STATS_PRI_ENTRY(counter, n) \
+ { BNGE_RX_STATS_EXT_OFFSET(counter##_cos0), \
+ __stringify(counter##_pri##n) }
+
+#define BNGE_TX_STATS_PRI_ENTRY(counter, n) \
+ { BNGE_TX_STATS_EXT_OFFSET(counter##_cos0), \
+ __stringify(counter##_pri##n) }
+
+#define BNGE_RX_STATS_PRI_ENTRIES(counter) \
+ BNGE_RX_STATS_PRI_ENTRY(counter, 0), \
+ BNGE_RX_STATS_PRI_ENTRY(counter, 1), \
+ BNGE_RX_STATS_PRI_ENTRY(counter, 2), \
+ BNGE_RX_STATS_PRI_ENTRY(counter, 3), \
+ BNGE_RX_STATS_PRI_ENTRY(counter, 4), \
+ BNGE_RX_STATS_PRI_ENTRY(counter, 5), \
+ BNGE_RX_STATS_PRI_ENTRY(counter, 6), \
+ BNGE_RX_STATS_PRI_ENTRY(counter, 7)
+
+#define BNGE_TX_STATS_PRI_ENTRIES(counter) \
+ BNGE_TX_STATS_PRI_ENTRY(counter, 0), \
+ BNGE_TX_STATS_PRI_ENTRY(counter, 1), \
+ BNGE_TX_STATS_PRI_ENTRY(counter, 2), \
+ BNGE_TX_STATS_PRI_ENTRY(counter, 3), \
+ BNGE_TX_STATS_PRI_ENTRY(counter, 4), \
+ BNGE_TX_STATS_PRI_ENTRY(counter, 5), \
+ BNGE_TX_STATS_PRI_ENTRY(counter, 6), \
+ BNGE_TX_STATS_PRI_ENTRY(counter, 7)
+
+#define NUM_RING_Q_HW_STATS ARRAY_SIZE(bnge_ring_q_stats_str)
+
+static const struct {
+ long offset;
+ char string[ETH_GSTRING_LEN];
+} bnge_tx_port_stats_ext_arr[] = {
+ BNGE_TX_STATS_EXT_COS_ENTRIES,
+ BNGE_TX_STATS_EXT_PFC_ENTRIES,
+};
+
+static const struct {
+ long base_off;
+ char string[ETH_GSTRING_LEN];
+} bnge_rx_bytes_pri_arr[] = {
+ BNGE_RX_STATS_PRI_ENTRIES(rx_bytes),
+};
+
+static const struct {
+ long base_off;
+ char string[ETH_GSTRING_LEN];
+} bnge_rx_pkts_pri_arr[] = {
+ BNGE_RX_STATS_PRI_ENTRIES(rx_packets),
+};
+
+static const struct {
+ long base_off;
+ char string[ETH_GSTRING_LEN];
+} bnge_tx_bytes_pri_arr[] = {
+ BNGE_TX_STATS_PRI_ENTRIES(tx_bytes),
+};
+
+static const struct {
+ long base_off;
+ char string[ETH_GSTRING_LEN];
+} bnge_tx_pkts_pri_arr[] = {
+ BNGE_TX_STATS_PRI_ENTRIES(tx_packets),
+};
+
+static const struct {
+ long offset;
+ char string[ETH_GSTRING_LEN];
+} bnge_port_stats_arr[] = {
+ BNGE_RX_PORT_STATS_ENTRY(good_vlan_frames),
+ BNGE_RX_PORT_STATS_ENTRY(mtu_err_frames),
+ BNGE_RX_PORT_STATS_ENTRY(tagged_frames),
+ BNGE_RX_PORT_STATS_ENTRY(double_tagged_frames),
+ BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri0),
+ BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri1),
+ BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri2),
+ BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri3),
+ BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri4),
+ BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri5),
+ BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri6),
+ BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri7),
+ BNGE_RX_PORT_STATS_ENTRY(eee_lpi_events),
+ BNGE_RX_PORT_STATS_ENTRY(eee_lpi_duration),
+ BNGE_RX_PORT_STATS_ENTRY(runt_bytes),
+ BNGE_RX_PORT_STATS_ENTRY(runt_frames),
+
+ BNGE_TX_PORT_STATS_ENTRY(good_vlan_frames),
+ BNGE_TX_PORT_STATS_ENTRY(jabber_frames),
+ BNGE_TX_PORT_STATS_ENTRY(fcs_err_frames),
+ BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri0),
+ BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri1),
+ BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri2),
+ BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri3),
+ BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri4),
+ BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri5),
+ BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri6),
+ BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri7),
+ BNGE_TX_PORT_STATS_ENTRY(eee_lpi_events),
+ BNGE_TX_PORT_STATS_ENTRY(eee_lpi_duration),
+ BNGE_TX_PORT_STATS_ENTRY(xthol_frames),
+};
+
+static const struct {
+ long offset;
+ char string[ETH_GSTRING_LEN];
+} bnge_port_stats_ext_arr[] = {
+ BNGE_RX_STATS_EXT_ENTRY(continuous_pause_events),
+ BNGE_RX_STATS_EXT_ENTRY(resume_pause_events),
+ BNGE_RX_STATS_EXT_ENTRY(continuous_roce_pause_events),
+ BNGE_RX_STATS_EXT_ENTRY(resume_roce_pause_events),
+ BNGE_RX_STATS_EXT_COS_ENTRIES,
+ BNGE_RX_STATS_EXT_PFC_ENTRIES,
+ BNGE_RX_STATS_EXT_ENTRY(rx_bits),
+ BNGE_RX_STATS_EXT_ENTRY(rx_buffer_passed_threshold),
+ BNGE_RX_STATS_EXT_DISCARD_COS_ENTRIES,
+ BNGE_RX_STATS_EXT_ENTRY(rx_filter_miss),
+};
+
+static int bnge_get_num_tpa_ring_stats(struct bnge_dev *bd)
+{
+ if (BNGE_SUPPORTS_TPA(bd))
+ return BNGE_NUM_TPA_RING_STATS;
+ return 0;
+}
+
+#define BNGE_NUM_PORT_STATS ARRAY_SIZE(bnge_port_stats_arr)
+#define BNGE_NUM_STATS_PRI \
+ (ARRAY_SIZE(bnge_rx_bytes_pri_arr) + \
+ ARRAY_SIZE(bnge_rx_pkts_pri_arr) + \
+ ARRAY_SIZE(bnge_tx_bytes_pri_arr) + \
+ ARRAY_SIZE(bnge_tx_pkts_pri_arr))
+
+static int bnge_get_num_ring_stats(struct bnge_dev *bd)
+{
+ int rx, tx;
+
+ rx = NUM_RING_Q_HW_STATS + bnge_get_num_tpa_ring_stats(bd);
+ tx = NUM_RING_Q_HW_STATS;
+ return rx * bd->rx_nr_rings +
+ tx * bd->tx_nr_rings_per_tc;
+}
+
+static u32 bnge_get_num_stats(struct bnge_net *bn)
+{
+ u32 num_stats = bnge_get_num_ring_stats(bn->bd);
+ u32 len;
+
+ if (bn->flags & BNGE_FLAG_PORT_STATS)
+ num_stats += BNGE_NUM_PORT_STATS;
+
+ if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) {
+ len = min_t(int, bn->fw_rx_stats_ext_size,
+ ARRAY_SIZE(bnge_port_stats_ext_arr));
+ num_stats += len;
+ len = min_t(int, bn->fw_tx_stats_ext_size,
+ ARRAY_SIZE(bnge_tx_port_stats_ext_arr));
+ num_stats += len;
+ if (bn->pri2cos_valid)
+ num_stats += BNGE_NUM_STATS_PRI;
+ }
+
+ return num_stats;
+}
+
static void bnge_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
@@ -42,6 +307,219 @@ static void bnge_get_drvinfo(struct net_device *dev,
strscpy(info->bus_info, pci_name(bd->pdev), sizeof(info->bus_info));
}
+static int bnge_get_sset_count(struct net_device *dev, int sset)
+{
+ struct bnge_net *bn = netdev_priv(dev);
+
+ switch (sset) {
+ case ETH_SS_STATS:
+ return bnge_get_num_stats(bn);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static bool is_rx_ring(struct bnge_dev *bd, u16 ring_num)
+{
+ return ring_num < bd->rx_nr_rings;
+}
+
+static bool is_tx_ring(struct bnge_dev *bd, u16 ring_num)
+{
+ u16 tx_base = 0;
+
+ if (!(bd->flags & BNGE_EN_SHARED_CHNL))
+ tx_base = bd->rx_nr_rings;
+
+ return ring_num >= tx_base && ring_num < (tx_base + bd->tx_nr_rings);
+}
+
+static void bnge_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *buf)
+{
+ struct bnge_net *bn = netdev_priv(dev);
+ struct bnge_dev *bd = bn->bd;
+ u32 tpa_stats;
+ u32 i, j = 0;
+
+ if (!bn->bnapi) {
+ j += bnge_get_num_ring_stats(bd);
+ goto skip_ring_stats;
+ }
+
+ tpa_stats = bnge_get_num_tpa_ring_stats(bd);
+ for (i = 0; i < bd->nq_nr_rings; i++) {
+ struct bnge_napi *bnapi = bn->bnapi[i];
+ struct bnge_nq_ring_info *nqr;
+ u64 *sw_stats;
+ int k;
+
+ nqr = &bnapi->nq_ring;
+ sw_stats = nqr->stats.sw_stats;
+
+ if (is_rx_ring(bd, i)) {
+ buf[j++] = BNGE_GET_RING_STATS64(sw_stats, rx_ucast_pkts);
+ buf[j++] = BNGE_GET_RING_STATS64(sw_stats, rx_mcast_pkts);
+ buf[j++] = BNGE_GET_RING_STATS64(sw_stats, rx_bcast_pkts);
+ buf[j++] = BNGE_GET_RING_STATS64(sw_stats, rx_ucast_bytes);
+ buf[j++] = BNGE_GET_RING_STATS64(sw_stats, rx_mcast_bytes);
+ buf[j++] = BNGE_GET_RING_STATS64(sw_stats, rx_bcast_bytes);
+ }
+ if (is_tx_ring(bd, i)) {
+ buf[j++] = BNGE_GET_RING_STATS64(sw_stats, tx_ucast_pkts);
+ buf[j++] = BNGE_GET_RING_STATS64(sw_stats, tx_mcast_pkts);
+ buf[j++] = BNGE_GET_RING_STATS64(sw_stats, tx_bcast_pkts);
+ buf[j++] = BNGE_GET_RING_STATS64(sw_stats, tx_ucast_bytes);
+ buf[j++] = BNGE_GET_RING_STATS64(sw_stats, tx_mcast_bytes);
+ buf[j++] = BNGE_GET_RING_STATS64(sw_stats, tx_bcast_bytes);
+ }
+ if (!tpa_stats || !is_rx_ring(bd, i))
+ continue;
+
+ k = BNGE_NUM_RX_RING_STATS + BNGE_NUM_TX_RING_STATS;
+ for (; k < BNGE_NUM_RX_RING_STATS + BNGE_NUM_TX_RING_STATS +
+ tpa_stats; j++, k++)
+ buf[j] = sw_stats[k];
+ }
+
+skip_ring_stats:
+ if (bn->flags & BNGE_FLAG_PORT_STATS) {
+ u64 *port_stats = bn->port_stats.sw_stats;
+
+ for (i = 0; i < BNGE_NUM_PORT_STATS; i++, j++)
+ buf[j] = *(port_stats + bnge_port_stats_arr[i].offset);
+ }
+ if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) {
+ u64 *rx_port_stats_ext = bn->rx_port_stats_ext.sw_stats;
+ u64 *tx_port_stats_ext = bn->tx_port_stats_ext.sw_stats;
+ u32 len;
+
+ len = min_t(u32, bn->fw_rx_stats_ext_size,
+ ARRAY_SIZE(bnge_port_stats_ext_arr));
+ for (i = 0; i < len; i++, j++) {
+ buf[j] = *(rx_port_stats_ext +
+ bnge_port_stats_ext_arr[i].offset);
+ }
+ len = min_t(u32, bn->fw_tx_stats_ext_size,
+ ARRAY_SIZE(bnge_tx_port_stats_ext_arr));
+ for (i = 0; i < len; i++, j++) {
+ buf[j] = *(tx_port_stats_ext +
+ bnge_tx_port_stats_ext_arr[i].offset);
+ }
+ if (bn->pri2cos_valid) {
+ for (i = 0; i < 8; i++, j++) {
+ long n = bnge_rx_bytes_pri_arr[i].base_off +
+ bn->pri2cos_idx[i];
+
+ buf[j] = *(rx_port_stats_ext + n);
+ }
+ for (i = 0; i < 8; i++, j++) {
+ long n = bnge_rx_pkts_pri_arr[i].base_off +
+ bn->pri2cos_idx[i];
+
+ buf[j] = *(rx_port_stats_ext + n);
+ }
+ for (i = 0; i < 8; i++, j++) {
+ long n = bnge_tx_bytes_pri_arr[i].base_off +
+ bn->pri2cos_idx[i];
+
+ buf[j] = *(tx_port_stats_ext + n);
+ }
+ for (i = 0; i < 8; i++, j++) {
+ long n = bnge_tx_pkts_pri_arr[i].base_off +
+ bn->pri2cos_idx[i];
+
+ buf[j] = *(tx_port_stats_ext + n);
+ }
+ }
+ }
+}
+
+static void bnge_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
+{
+ struct bnge_net *bn = netdev_priv(dev);
+ struct bnge_dev *bd = bn->bd;
+ u32 i, j, num_str;
+ const char *str;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ for (i = 0; i < bd->nq_nr_rings; i++) {
+ if (is_rx_ring(bd, i))
+ for (j = 0; j < NUM_RING_Q_HW_STATS; j++) {
+ str = bnge_ring_q_stats_str[j];
+ ethtool_sprintf(&buf, "rxq%d_%s", i,
+ str);
+ }
+ if (is_tx_ring(bd, i))
+ for (j = 0; j < NUM_RING_Q_HW_STATS; j++) {
+ str = bnge_ring_q_stats_str[j];
+ ethtool_sprintf(&buf, "txq%d_%s", i,
+ str);
+ }
+ num_str = bnge_get_num_tpa_ring_stats(bd);
+ if (!num_str || !is_rx_ring(bd, i))
+ continue;
+
+ for (j = 0; j < num_str; j++) {
+ str = bnge_ring_tpa2_stats_str[j];
+ ethtool_sprintf(&buf, "rxq%d_%s", i, str);
+ }
+ }
+
+ if (bn->flags & BNGE_FLAG_PORT_STATS)
+ for (i = 0; i < BNGE_NUM_PORT_STATS; i++) {
+ str = bnge_port_stats_arr[i].string;
+ ethtool_puts(&buf, str);
+ }
+
+ if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) {
+ u32 len;
+
+ len = min_t(u32, bn->fw_rx_stats_ext_size,
+ ARRAY_SIZE(bnge_port_stats_ext_arr));
+ for (i = 0; i < len; i++) {
+ str = bnge_port_stats_ext_arr[i].string;
+ ethtool_puts(&buf, str);
+ }
+
+ len = min_t(u32, bn->fw_tx_stats_ext_size,
+ ARRAY_SIZE(bnge_tx_port_stats_ext_arr));
+ for (i = 0; i < len; i++) {
+ str = bnge_tx_port_stats_ext_arr[i].string;
+ ethtool_puts(&buf, str);
+ }
+
+ if (bn->pri2cos_valid) {
+ for (i = 0; i < 8; i++) {
+ str = bnge_rx_bytes_pri_arr[i].string;
+ ethtool_puts(&buf, str);
+ }
+
+ for (i = 0; i < 8; i++) {
+ str = bnge_rx_pkts_pri_arr[i].string;
+ ethtool_puts(&buf, str);
+ }
+
+ for (i = 0; i < 8; i++) {
+ str = bnge_tx_bytes_pri_arr[i].string;
+ ethtool_puts(&buf, str);
+ }
+
+ for (i = 0; i < 8; i++) {
+ str = bnge_tx_pkts_pri_arr[i].string;
+ ethtool_puts(&buf, str);
+ }
+ }
+ }
+ break;
+ default:
+ netdev_err(bd->netdev, "%s invalid request %x\n",
+ __func__, stringset);
+ break;
+ }
+}
+
static void bnge_get_eth_phy_stats(struct net_device *dev,
struct ethtool_eth_phy_stats *phy_stats)
{
@@ -262,6 +740,9 @@ static const struct ethtool_ops bnge_ethtool_ops = {
.nway_reset = bnge_nway_reset,
.get_pauseparam = bnge_get_pauseparam,
.set_pauseparam = bnge_set_pauseparam,
+ .get_sset_count = bnge_get_sset_count,
+ .get_strings = bnge_get_strings,
+ .get_ethtool_stats = bnge_get_ethtool_stats,
.get_eth_phy_stats = bnge_get_eth_phy_stats,
.get_eth_mac_stats = bnge_get_eth_mac_stats,
.get_eth_ctrl_stats = bnge_get_eth_ctrl_stats,
--
2.47.1
prev parent reply other threads:[~2026-03-15 14:18 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-15 14:15 [PATCH net-next v7 00/10] bng_en: add link management and statistics support Vikas Gupta
2026-03-15 14:15 ` [PATCH net-next v7 01/10] bng_en: add per-PF workqueue, timer, and slow-path task Vikas Gupta
2026-03-15 14:15 ` [PATCH net-next v7 02/10] bng_en: query PHY capabilities and report link status Vikas Gupta
2026-03-15 14:15 ` [PATCH net-next v7 03/10] bng_en: add ethtool link settings, get_link, and nway_reset Vikas Gupta
2026-03-15 14:15 ` [PATCH net-next v7 04/10] bng_en: implement ethtool pauseparam operations Vikas Gupta
2026-03-15 14:16 ` [PATCH net-next v7 05/10] bng_en: add support for link async events Vikas Gupta
2026-03-15 14:16 ` [PATCH net-next v7 06/10] bng_en: add HW stats infra and structured ethtool ops Vikas Gupta
2026-03-18 22:01 ` Jakub Kicinski
2026-03-19 2:53 ` Jakub Kicinski
2026-03-15 14:16 ` [PATCH net-next v7 07/10] bng_en: periodically fetch and accumulate hardware statistics Vikas Gupta
2026-03-15 14:16 ` [PATCH net-next v7 08/10] bng_en: implement ndo_get_stats64 Vikas Gupta
2026-03-15 14:16 ` [PATCH net-next v7 09/10] bng_en: implement netdev_stat_ops Vikas Gupta
2026-03-15 14:16 ` Vikas Gupta [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260315141605.410878-11-vikas.gupta@broadcom.com \
--to=vikas.gupta@broadcom.com \
--cc=ajit.khaparde@broadcom.com \
--cc=andrew+netdev@lunn.ch \
--cc=bhargava.marreddy@broadcom.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=michael.chan@broadcom.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pavan.chebbi@broadcom.com \
--cc=rajashekar.hudumula@broadcom.com \
--cc=vsrama-krishna.nemani@broadcom.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox