Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/3] net: libwx: improve VF ethtool support
@ 2026-05-25 10:11 Mengyuan Lou
  2026-05-25 10:11 ` [PATCH net-next v2 1/3] net: libwx: add support for set_ringparam in wx_ethtool_ops_vf Mengyuan Lou
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Mengyuan Lou @ 2026-05-25 10:11 UTC (permalink / raw)
  To: netdev; +Cc: jiawenwu, duanqiangwen, Mengyuan Lou

This series improves ethtool support for Wangxun VF drivers
(ngbevf and txgbevf) in libwx.

This series extends VF support by enabling:
ring parameter configuration via ethtool -G
interrupt coalescing configuration via ethtool -C
hardware statistics reporting via ethtool -S

Patch 1 adds support for set_ringparam in wx_ethtool_ops_vf,
allowing VF users to adjust TX/RX descriptor ring sizes.
Patch 2 enables set_coalesce support for VF devices and updates
EITR programming to use the VF-specific register access helper.
Patch 3 adds VF hardware statistics support so ethtool -S can
report useful runtime counters for VF interfaces.

Changes log:
v2:
- Patch 1:
  Remove some stats which can be replaced by standard stats defined in
  include/net/netdev_queues.h.
- Patch 3:
  Adding a return value to wx_set_ring to make wx_set_ringparam_vf can
  be passed back to userspace.
  Remove freeing and requesting of IRQs. Ring resize only updates descriptor
  resources and does not change MSI-X vector or interrupt configuration,
  so IRQs do not need to be reallocated.
v1: https://lore.kernel.org/all/20260514103405.42175-1-mengyuanlou@net-swift.com

Mengyuan Lou (3):
  net: libwx: add support for set_ringparam in wx_ethtool_ops_vf
  net: libwx: add support for set_coalesce in wx_ethtool_ops_vf
  net: libwx: support vf hardware statistics

 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 98 +++++++++++++++++--
 drivers/net/ethernet/wangxun/libwx/wx_hw.c    | 75 +++++++-------
 drivers/net/ethernet/wangxun/libwx/wx_lib.c   |  9 +-
 drivers/net/ethernet/wangxun/libwx/wx_lib.h   |  4 +-
 .../net/ethernet/wangxun/libwx/wx_vf_common.c | 55 ++++++++++-
 .../net/ethernet/wangxun/libwx/wx_vf_common.h |  3 +
 .../net/ethernet/wangxun/ngbevf/ngbevf_main.c |  1 +
 .../ethernet/wangxun/txgbevf/txgbevf_main.c   |  2 +
 8 files changed, 195 insertions(+), 52 deletions(-)

-- 
2.30.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH net-next v2 1/3] net: libwx: add support for set_ringparam in wx_ethtool_ops_vf
  2026-05-25 10:11 [PATCH net-next v2 0/3] net: libwx: improve VF ethtool support Mengyuan Lou
@ 2026-05-25 10:11 ` Mengyuan Lou
  2026-05-25 10:11 ` [PATCH net-next v2 2/3] net: libwx: add support for set_coalesce " Mengyuan Lou
  2026-05-25 10:11 ` [PATCH net-next v2 3/3] net: libwx: support vf hardware statistics Mengyuan Lou
  2 siblings, 0 replies; 5+ messages in thread
From: Mengyuan Lou @ 2026-05-25 10:11 UTC (permalink / raw)
  To: netdev; +Cc: jiawenwu, duanqiangwen, Mengyuan Lou

Add support for the set_ringparam in wx_ethtool_ops_vf,
which is used to set ring sizes for ngbevf and txgbevf.

Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
---
 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 60 +++++++++++++++++++
 drivers/net/ethernet/wangxun/libwx/wx_lib.c   |  9 +--
 drivers/net/ethernet/wangxun/libwx/wx_lib.h   |  4 +-
 .../net/ethernet/wangxun/libwx/wx_vf_common.c |  4 +-
 .../net/ethernet/wangxun/libwx/wx_vf_common.h |  2 +
 5 files changed, 71 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index 5df971aca9e3..6d8fcddde6fa 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -9,6 +9,7 @@
 #include "wx_ethtool.h"
 #include "wx_hw.h"
 #include "wx_lib.h"
