[PATCH net-next v18 3/4] hinic3: Add Add per queue netdev-genl stats

From: Fan Gong

Date: Thu Oct 22 2026 - 08:25:55 EST


Co-developed-by: Wu Di <wudi234@xxxxxxxxxx>
Signed-off-by: Wu Di <wudi234@xxxxxxxxxx>
Co-developed-by: Teng Peisen <tengpeisen@xxxxxxxxxx>
Signed-off-by: Teng Peisen <tengpeisen@xxxxxxxxxx>
Signed-off-by: Fan Gong <gongfan1@xxxxxxxxxx>
---
.../huawei/hinic3/hinic3_netdev_ops.c | 74 +++++++++++++++++++
1 file changed, 74 insertions(+)

diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
index c71bb3dff39c..10364c4dc11f 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
@@ -5,6 +5,7 @@
#include <linux/if_vlan.h>
#include <linux/netdevice.h>
#include <net/vxlan.h>
+#include <net/netdev_queues.h>

#include "hinic3_hwif.h"
#include "hinic3_nic_cfg.h"
@@ -866,7 +867,80 @@ static const struct net_device_ops hinic3_netdev_ops = {
.ndo_start_xmit = hinic3_xmit_frame,
};

+static void hinic3_get_queue_stats_rx(struct net_device *netdev, int i,
+ struct netdev_queue_stats_rx *stats_rx)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic3_rxq_stats *rxq_stats;
+ struct hinic3_rxq *rxq;
+ unsigned int start;
+
+ rxq = &nic_dev->rxqs[i];
+ rxq_stats = &rxq->rxq_stats;
+ do {
+ start = u64_stats_fetch_begin(&rxq_stats->syncp);
+ stats_rx->bytes = rxq_stats->bytes;
+ stats_rx->packets = rxq_stats->packets;
+ stats_rx->csum_bad = rxq_stats->csum_errors;
+ stats_rx->alloc_fail = rxq_stats->alloc_fail;
+ } while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
+}
+
+static void hinic3_get_queue_stats_tx(struct net_device *netdev, int i,
+ struct netdev_queue_stats_tx *stats_tx)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic3_txq_stats *txq_stats;
+ struct hinic3_txq *txq;
+ unsigned int start;
+
+ txq = &nic_dev->txqs[i];
+ txq_stats = &txq->txq_stats;
+ do {
+ start = u64_stats_fetch_begin(&txq_stats->syncp);
+ stats_tx->bytes = txq_stats->bytes;
+ stats_tx->packets = txq_stats->packets;
+ stats_tx->stop = txq_stats->busy;
+ } while (u64_stats_fetch_retry(&txq_stats->syncp, start));
+}
+
+static void hinic3_get_base_stats(struct net_device *netdev,
+ struct netdev_queue_stats_rx *stats_rx,
+ struct netdev_queue_stats_tx *stats_tx)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ int i;
+
+ memset(stats_rx, 0, sizeof(*stats_rx));
+ memset(stats_tx, 0, sizeof(*stats_tx));
+
+ for (i = nic_dev->q_params.num_qps; i < nic_dev->max_qps; i++) {
+ struct netdev_queue_stats_rx rx = {0};
+
+ hinic3_get_queue_stats_rx(netdev, i, &rx);
+ stats_rx->bytes += rx.bytes;
+ stats_rx->packets += rx.packets;
+ stats_rx->csum_bad += rx.csum_bad;
+ }
+
+ for (i = nic_dev->q_params.num_qps; i < nic_dev->max_qps; i++) {
+ struct netdev_queue_stats_tx tx = {0};
+
+ hinic3_get_queue_stats_tx(netdev, i, &tx);
+ stats_tx->bytes += tx.bytes;
+ stats_tx->packets += tx.packets;
+ stats_tx->stop += tx.stop;
+ }
+}
+
+static const struct netdev_stat_ops hinic3_stat_ops = {
+ .get_queue_stats_rx = hinic3_get_queue_stats_rx,
+ .get_queue_stats_tx = hinic3_get_queue_stats_tx,
+ .get_base_stats = hinic3_get_base_stats,
+};
+
void hinic3_set_netdev_ops(struct net_device *netdev)
{
netdev->netdev_ops = &hinic3_netdev_ops;
+ netdev->stat_ops = &hinic3_stat_ops;
}
--
2.43.0