@@ -6,4 +6,4 @@ ccflags-y += -I$(srctree)/drivers/net/ethernet/yunsilicon/xsc
obj-$(CONFIG_YUNSILICON_XSC_ETH) += xsc_eth.o
-xsc_eth-y := main.o xsc_eth_wq.o xsc_eth_txrx.o xsc_eth_tx.o xsc_eth_rx.o
+xsc_eth-y := main.o xsc_eth_wq.o xsc_eth_txrx.o xsc_eth_tx.o xsc_eth_rx.o xsc_eth_stats.o
@@ -541,12 +541,15 @@ static int xsc_eth_open_qp_sq(struct xsc_channel *c,
struct xsc_core_device *xdev = adapter->xdev;
u8 q_log_size = psq_param->sq_attr.q_log_size;
u8 ele_log_size = psq_param->sq_attr.ele_log_size;
+ struct xsc_stats *stats = adapter->stats;
+ struct xsc_channel_stats *channel_stats = &stats->channel_stats[c->chl_idx];
struct xsc_create_qp_mbox_in *in;
struct xsc_modify_raw_qp_mbox_in *modify_in;
int hw_npages;
int inlen;
int ret;
+ psq->stats = &channel_stats->sq[sq_idx];
psq_param->wq.db_numa_node = cpu_to_node(c->cpu);
ret = xsc_eth_wq_cyc_create(xdev, &psq_param->wq,
@@ -845,10 +848,13 @@ static int xsc_eth_alloc_rq(struct xsc_channel *c,
struct page_pool_params pagepool_params = { 0 };
u32 pool_size = 1 << q_log_size;
u8 ele_log_size = prq_param->rq_attr.ele_log_size;
+ struct xsc_stats *stats = c->adapter->stats;
+ struct xsc_channel_stats *channel_stats = &stats->channel_stats[c->chl_idx];
int wq_sz;
int i, f;
int ret = 0;
+ prq->stats = &channel_stats->rq;
prq_param->wq.db_numa_node = cpu_to_node(c->cpu);
ret = xsc_eth_wq_cyc_create(c->adapter->xdev, &prq_param->wq,
@@ -1634,6 +1640,13 @@ static int xsc_eth_close(struct net_device *netdev)
return ret;
}
+static void xsc_eth_get_stats(struct net_device *netdev, struct rtnl_link_stats64 *stats)
+{
+ struct xsc_adapter *adapter = netdev_priv(netdev);
+
+ xsc_eth_fold_sw_stats64(adapter, stats);
+}
+
static int xsc_eth_set_hw_mtu(struct xsc_core_device *xdev, u16 mtu, u16 rx_buf_sz)
{
struct xsc_set_mtu_mbox_in in;
@@ -1663,6 +1676,7 @@ static const struct net_device_ops xsc_netdev_ops = {
.ndo_open = xsc_eth_open,
.ndo_stop = xsc_eth_close,
.ndo_start_xmit = xsc_eth_xmit_start,
+ .ndo_get_stats64 = xsc_eth_get_stats,
};
static void xsc_eth_build_nic_netdev(struct xsc_adapter *adapter)
@@ -1872,16 +1886,22 @@ static void *xsc_eth_add(struct xsc_core_device *xdev)
goto err_cleanup_netdev;
}
+ adapter->stats = kvzalloc(sizeof(*adapter->stats), GFP_KERNEL);
+ if (!adapter->stats)
+ goto err_detach;
+
err = register_netdev(netdev);
if (err) {
xsc_core_warn(xdev, "register_netdev failed, err=%d\n", err);
- goto err_detach;
+ goto err_free_stats;
}
xdev->netdev = (void *)netdev;
return adapter;
+err_free_stats:
+ kfree(adapter->stats);
err_detach:
xsc_eth_detach(xdev, adapter);
err_cleanup_netdev:
@@ -1908,7 +1928,7 @@ static void xsc_eth_remove(struct xsc_core_device *xdev, void *context)
xsc_core_info(adapter->xdev, "remove netdev %s entry\n", adapter->netdev->name);
unregister_netdev(adapter->netdev);
-
+ kfree(adapter->stats);
free_netdev(adapter->netdev);
xdev->netdev = NULL;
@@ -9,6 +9,7 @@
#include <linux/udp.h>
#include "common/xsc_device.h"
#include "xsc_eth_common.h"
+#include "xsc_eth_stats.h"
#define XSC_INVALID_LKEY 0x100
@@ -48,6 +49,8 @@ struct xsc_adapter {
u32 status;
struct mutex status_lock; // protect status
+
+ struct xsc_stats *stats;
};
#endif /* XSC_ETH_H */
@@ -176,6 +176,10 @@ static inline void xsc_complete_rx_cqe(struct xsc_rq *rq,
struct sk_buff *skb,
struct xsc_wqe_frag_info *wi)
{
+ struct xsc_rq_stats *stats = rq->stats;
+
+ stats->packets++;
+ stats->bytes += cqe_bcnt;
xsc_build_rx_skb(cqe, cqe_bcnt, rq, skb, wi);
}
new file mode 100644
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2021-2025, Shanghai Yunsilicon Technology Co., Ltd.
+ * All rights reserved.
+ */
+
+#include "xsc_eth_stats.h"
+#include "xsc_eth.h"
+
+static inline int xsc_get_netdev_max_channels(struct xsc_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ return min_t(unsigned int, netdev->num_rx_queues,
+ netdev->num_tx_queues);
+}
+
+static inline int xsc_get_netdev_max_tc(struct xsc_adapter *adapter)
+{
+ return adapter->nic_param.num_tc;
+}
+
+void xsc_eth_fold_sw_stats64(struct xsc_adapter *adapter, struct rtnl_link_stats64 *s)
+{
+ int i, j;
+
+ for (i = 0; i < xsc_get_netdev_max_channels(adapter); i++) {
+ struct xsc_channel_stats *channel_stats = &adapter->stats->channel_stats[i];
+ struct xsc_rq_stats *rq_stats = &channel_stats->rq;
+
+ s->rx_packets += rq_stats->packets;
+ s->rx_bytes += rq_stats->bytes;
+
+ for (j = 0; j < xsc_get_netdev_max_tc(adapter); j++) {
+ struct xsc_sq_stats *sq_stats = &channel_stats->sq[j];
+
+ s->tx_packets += sq_stats->packets;
+ s->tx_bytes += sq_stats->bytes;
+ s->tx_dropped += sq_stats->dropped;
+ }
+ }
+}
+
new file mode 100644
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2021-2025, Shanghai Yunsilicon Technology Co., Ltd.
+ * All rights reserved.
+ */
+
+#ifndef XSC_EN_STATS_H
+#define XSC_EN_STATS_H
+
+#include "xsc_eth_common.h"
+
+struct xsc_rq_stats {
+ u64 packets;
+ u64 bytes;
+};
+
+struct xsc_sq_stats {
+ u64 packets;
+ u64 bytes;
+ u64 dropped;
+};
+
+struct xsc_channel_stats {
+ struct xsc_sq_stats sq[XSC_MAX_NUM_TC];
+ struct xsc_rq_stats rq;
+} ____cacheline_aligned_in_smp;
+
+struct xsc_stats {
+ struct xsc_channel_stats channel_stats[XSC_ETH_MAX_NUM_CHANNELS];
+};
+
+void xsc_eth_fold_sw_stats64(struct xsc_adapter *adapter, struct rtnl_link_stats64 *s);
+
+#endif /* XSC_EN_STATS_H */
@@ -201,6 +201,7 @@ static uint32_t xsc_eth_xmit_frame(struct sk_buff *skb,
struct xsc_send_wqe_ctrl_seg *cseg;
struct xsc_wqe_data_seg *dseg;
struct xsc_tx_wqe_info *wi;
+ struct xsc_sq_stats *stats = sq->stats;
struct xsc_core_device *xdev = sq->cq.xdev;
u16 ds_cnt;
u16 mss, ihs, headlen;
@@ -219,11 +220,13 @@ static uint32_t xsc_eth_xmit_frame(struct sk_buff *skb,
mss = skb_shinfo(skb)->gso_size;
ihs = xsc_tx_get_gso_ihs(sq, skb);
num_bytes = skb->len;
+ stats->packets += skb_shinfo(skb)->gso_segs;
} else {
opcode = XSC_OPCODE_RAW;
mss = 0;
ihs = 0;
num_bytes = skb->len;
+ stats->packets++;
}
/*linear data in skb*/
@@ -261,10 +264,12 @@ static uint32_t xsc_eth_xmit_frame(struct sk_buff *skb,
xsc_txwqe_complete(sq, skb, opcode, ds_cnt, num_wqebbs, num_bytes,
num_dma, wi);
+ stats->bytes += num_bytes;
return NETDEV_TX_OK;
err_drop:
+ stats->dropped++;
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
@@ -156,6 +156,7 @@ struct xsc_rq {
unsigned long state;
struct work_struct recover_work;
+ struct xsc_rq_stats *stats;
u32 hw_mtu;
u32 frags_sz;
@@ -204,6 +205,7 @@ struct xsc_sq {
/* read only */
struct xsc_wq_cyc wq;
u32 dma_fifo_mask;
+ struct xsc_sq_stats *stats;
struct {
struct xsc_sq_dma *dma_fifo;
struct xsc_tx_wqe_info *wqe_info;
Support nic stats Co-developed-by: Honggang Wei <weihg@yunsilicon.com> Co-developed-by: Lei Yan <Jacky@yunsilicon.com> Signed-off-by: Xin Tian <tianx@yunsilicon.com> --- .../net/ethernet/yunsilicon/xsc/net/Makefile | 2 +- .../net/ethernet/yunsilicon/xsc/net/main.c | 24 ++++++++++- .../net/ethernet/yunsilicon/xsc/net/xsc_eth.h | 3 ++ .../ethernet/yunsilicon/xsc/net/xsc_eth_rx.c | 4 ++ .../yunsilicon/xsc/net/xsc_eth_stats.c | 42 +++++++++++++++++++ .../yunsilicon/xsc/net/xsc_eth_stats.h | 33 +++++++++++++++ .../ethernet/yunsilicon/xsc/net/xsc_eth_tx.c | 5 +++ .../ethernet/yunsilicon/xsc/net/xsc_queue.h | 2 + 8 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 drivers/net/ethernet/yunsilicon/xsc/net/xsc_eth_stats.c create mode 100644 drivers/net/ethernet/yunsilicon/xsc/net/xsc_eth_stats.h