+#include "wx_vf_common.h"
 
 struct wx_stats {
 	char stat_string[ETH_GSTRING_LEN];
@@ -775,6 +776,64 @@ static int wx_get_link_ksettings_vf(struct net_device *netdev,
 	return 0;
 }
 
+static int wx_set_ringparam_vf(struct net_device *netdev,
+			       struct ethtool_ringparam *ring,
+			       struct kernel_ethtool_ringparam *kernel_ring,
+			       struct netlink_ext_ack *extack)
+{
+	struct wx *wx = netdev_priv(netdev);
+	u32 new_rx_count, new_tx_count;
+	struct wx_ring *temp_ring;
+	int i, err = 0;
+
+	new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD);
+	new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE);
+
+	new_rx_count = clamp_t(u32, ring->rx_pending, WX_MIN_RXD, WX_MAX_RXD);
+	new_rx_count = ALIGN(new_rx_count, WX_REQ_RX_DESCRIPTOR_MULTIPLE);
+
+	if (new_tx_count == wx->tx_ring_count &&
+	    new_rx_count == wx->rx_ring_count)
+		return 0;
+
+	mutex_lock(&wx->reset_lock);
+	set_bit(WX_STATE_RESETTING, wx->state);
+
+	if (!netif_running(wx->netdev)) {
+		for (i = 0; i < wx->num_tx_queues; i++)
+			wx->tx_ring[i]->count = new_tx_count;
+		for (i = 0; i < wx->num_rx_queues; i++)
+			wx->rx_ring[i]->count = new_rx_count;
+		wx->tx_ring_count = new_tx_count;
+		wx->rx_ring_count = new_rx_count;
+
+		goto clear_reset;
+	}
+
+	/* allocate temporary buffer to store rings in */
+	i = max_t(int, wx->num_tx_queues, wx->num_rx_queues);
+	temp_ring = kvmalloc_objs(struct wx_ring, i);
+	if (!temp_ring) {
+		err = -ENOMEM;
+		goto clear_reset;
+	}
+
+	wxvf_down(wx);
+	/* When set_ring fails, the count will not be updated.
+	 * It merely notifies that there is an error in the setting.
+	 */
+	err = wx_set_ring(wx, new_tx_count, new_rx_count, temp_ring);
+	if (err)
+		wx_err(wx, "failed to set ring parameters: %d", err);
+	wx_configure_vf(wx);
+	wxvf_up_complete(wx);
+	kvfree(temp_ring);
+clear_reset:
+	clear_bit(WX_STATE_RESETTING, wx->state);
+	mutex_unlock(&wx->reset_lock);
+	return err;
+}
+
 static const struct ethtool_ops wx_ethtool_ops_vf = {
 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
 				     ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ |
@@ -782,6 +841,7 @@ static const struct ethtool_ops wx_ethtool_ops_vf = {
 	.get_drvinfo		= wx_get_drvinfo,
 	.get_link		= ethtool_op_get_link,
 	.get_ringparam		= wx_get_ringparam,
+	.set_ringparam		= wx_set_ringparam_vf,
 	.get_msglevel		= wx_get_msglevel,
 	.get_coalesce		= wx_get_coalesce,
 	.get_ts_info		= ethtool_op_get_ts_info,
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
index 746623fa59b4..2f5d5ef639df 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -3246,8 +3246,8 @@ netdev_features_t wx_features_check(struct sk_buff *skb,
 }
 EXPORT_SYMBOL(wx_features_check);
 
-void wx_set_ring(struct wx *wx, u32 new_tx_count,
-		 u32 new_rx_count, struct wx_ring *temp_ring)
+int wx_set_ring(struct wx *wx, u32 new_tx_count,
+		u32 new_rx_count, struct wx_ring *temp_ring)
 {
 	int i, err = 0;
 
@@ -3269,7 +3269,7 @@ void wx_set_ring(struct wx *wx, u32 new_tx_count,
 					i--;
 					wx_free_tx_resources(&temp_ring[i]);
 				}
-				return;
+				return err;
 			}
 		}
 
@@ -3297,7 +3297,7 @@ void wx_set_ring(struct wx *wx, u32 new_tx_count,
 					i--;
 					wx_free_rx_resources(&temp_ring[i]);
 				}
-				return;
+				return err;
 			}
 		}
 
@@ -3309,6 +3309,7 @@ void wx_set_ring(struct wx *wx, u32 new_tx_count,
 
 		wx->rx_ring_count = new_rx_count;
 	}
+	return 0;
 }
 EXPORT_SYMBOL(wx_set_ring);
 
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.h b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
index aed6ea8cf0d6..bc671786978e 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
@@ -36,8 +36,8 @@ netdev_features_t wx_fix_features(struct net_device *netdev,
 netdev_features_t wx_features_check(struct sk_buff *skb,
 				    struct net_device *netdev,
 				    netdev_features_t features);
-void wx_set_ring(struct wx *wx, u32 new_tx_count,
-		 u32 new_rx_count, struct wx_ring *temp_ring);
+int wx_set_ring(struct wx *wx, u32 new_tx_count,
+		u32 new_rx_count, struct wx_ring *temp_ring);
 void wx_service_event_schedule(struct wx *wx);
 void wx_service_event_complete(struct wx *wx);
 void wx_service_timer(struct timer_list *t);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
index 94ff8f5f0b4c..a3361696b783 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
@@ -269,7 +269,7 @@ static void wxvf_irq_enable(struct wx *wx)
 	wr32(wx, WX_VXIMC, wx->eims_enable_mask);
 }
 
-static void wxvf_up_complete(struct wx *wx)
+void wxvf_up_complete(struct wx *wx)
 {
 	/* Always set the carrier off */
 	netif_carrier_off(wx->netdev);
@@ -323,7 +323,7 @@ int wxvf_open(struct net_device *netdev)
 }
 EXPORT_SYMBOL(wxvf_open);
 
-static void wxvf_down(struct wx *wx)
+void wxvf_down(struct wx *wx)
 {
 	struct net_device *netdev = wx->netdev;
 
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.h b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.h
index cbbb1b178cb2..d45d5d8ac3ab 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.h
@@ -15,7 +15,9 @@ void wx_set_rx_mode_vf(struct net_device *netdev);
 void wx_configure_vf(struct wx *wx);
 int wx_set_mac_vf(struct net_device *netdev, void *p);
 void wxvf_watchdog_update_link(struct wx *wx);
+void wxvf_up_complete(struct wx *wx);
 int wxvf_open(struct net_device *netdev);
+void wxvf_down(struct wx *wx);
 int wxvf_close(struct net_device *netdev);
 void wxvf_init_service(struct wx *wx);
 
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-next v2 2/3] net: libwx: add support for set_coalesce in wx_ethtool_ops_vf
  2026-05-25 10:11 [PATCH net-next v2 0/3] net: libwx: improve VF ethtool support Mengyuan Lou
  2026-05-25 10:11 ` [PATCH net-next v2 1/3] net: libwx: add support for set_ringparam in wx_ethtool_ops_vf Mengyuan Lou
@ 2026-05-25 10:11 ` Mengyuan Lou
  2026-05-25 10:11 ` [PATCH net-next v2 3/3] net: libwx: support vf hardware statistics Mengyuan Lou
  2 siblings, 0 replies; 5+ messages in thread
From: Mengyuan Lou @ 2026-05-25 10:11 UTC (permalink / raw)
  To: netdev; +Cc: jiawenwu, duanqiangwen, Mengyuan Lou

Add support for set_coalesce in wx_ethtool_ops_vf, which
is used to set interrupt coalescing parameters.

Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
---
 drivers/net/ethernet/wangxun/libwx/wx_ethtool.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index 6d8fcddde6fa..30c6ef6103ac 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -10,6 +10,7 @@
 #include "wx_hw.h"
 #include "wx_lib.h"
 #include "wx_vf_common.h"
+#include "wx_vf_lib.h"
 
 struct wx_stats {
 	char stat_string[ETH_GSTRING_LEN];
@@ -488,7 +489,10 @@ int wx_set_coalesce(struct net_device *netdev,
 		else
 			/* rx only or mixed */
 			q_vector->itr = rx_itr_param;
-		wx_write_eitr(q_vector);
+		if (wx->pdev->is_virtfn)
+			wx_write_eitr_vf(q_vector);
+		else
+			wx_write_eitr(q_vector);
 	}
 
 	wx_update_rsc(wx);
@@ -844,6 +848,7 @@ static const struct ethtool_ops wx_ethtool_ops_vf = {
 	.set_ringparam		= wx_set_ringparam_vf,
 	.get_msglevel		= wx_get_msglevel,
 	.get_coalesce		= wx_get_coalesce,
+	.set_coalesce		= wx_set_coalesce,
 	.get_ts_info		= ethtool_op_get_ts_info,
 	.get_link_ksettings	= wx_get_link_ksettings_vf,
 };
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-next v2 3/3] net: libwx: support vf hardware statistics
  2026-05-25 10:11 [PATCH net-next v2 0/3] net: libwx: improve VF ethtool support Mengyuan Lou
  2026-05-25 10:11 ` [PATCH net-next v2 1/3] net: libwx: add support for set_ringparam in wx_ethtool_ops_vf Mengyuan Lou
  2026-05-25 10:11 ` [PATCH net-next v2 2/3] net: libwx: add support for set_coalesce " Mengyuan Lou
@ 2026-05-25 10:11 ` Mengyuan Lou
  2026-05-27  1:49   ` Jakub Kicinski
  2 siblings, 1 reply; 5+ messages in thread
From: Mengyuan Lou @ 2026-05-25 10:11 UTC (permalink / raw)
  To: netdev; +Cc: jiawenwu, duanqiangwen, Mengyuan Lou

Add support to show hardware statistics for ethtool -S ethx.

Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
---
 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 31 ++++++--
 drivers/net/ethernet/wangxun/libwx/wx_hw.c    | 75 ++++++++++---------
 .../net/ethernet/wangxun/libwx/wx_vf_common.c | 51 +++++++++++++
 .../net/ethernet/wangxun/libwx/wx_vf_common.h |  1 +
 .../net/ethernet/wangxun/ngbevf/ngbevf_main.c |  1 +
 .../ethernet/wangxun/txgbevf/txgbevf_main.c   |  2 +
 6 files changed, 118 insertions(+), 43 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index 30c6ef6103ac..a12e1205ce80 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -48,6 +48,10 @@ static const struct wx_stats wx_gstrings_stats[] = {
 	WX_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
 };
 
+static const struct wx_stats wx_gstrings_stats_vf[] = {
+	WX_STAT("non_eop_descs", non_eop_descs),
+};
+
 static const struct wx_stats wx_gstrings_fdir_stats[] = {
 	WX_STAT("fdir_match", stats.fdirmatch),
 	WX_STAT("fdir_miss", stats.fdirmiss),
@@ -69,7 +73,9 @@ static const struct wx_stats wx_gstrings_rsc_stats[] = {
 #define WX_QUEUE_STATS_LEN ( \
 		(WX_NUM_TX_QUEUES + WX_NUM_RX_QUEUES) * \
 		(sizeof(struct wx_queue_stats) / sizeof(u64)))
-#define WX_GLOBAL_STATS_LEN  ARRAY_SIZE(wx_gstrings_stats)
+#define WX_GLOBAL_STATS_LEN (wx->pdev->is_virtfn ? \
+		ARRAY_SIZE(wx_gstrings_stats_vf) : \
+		ARRAY_SIZE(wx_gstrings_stats))
 #define WX_FDIR_STATS_LEN  ARRAY_SIZE(wx_gstrings_fdir_stats)
 #define WX_RSC_STATS_LEN  ARRAY_SIZE(wx_gstrings_rsc_stats)
 #define WX_STATS_LEN (WX_GLOBAL_STATS_LEN + WX_QUEUE_STATS_LEN)
@@ -101,7 +107,10 @@ void wx_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
 	switch (stringset) {
 	case ETH_SS_STATS:
 		for (i = 0; i < WX_GLOBAL_STATS_LEN; i++)
-			ethtool_puts(&p, wx_gstrings_stats[i].stat_string);
+			if (wx->pdev->is_virtfn)
+				ethtool_puts(&p, wx_gstrings_stats_vf[i].stat_string);
+			else
+				ethtool_puts(&p, wx_gstrings_stats[i].stat_string);
 		if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags)) {
 			for (i = 0; i < WX_FDIR_STATS_LEN; i++)
 				ethtool_puts(&p, wx_gstrings_fdir_stats[i].stat_string);
@@ -135,9 +144,15 @@ void wx_get_ethtool_stats(struct net_device *netdev,
 	wx_update_stats(wx);
 
 	for (i = 0; i < WX_GLOBAL_STATS_LEN; i++) {
-		p = (char *)wx + wx_gstrings_stats[i].stat_offset;
-		data[i] = (wx_gstrings_stats[i].sizeof_stat ==
-			   sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+		if (wx->pdev->is_virtfn) {
+			p = (char *)wx + wx_gstrings_stats_vf[i].stat_offset;
+			data[i] = (wx_gstrings_stats_vf[i].sizeof_stat ==
+				   sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+		} else {
+			p = (char *)wx + wx_gstrings_stats[i].stat_offset;
+			data[i] = (wx_gstrings_stats[i].sizeof_stat ==
+				   sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+		}
 	}
 
 	if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags)) {
@@ -219,9 +234,10 @@ EXPORT_SYMBOL(wx_get_pause_stats);
 
 void wx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
 {
-	unsigned int stats_len = WX_STATS_LEN;
 	struct wx *wx = netdev_priv(netdev);
+	unsigned int stats_len;
 
+	stats_len = WX_STATS_LEN;
 	if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags))
 		stats_len += WX_FDIR_STATS_LEN;
 
@@ -851,6 +867,9 @@ static const struct ethtool_ops wx_ethtool_ops_vf = {
 	.set_coalesce		= wx_set_coalesce,
 	.get_ts_info		= ethtool_op_get_ts_info,
 	.get_link_ksettings	= wx_get_link_ksettings_vf,
+	.get_sset_count		= wx_get_sset_count,
+	.get_strings		= wx_get_strings,
+	.get_ethtool_stats	= wx_get_ethtool_stats,
 };
 
 void wx_set_ethtool_ops_vf(struct net_device *netdev)
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 2451f6b20b11..7244aee3fc74 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -2916,45 +2916,46 @@ void wx_update_stats(struct wx *wx)
 	wx->restart_queue = restart_queue;
 	wx->tx_busy = tx_busy;
 
-	wx_update_xoff_rx_lfc(wx);
-
-	hwstats->gprc += rd32(wx, WX_RDM_PKT_CNT);
-	hwstats->gptc += rd32(wx, WX_TDM_PKT_CNT);
-	hwstats->gorc += rd64(wx, WX_RDM_BYTE_CNT_LSB);
-	hwstats->gotc += rd64(wx, WX_TDM_BYTE_CNT_LSB);
-	hwstats->tpr += rd64(wx, WX_RX_FRAME_CNT_GOOD_BAD_L);
-	hwstats->tpt += rd64(wx, WX_TX_FRAME_CNT_GOOD_BAD_L);
-	hwstats->crcerrs += rd64(wx, WX_RX_CRC_ERROR_FRAMES_L);
-	hwstats->rlec += rd64(wx, WX_RX_LEN_ERROR_FRAMES_L);
-	hwstats->bprc += rd64(wx, WX_RX_BC_FRAMES_GOOD_L);
-	hwstats->bptc += rd64(wx, WX_TX_BC_FRAMES_GOOD_L);
-	hwstats->mprc += rd64(wx, WX_RX_MC_FRAMES_GOOD_L);
-	hwstats->mptc += rd64(wx, WX_TX_MC_FRAMES_GOOD_L);
-	hwstats->roc += rd32(wx, WX_RX_OVERSIZE_FRAMES_GOOD);
-	hwstats->ruc += rd32(wx, WX_RX_UNDERSIZE_FRAMES_GOOD);
-	if (wx->mac.type >= wx_mac_aml)
-		hwstats->lxonrxc += rd32_wrap(wx, WX_MAC_LXONRXC_AML,
-					      &wx->last_stats.lxonrxc);
-	else
-		hwstats->lxonrxc += rd32(wx, WX_MAC_LXONRXC);
-	hwstats->lxontxc += rd32(wx, WX_RDB_LXONTXC);
-	hwstats->lxofftxc += rd32(wx, WX_RDB_LXOFFTXC);
-	hwstats->o2bgptc += rd32(wx, WX_TDM_OS2BMC_CNT);
-	hwstats->b2ospc += rd32(wx, WX_MNG_BMC2OS_CNT);
-	hwstats->o2bspc += rd32(wx, WX_MNG_OS2BMC_CNT);
-	hwstats->b2ogprc += rd32(wx, WX_RDM_BMC2OS_CNT);
-	hwstats->rdmdrop += rd32(wx, WX_RDM_DRP_PKT);
+	if (wx->pdev->is_physfn) {
+		wx_update_xoff_rx_lfc(wx);
+
+		hwstats->gprc += rd32(wx, WX_RDM_PKT_CNT);
+		hwstats->gptc += rd32(wx, WX_TDM_PKT_CNT);
+		hwstats->gorc += rd64(wx, WX_RDM_BYTE_CNT_LSB);
+		hwstats->gotc += rd64(wx, WX_TDM_BYTE_CNT_LSB);
+		hwstats->tpr += rd64(wx, WX_RX_FRAME_CNT_GOOD_BAD_L);
+		hwstats->tpt += rd64(wx, WX_TX_FRAME_CNT_GOOD_BAD_L);
+		hwstats->crcerrs += rd64(wx, WX_RX_CRC_ERROR_FRAMES_L);
+		hwstats->rlec += rd64(wx, WX_RX_LEN_ERROR_FRAMES_L);
+		hwstats->bprc += rd64(wx, WX_RX_BC_FRAMES_GOOD_L);
+		hwstats->bptc += rd64(wx, WX_TX_BC_FRAMES_GOOD_L);
+		hwstats->mprc += rd64(wx, WX_RX_MC_FRAMES_GOOD_L);
+		hwstats->mptc += rd64(wx, WX_TX_MC_FRAMES_GOOD_L);
+		hwstats->roc += rd32(wx, WX_RX_OVERSIZE_FRAMES_GOOD);
+		hwstats->ruc += rd32(wx, WX_RX_UNDERSIZE_FRAMES_GOOD);
+		if (wx->mac.type >= wx_mac_aml)
+			hwstats->lxonrxc += rd32_wrap(wx, WX_MAC_LXONRXC_AML,
+						&wx->last_stats.lxonrxc);
+		else
+			hwstats->lxonrxc += rd32(wx, WX_MAC_LXONRXC);
+		hwstats->lxontxc += rd32(wx, WX_RDB_LXONTXC);
+		hwstats->lxofftxc += rd32(wx, WX_RDB_LXOFFTXC);
+		hwstats->o2bgptc += rd32(wx, WX_TDM_OS2BMC_CNT);
+		hwstats->b2ospc += rd32(wx, WX_MNG_BMC2OS_CNT);
+		hwstats->o2bspc += rd32(wx, WX_MNG_OS2BMC_CNT);
+		hwstats->b2ogprc += rd32(wx, WX_RDM_BMC2OS_CNT);
+		hwstats->rdmdrop += rd32(wx, WX_RDM_DRP_PKT);
+
+		if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags)) {
+			hwstats->fdirmatch += rd32(wx, WX_RDB_FDIR_MATCH);
+			hwstats->fdirmiss += rd32(wx, WX_RDB_FDIR_MISS);
+		}
 
-	if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags)) {
-		hwstats->fdirmatch += rd32(wx, WX_RDB_FDIR_MATCH);
-		hwstats->fdirmiss += rd32(wx, WX_RDB_FDIR_MISS);
+		for (i = wx->num_vfs * wx->num_rx_queues_per_pool;
+		     i < wx->mac.max_rx_queues; i++)
+			hwstats->qmprc += rd32_wrap(wx, WX_PX_MPRC(i),
+						&wx->last_stats.qmprc[i]);
 	}
-
-	for (i = wx->num_vfs * wx->num_rx_queues_per_pool;
-	     i < wx->mac.max_rx_queues; i++)
-		hwstats->qmprc += rd32_wrap(wx, WX_PX_MPRC(i),
-					    &wx->last_stats.qmprc[i]);
-
 	spin_unlock(&wx->hw_stats_lock);
 }
 EXPORT_SYMBOL(wx_update_stats);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
index a3361696b783..c2c748d6420a 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
@@ -5,6 +5,7 @@
 #include <linux/pci.h>
 
 #include "wx_type.h"
+#include "wx_hw.h"
 #include "wx_mbx.h"
 #include "wx_lib.h"
 #include "wx_vf.h"
@@ -332,6 +333,7 @@ void wxvf_down(struct wx *wx)
 	netif_tx_disable(netdev);
 	netif_carrier_off(netdev);
 	wx_napi_disable_all(wx);
+	wx_update_stats(wx);
 	wx_reset_vf(wx);
 
 	wx_clean_all_tx_rings(wx);
@@ -405,6 +407,7 @@ static void wxvf_service_task(struct work_struct *work)
 
 	wxvf_link_config_subtask(wx);
 	wxvf_reset_subtask(wx);
+	wx_update_stats(wx);
 	wx_service_event_complete(wx);
 }
 
@@ -415,3 +418,51 @@ void wxvf_init_service(struct wx *wx)
 	clear_bit(WX_STATE_SERVICE_SCHED, wx->state);
 }
 EXPORT_SYMBOL(wxvf_init_service);
+
+static void wxvf_get_queue_stats_rx(struct net_device *dev, int idx,
+				    struct netdev_queue_stats_rx *stats)
+{
+	struct wx *wx = netdev_priv(dev);
+	struct wx_ring *ring = wx->rx_ring[idx];
+
+	stats->packets = ring->stats.packets;
+	stats->bytes = ring->stats.bytes;
+	stats->alloc_fail = wx->alloc_rx_buff_failed;
+	stats->csum_complete = wx->hw_csum_rx_good;
+	stats->csum_bad = wx->hw_csum_rx_error;
+}
+
+static void wxvf_get_queue_stats_tx(struct net_device *dev, int idx,
+				    struct netdev_queue_stats_tx *stats)
+{
+	struct wx *wx = netdev_priv(dev);
+	struct wx_ring *ring = wx->tx_ring[idx];
+
+	stats->packets = ring->stats.packets;
+	stats->bytes = ring->stats.bytes;
+}
+
+static void wxvf_get_base_stats(struct net_device *dev,
+				struct netdev_queue_stats_rx *rx,
+				struct netdev_queue_stats_tx *tx)
+{
+	rx->bytes = 0;
+	rx->packets = 0;
+	rx->alloc_fail = 0;
+	rx->csum_complete = 0;
+	rx->csum_bad = 0;
+	tx->bytes = 0;
+	tx->packets = 0;
+}
+
+static const struct netdev_stat_ops wxvf_stat_ops = {
+	.get_queue_stats_rx  = wxvf_get_queue_stats_rx,
+	.get_queue_stats_tx  = wxvf_get_queue_stats_tx,
+	.get_base_stats      = wxvf_get_base_stats,
+};
+
+void wx_set_stat_ops_vf(struct net_device *netdev)
+{
+	netdev->stat_ops = &wxvf_stat_ops;
+}
+EXPORT_SYMBOL(wx_set_stat_ops_vf);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.h b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.h
index d45d5d8ac3ab..4367505a7b8f 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.h
@@ -20,5 +20,6 @@ int wxvf_open(struct net_device *netdev);
 void wxvf_down(struct wx *wx);
 int wxvf_close(struct net_device *netdev);
 void wxvf_init_service(struct wx *wx);
+void wx_set_stat_ops_vf(struct net_device *netdev);
 
 #endif /* _WX_VF_COMMON_H_ */
diff --git a/drivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c b/drivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c
index d79cf8d8484f..69765b6bb8c3 100644
--- a/drivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c
+++ b/drivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c
@@ -189,6 +189,7 @@ static int ngbevf_probe(struct pci_dev *pdev,
 
 	wx->driver_name = KBUILD_MODNAME;
 	wx_set_ethtool_ops_vf(netdev);
+	wx_set_stat_ops_vf(netdev);
 	netdev->netdev_ops = &ngbevf_netdev_ops;
 
 	/* setup the private structure */
diff --git a/drivers/net/ethernet/wangxun/txgbevf/txgbevf_main.c b/drivers/net/ethernet/wangxun/txgbevf/txgbevf_main.c
index 8b16b900820a..c7f0f7e1f54c 100644
--- a/drivers/net/ethernet/wangxun/txgbevf/txgbevf_main.c
+++ b/drivers/net/ethernet/wangxun/txgbevf/txgbevf_main.c
@@ -7,6 +7,7 @@
 #include <linux/netdevice.h>
 #include <linux/string.h>
 #include <linux/etherdevice.h>
+#include <net/netdev_queues.h>
 
 #include "../libwx/wx_type.h"
 #include "../libwx/wx_hw.h"
@@ -254,6 +255,7 @@ static int txgbevf_probe(struct pci_dev *pdev,
 
 	wx->driver_name = KBUILD_MODNAME;
 	wx_set_ethtool_ops_vf(netdev);
+	wx_set_stat_ops_vf(netdev);
 	netdev->netdev_ops = &txgbevf_netdev_ops;
 
 	/* setup the private structure */
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH net-next v2 3/3] net: libwx: support vf hardware statistics
  2026-05-25 10:11 ` [PATCH net-next v2 3/3] net: libwx: support vf hardware statistics Mengyuan Lou
@ 2026-05-27  1:49   ` Jakub Kicinski
  0 siblings, 0 replies; 5+ messages in thread
From: Jakub Kicinski @ 2026-05-27  1:49 UTC (permalink / raw)
  To: Mengyuan Lou; +Cc: netdev, jiawenwu, duanqiangwen

On Mon, 25 May 2026 18:11:15 +0800 Mengyuan Lou wrote:
> Add support to show hardware statistics for ethtool -S ethx.

Sadly this does not build. When you repost I think it would be good
to split this patch into two - one for ethtool -S and one for 
the queue stats via the netdev API.

../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:423:16: warning: declaration of 'struct netdev_queue_stats_rx' will not be visible outside of this function [-Wvisibility]
  423 |                                     struct netdev_queue_stats_rx *stats)
      |                                            ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:428:7: error: incomplete definition of type 'struct netdev_queue_stats_rx'
  428 |         stats->packets = ring->stats.packets;
      |         ~~~~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:423:16: note: forward declaration of 'struct netdev_queue_stats_rx'
  423 |                                     struct netdev_queue_stats_rx *stats)
      |                                            ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:429:7: error: incomplete definition of type 'struct netdev_queue_stats_rx'
  429 |         stats->bytes = ring->stats.bytes;
      |         ~~~~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:423:16: note: forward declaration of 'struct netdev_queue_stats_rx'
  423 |                                     struct netdev_queue_stats_rx *stats)
      |                                            ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:430:7: error: incomplete definition of type 'struct netdev_queue_stats_rx'
  430 |         stats->alloc_fail = wx->alloc_rx_buff_failed;
      |         ~~~~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:423:16: note: forward declaration of 'struct netdev_queue_stats_rx'
  423 |                                     struct netdev_queue_stats_rx *stats)
      |                                            ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:431:7: error: incomplete definition of type 'struct netdev_queue_stats_rx'
  431 |         stats->csum_complete = wx->hw_csum_rx_good;
      |         ~~~~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:423:16: note: forward declaration of 'struct netdev_queue_stats_rx'
  423 |                                     struct netdev_queue_stats_rx *stats)
      |                                            ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:432:7: error: incomplete definition of type 'struct netdev_queue_stats_rx'
  432 |         stats->csum_bad = wx->hw_csum_rx_error;
      |         ~~~~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:423:16: note: forward declaration of 'struct netdev_queue_stats_rx'
  423 |                                     struct netdev_queue_stats_rx *stats)
      |                                            ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:436:16: warning: declaration of 'struct netdev_queue_stats_tx' will not be visible outside of this function [-Wvisibility]
  436 |                                     struct netdev_queue_stats_tx *stats)
      |                                            ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:441:7: error: incomplete definition of type 'struct netdev_queue_stats_tx'
  441 |         stats->packets = ring->stats.packets;
      |         ~~~~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:436:16: note: forward declaration of 'struct netdev_queue_stats_tx'
  436 |                                     struct netdev_queue_stats_tx *stats)
      |                                            ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:442:7: error: incomplete definition of type 'struct netdev_queue_stats_tx'
  442 |         stats->bytes = ring->stats.bytes;
      |         ~~~~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:436:16: note: forward declaration of 'struct netdev_queue_stats_tx'
  436 |                                     struct netdev_queue_stats_tx *stats)
      |                                            ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:446:12: warning: declaration of 'struct netdev_queue_stats_rx' will not be visible outside of this function [-Wvisibility]
  446 |                                 struct netdev_queue_stats_rx *rx,
      |                                        ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:447:12: warning: declaration of 'struct netdev_queue_stats_tx' will not be visible outside of this function [-Wvisibility]
  447 |                                 struct netdev_queue_stats_tx *tx)
      |                                        ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:449:4: error: incomplete definition of type 'struct netdev_queue_stats_rx'
  449 |         rx->bytes = 0;
      |         ~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:446:12: note: forward declaration of 'struct netdev_queue_stats_rx'
  446 |                                 struct netdev_queue_stats_rx *rx,
      |                                        ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:450:4: error: incomplete definition of type 'struct netdev_queue_stats_rx'
  450 |         rx->packets = 0;
      |         ~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:446:12: note: forward declaration of 'struct netdev_queue_stats_rx'
  446 |                                 struct netdev_queue_stats_rx *rx,
      |                                        ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:451:4: error: incomplete definition of type 'struct netdev_queue_stats_rx'
  451 |         rx->alloc_fail = 0;
      |         ~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:446:12: note: forward declaration of 'struct netdev_queue_stats_rx'
  446 |                                 struct netdev_queue_stats_rx *rx,
      |                                        ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:452:4: error: incomplete definition of type 'struct netdev_queue_stats_rx'
  452 |         rx->csum_complete = 0;
      |         ~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:446:12: note: forward declaration of 'struct netdev_queue_stats_rx'
  446 |                                 struct netdev_queue_stats_rx *rx,
      |                                        ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:453:4: error: incomplete definition of type 'struct netdev_queue_stats_rx'
  453 |         rx->csum_bad = 0;
      |         ~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:446:12: note: forward declaration of 'struct netdev_queue_stats_rx'
  446 |                                 struct netdev_queue_stats_rx *rx,
      |                                        ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:454:4: error: incomplete definition of type 'struct netdev_queue_stats_tx'
  454 |         tx->bytes = 0;
      |         ~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:447:12: note: forward declaration of 'struct netdev_queue_stats_tx'
  447 |                                 struct netdev_queue_stats_tx *tx)
      |                                        ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:455:4: error: incomplete definition of type 'struct netdev_queue_stats_tx'
  455 |         tx->packets = 0;
      |         ~~^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:447:12: note: forward declaration of 'struct netdev_queue_stats_tx'
  447 |                                 struct netdev_queue_stats_tx *tx)
      |                                        ^
../drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:458:37: error: variable has incomplete type 'const struct netdev_stat_ops'
  458 | static const struct netdev_stat_ops wxvf_stat_ops = {
      |                                     ^
../include/linux/netdevice.h:2452:15: note: forward declaration of 'struct netdev_stat_ops'
 2452 |         const struct netdev_stat_ops *stat_ops;
      |                      ^
-- 
pw-bot: cr

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-05-27  1:49 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-25 10:11 [PATCH net-next v2 0/3] net: libwx: improve VF ethtool support Mengyuan Lou
2026-05-25 10:11 ` [PATCH net-next v2 1/3] net: libwx: add support for set_ringparam in wx_ethtool_ops_vf Mengyuan Lou
2026-05-25 10:11 ` [PATCH net-next v2 2/3] net: libwx: add support for set_coalesce " Mengyuan Lou
2026-05-25 10:11 ` [PATCH net-next v2 3/3] net: libwx: support vf hardware statistics Mengyuan Lou
2026-05-27  1:49   ` Jakub Kicinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox