All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v4 0/3] net: libwx: improve VF ethtool support
@ 2026-06-08 10:39 Mengyuan Lou
  2026-06-08 10:39 ` [PATCH net-next v4 1/3] net: libwx: add support for set_ringparam in wx_ethtool_ops_vf Mengyuan Lou
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Mengyuan Lou @ 2026-06-08 10:39 UTC (permalink / raw)
  To: netdev; +Cc: jiawenwu, duanqiangwen, horms, kuba, 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
per-queue 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 statistics support so ethtool -S can
report useful runtime counters for VF interfaces.

Changelog:
v4:
  sashiko: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260529075147.88398-1-mengyuanlou%40net-swift.com
- Patch 2:
  PF and VF share the same ITR value range. Update wx_write_eitr_vf() to apply
  identical range clamping as the PF path, ensuring consistent coalesce behavior
  across both device types.
- Patch 3:
  Remove wx_update_stats in wxvf_down.
  Replace both WX_GLOBAL_STATS_LEN and WX_STATS_LEN macros with type-safe
  static inline helpers wx_global_stats_len() and wx_stats_len().
v3: https://lore.kernel.org/all/20260529075147.88398-1-mengyuanlou@net-swift.com
- Patch 3:
  Drop netdev_stat_ops support from this patch.
v2: https://lore.kernel.org/all/20260525101115.13151-1-mengyuanlou@net-swift.com
- Patch 3:
  Remove some stats which can be replaced by standard stats defined in
  include/net/netdev_queues.h.
- Patch 1:
  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 per-queue statistics via ethtool -S

 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 115 ++++++++++++++++--
 drivers/net/ethernet/wangxun/libwx/wx_hw.c    |   4 +
 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 |   6 +-
 .../net/ethernet/wangxun/libwx/wx_vf_common.h |   2 +
 .../net/ethernet/wangxun/libwx/wx_vf_lib.c    |  13 +-
 7 files changed, 133 insertions(+), 20 deletions(-)

-- 
2.30.1


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

* [PATCH net-next v4 1/3] net: libwx: add support for set_ringparam in wx_ethtool_ops_vf
  2026-06-08 10:39 [PATCH net-next v4 0/3] net: libwx: improve VF ethtool support Mengyuan Lou
@ 2026-06-08 10:39 ` Mengyuan Lou
  2026-06-08 10:39 ` [PATCH net-next v4 2/3] net: libwx: add support for set_coalesce " Mengyuan Lou
  2026-06-08 10:39 ` [PATCH net-next v4 3/3] net: libwx: support vf per-queue statistics via ethtool -S Mengyuan Lou
  2 siblings, 0 replies; 7+ messages in thread
From: Mengyuan Lou @ 2026-06-08 10:39 UTC (permalink / raw)
  To: netdev; +Cc: jiawenwu, duanqiangwen, horms, kuba, 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 d042567b8128..2e5dba88d04a 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -3248,8 +3248,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;
 
@@ -3271,7 +3271,7 @@ void wx_set_ring(struct wx *wx, u32 new_tx_count,
 					i--;
 					wx_free_tx_resources(&temp_ring[i]);
 				}
-				return;
+				return err;
 			}
 		}
 
@@ -3299,7 +3299,7 @@ void wx_set_ring(struct wx *wx, u32 new_tx_count,
 					i--;
 					wx_free_rx_resources(&temp_ring[i]);
 				}
-				return;
+				return err;
 			}
 		}
 
@@ -3311,6 +3311,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 0d2db8d38cd5..26de78e9a69e 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);
@@ -324,7 +324,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] 7+ messages in thread

* [PATCH net-next v4 2/3] net: libwx: add support for set_coalesce in wx_ethtool_ops_vf
  2026-06-08 10:39 [PATCH net-next v4 0/3] net: libwx: improve VF ethtool support Mengyuan Lou
  2026-06-08 10:39 ` [PATCH net-next v4 1/3] net: libwx: add support for set_ringparam in wx_ethtool_ops_vf Mengyuan Lou
@ 2026-06-08 10:39 ` Mengyuan Lou
  2026-06-08 10:39 ` [PATCH net-next v4 3/3] net: libwx: support vf per-queue statistics via ethtool -S Mengyuan Lou
  2 siblings, 0 replies; 7+ messages in thread
From: Mengyuan Lou @ 2026-06-08 10:39 UTC (permalink / raw)
  To: netdev; +Cc: jiawenwu, duanqiangwen, horms, kuba, 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 ++++++-
 drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c  | 13 ++++++++++++-
 2 files changed, 18 insertions(+), 2 deletions(-)

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,
 };
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c
index aa8be036956c..7325b475ee10 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c
@@ -16,7 +16,18 @@ void wx_write_eitr_vf(struct wx_q_vector *q_vector)
 	int v_idx = q_vector->v_idx;
 	u32 itr_reg;
 
-	itr_reg = q_vector->itr & WX_VXITR_MASK;
+	switch (wx->mac.type) {
+	case wx_mac_sp:
+		itr_reg = q_vector->itr & WX_SP_MAX_EITR;
+		break;
+	case wx_mac_aml:
+	case wx_mac_aml40:
+		itr_reg = (q_vector->itr >> 3) & WX_AML_MAX_EITR;
+		break;
+	default:
+		itr_reg = q_vector->itr & WX_EM_MAX_EITR;
+		break;
+	}
 
 	/* set the WDIS bit to not clear the timer bits and cause an
 	 * immediate assertion of the interrupt
-- 
2.30.1


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

* [PATCH net-next v4 3/3] net: libwx: support vf per-queue statistics via ethtool -S
  2026-06-08 10:39 [PATCH net-next v4 0/3] net: libwx: improve VF ethtool support Mengyuan Lou
  2026-06-08 10:39 ` [PATCH net-next v4 1/3] net: libwx: add support for set_ringparam in wx_ethtool_ops_vf Mengyuan Lou
  2026-06-08 10:39 ` [PATCH net-next v4 2/3] net: libwx: add support for set_coalesce " Mengyuan Lou
@ 2026-06-08 10:39 ` Mengyuan Lou
  2026-06-11  6:48   ` Simon Horman
  2 siblings, 1 reply; 7+ messages in thread
From: Mengyuan Lou @ 2026-06-08 10:39 UTC (permalink / raw)
  To: netdev; +Cc: jiawenwu, duanqiangwen, horms, kuba, Mengyuan Lou

Add per-queue TX/RX packet and byte counters to the VF ethtool stats
table.
The stats length is now dynamically determined based on whether the
device is a VF or PF via wx_stats_len().

Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
---
 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 48 +++++++++++++++----
 drivers/net/ethernet/wangxun/libwx/wx_hw.c    |  4 ++
 .../net/ethernet/wangxun/libwx/wx_vf_common.c |  2 +
 3 files changed, 44 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index 30c6ef6103ac..86f6ac63acf7 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,15 +73,26 @@ 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_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)
+
+static inline unsigned int wx_global_stats_len(const struct wx *wx)
+{
+	return wx->pdev->is_virtfn ?
+	       ARRAY_SIZE(wx_gstrings_stats_vf) : ARRAY_SIZE(wx_gstrings_stats);
+}
+
+static inline unsigned int wx_stats_len(const struct wx *wx)
+{
+	struct net_device *netdev = wx->netdev;
+
+	return wx_global_stats_len(wx) + WX_QUEUE_STATS_LEN;
+}
 
 int wx_get_sset_count(struct net_device *netdev, int sset)
 {
 	struct wx *wx = netdev_priv(netdev);
-	int len = WX_STATS_LEN;
+	int len = wx_stats_len(wx);
 
 	switch (sset) {
 	case ETH_SS_STATS:
@@ -100,8 +115,11 @@ 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);
+		for (i = 0; i < wx_global_stats_len(wx); i++)
+			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);
@@ -134,10 +152,16 @@ 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;
+	for (i = 0; i < wx_global_stats_len(wx); i++) {
+		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 +243,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(wx);
 	if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags))
 		stats_len += WX_FDIR_STATS_LEN;
 
@@ -851,6 +876,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 260e14d5d541..ce172b6deb80 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -2917,6 +2917,9 @@ void wx_update_stats(struct wx *wx)
 	wx->restart_queue = restart_queue;
 	wx->tx_busy = tx_busy;
 
+	if (wx->pdev->is_virtfn)
+		goto skip_hw_stats;
+
 	wx_update_xoff_rx_lfc(wx);
 
 	hwstats->gprc += rd32(wx, WX_RDM_PKT_CNT);
@@ -2956,6 +2959,7 @@ void wx_update_stats(struct wx *wx)
 		hwstats->qmprc += rd32_wrap(wx, WX_PX_MPRC(i),
 					    &wx->last_stats.qmprc[i]);
 
+skip_hw_stats:
 	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 26de78e9a69e..1d84fe35d7d9 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"
@@ -409,6 +410,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);
 }
 
-- 
2.30.1


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

* Re: [PATCH net-next v4 3/3] net: libwx: support vf per-queue statistics via ethtool -S
  2026-06-08 10:39 ` [PATCH net-next v4 3/3] net: libwx: support vf per-queue statistics via ethtool -S Mengyuan Lou
@ 2026-06-11  6:48   ` Simon Horman
  2026-06-11  8:46     ` mengyuanlou
  0 siblings, 1 reply; 7+ messages in thread
From: Simon Horman @ 2026-06-11  6:48 UTC (permalink / raw)
  To: Mengyuan Lou; +Cc: netdev, jiawenwu, duanqiangwen, kuba

On Mon, Jun 08, 2026 at 06:39:46PM +0800, Mengyuan Lou wrote:
> Add per-queue TX/RX packet and byte counters to the VF ethtool stats
> table.
> The stats length is now dynamically determined based on whether the
> device is a VF or PF via wx_stats_len().
> 
> Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
> ---
>  .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 48 +++++++++++++++----
>  drivers/net/ethernet/wangxun/libwx/wx_hw.c    |  4 ++
>  .../net/ethernet/wangxun/libwx/wx_vf_common.c |  2 +
>  3 files changed, 44 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
> index 30c6ef6103ac..86f6ac63acf7 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),
> +};
> +

The AI-generated review available at https://netdev-ai.bots.linux.dev/sashiko/
flags that this is user-exposed and probably could benefit from a bit
more explanation in the patch description.

>  static const struct wx_stats wx_gstrings_fdir_stats[] = {
>  	WX_STAT("fdir_match", stats.fdirmatch),
>  	WX_STAT("fdir_miss", stats.fdirmiss),
> @@ -69,15 +73,26 @@ 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_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)
> +
> +static inline unsigned int wx_global_stats_len(const struct wx *wx)
> +{
> +	return wx->pdev->is_virtfn ?
> +	       ARRAY_SIZE(wx_gstrings_stats_vf) : ARRAY_SIZE(wx_gstrings_stats);
> +}

Please don't use the inline keyword in .c files unless there is a
demonstrable - usually performance - reason to do so. Rather, please
let the compiler inline code (or not).

It is of course fine to use the inline keyword in .h files.

> +
> +static inline unsigned int wx_stats_len(const struct wx *wx)
> +{
> +	struct net_device *netdev = wx->netdev;

netdev seems unused.

Flagged by AI-generated review on sashiko.dev 

> +
> +	return wx_global_stats_len(wx) + WX_QUEUE_STATS_LEN;
> +}
>  
>  int wx_get_sset_count(struct net_device *netdev, int sset)
>  {
>  	struct wx *wx = netdev_priv(netdev);
> -	int len = WX_STATS_LEN;
> +	int len = wx_stats_len(wx);
>  
>  	switch (sset) {
>  	case ETH_SS_STATS:
> @@ -100,8 +115,11 @@ 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);
> +		for (i = 0; i < wx_global_stats_len(wx); i++)
> +			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);

The AI-generated review at https://netdev-ai.bots.linux.dev/sashiko/ also
flags that these seem to cover statistics that can be exposed via
netdev_stat_ops, which is preferred.

If consistency with the PF stats is desired for VF stats, then perhaps
netdev_stat_ops can also be implemented for PF queues.

>  		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);

...

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

* Re: [PATCH net-next v4 3/3] net: libwx: support vf per-queue statistics via ethtool -S
  2026-06-11  6:48   ` Simon Horman
@ 2026-06-11  8:46     ` mengyuanlou
  2026-06-11 15:18       ` Simon Horman
  0 siblings, 1 reply; 7+ messages in thread
From: mengyuanlou @ 2026-06-11  8:46 UTC (permalink / raw)
  To: Simon Horman; +Cc: netdev, jiawenwu, duanqiangwen, kuba



> 2026年6月11日 14:48,Simon Horman <horms@kernel.org> 写道:
> 
> On Mon, Jun 08, 2026 at 06:39:46PM +0800, Mengyuan Lou wrote:
>> Add per-queue TX/RX packet and byte counters to the VF ethtool stats
>> table.
>> The stats length is now dynamically determined based on whether the
>> device is a VF or PF via wx_stats_len().
>> 
>> Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
>> ---
>> .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 48 +++++++++++++++----
>> drivers/net/ethernet/wangxun/libwx/wx_hw.c    |  4 ++
>> .../net/ethernet/wangxun/libwx/wx_vf_common.c |  2 +
>> 3 files changed, 44 insertions(+), 10 deletions(-)
>> 
>> diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
>> index 30c6ef6103ac..86f6ac63acf7 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),
>> +};
>> +
> 
> The AI-generated review available at https://netdev-ai.bots.linux.dev/sashiko/
> flags that this is user-exposed and probably could benefit from a bit
> more explanation in the patch description.
> 
>> static const struct wx_stats wx_gstrings_fdir_stats[] = {
>> WX_STAT("fdir_match", stats.fdirmatch),
>> WX_STAT("fdir_miss", stats.fdirmiss),
>> @@ -69,15 +73,26 @@ 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_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)
>> +
>> +static inline unsigned int wx_global_stats_len(const struct wx *wx)
>> +{
>> + return wx->pdev->is_virtfn ?
>> +        ARRAY_SIZE(wx_gstrings_stats_vf) : ARRAY_SIZE(wx_gstrings_stats);
>> +}
> 
> Please don't use the inline keyword in .c files unless there is a
> demonstrable - usually performance - reason to do so. Rather, please
> let the compiler inline code (or not).
> 
> It is of course fine to use the inline keyword in .h files.

Ok,I will drop it.
> 
>> +
>> +static inline unsigned int wx_stats_len(const struct wx *wx)
>> +{
>> + struct net_device *netdev = wx->netdev;
> 
> netdev seems unused.
> 
> Flagged by AI-generated review on sashiko.dev 


#define WX_NUM_RX_QUEUES netdev->num_tx_queues
#define WX_NUM_TX_QUEUES netdev->num_tx_queues

#define WX_QUEUE_STATS_LEN ( \
(WX_NUM_TX_QUEUES + WX_NUM_RX_QUEUES) * \
(sizeof(struct wx_queue_stats) / sizeof(u64)))

netdev is used.

> 
>> +
>> + return wx_global_stats_len(wx) + WX_QUEUE_STATS_LEN;
>> +}
>> 
>> int wx_get_sset_count(struct net_device *netdev, int sset)
>> {
>> struct wx *wx = netdev_priv(netdev);
>> - int len = WX_STATS_LEN;
>> + int len = wx_stats_len(wx);
>> 
>> switch (sset) {
>> case ETH_SS_STATS:
>> @@ -100,8 +115,11 @@ 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);
>> + for (i = 0; i < wx_global_stats_len(wx); i++)
>> + 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);
> 
> The AI-generated review at https://netdev-ai.bots.linux.dev/sashiko/ also
> flags that these seem to cover statistics that can be exposed via
> netdev_stat_ops, which is preferred.
> 
> If consistency with the PF stats is desired for VF stats, then perhaps
> netdev_stat_ops can also be implemented for PF queues.

Netdev_stat_ops will add in another. changlogs v3 just remove it.
> 
>> 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);
> 
> ...



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

* Re: [PATCH net-next v4 3/3] net: libwx: support vf per-queue statistics via ethtool -S
  2026-06-11  8:46     ` mengyuanlou
@ 2026-06-11 15:18       ` Simon Horman
  0 siblings, 0 replies; 7+ messages in thread
From: Simon Horman @ 2026-06-11 15:18 UTC (permalink / raw)
  To: mengyuanlou@net-swift.com; +Cc: netdev, jiawenwu, duanqiangwen, kuba

On Thu, Jun 11, 2026 at 04:46:08PM +0800, mengyuanlou@net-swift.com wrote:
> 
> 
> > 2026年6月11日 14:48,Simon Horman <horms@kernel.org> 写道:
> > 
> > On Mon, Jun 08, 2026 at 06:39:46PM +0800, Mengyuan Lou wrote:
> >> Add per-queue TX/RX packet and byte counters to the VF ethtool stats
> >> table.
> >> The stats length is now dynamically determined based on whether the
> >> device is a VF or PF via wx_stats_len().
> >> 
> >> Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
> >> ---
> >> .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 48 +++++++++++++++----
> >> drivers/net/ethernet/wangxun/libwx/wx_hw.c    |  4 ++
> >> .../net/ethernet/wangxun/libwx/wx_vf_common.c |  2 +
> >> 3 files changed, 44 insertions(+), 10 deletions(-)
> >> 
> >> diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
> >> index 30c6ef6103ac..86f6ac63acf7 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),
> >> +};
> >> +
> > 
> > The AI-generated review available at https://netdev-ai.bots.linux.dev/sashiko/
> > flags that this is user-exposed and probably could benefit from a bit
> > more explanation in the patch description.
> > 
> >> static const struct wx_stats wx_gstrings_fdir_stats[] = {
> >> WX_STAT("fdir_match", stats.fdirmatch),
> >> WX_STAT("fdir_miss", stats.fdirmiss),
> >> @@ -69,15 +73,26 @@ 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_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)
> >> +
> >> +static inline unsigned int wx_global_stats_len(const struct wx *wx)
> >> +{
> >> + return wx->pdev->is_virtfn ?
> >> +        ARRAY_SIZE(wx_gstrings_stats_vf) : ARRAY_SIZE(wx_gstrings_stats);
> >> +}
> > 
> > Please don't use the inline keyword in .c files unless there is a
> > demonstrable - usually performance - reason to do so. Rather, please
> > let the compiler inline code (or not).
> > 
> > It is of course fine to use the inline keyword in .h files.
> 
> Ok,I will drop it.
> > 
> >> +
> >> +static inline unsigned int wx_stats_len(const struct wx *wx)
> >> +{
> >> + struct net_device *netdev = wx->netdev;
> > 
> > netdev seems unused.
> > 
> > Flagged by AI-generated review on sashiko.dev 
> 
> 
> #define WX_NUM_RX_QUEUES netdev->num_tx_queues
> #define WX_NUM_TX_QUEUES netdev->num_tx_queues
> 
> #define WX_QUEUE_STATS_LEN ( \
> (WX_NUM_TX_QUEUES + WX_NUM_RX_QUEUES) * \
> (sizeof(struct wx_queue_stats) / sizeof(u64)))
> 
> netdev is used.

Thanks, sorry for missing that.

Perhaps it would clearer if WX_NUM_RX_QUEUES and WX_NUM_TX_QUEUES took
arguments. And in that case, perhaps were functions rather than macros.
But maybe that is orthogonal to this patch-set.

> 
> > 
> >> +
> >> + return wx_global_stats_len(wx) + WX_QUEUE_STATS_LEN;
> >> +}
> >> 
> >> int wx_get_sset_count(struct net_device *netdev, int sset)
> >> {
> >> struct wx *wx = netdev_priv(netdev);
> >> - int len = WX_STATS_LEN;
> >> + int len = wx_stats_len(wx);
> >> 
> >> switch (sset) {
> >> case ETH_SS_STATS:
> >> @@ -100,8 +115,11 @@ 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);
> >> + for (i = 0; i < wx_global_stats_len(wx); i++)
> >> + 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);
> > 
> > The AI-generated review at https://netdev-ai.bots.linux.dev/sashiko/ also
> > flags that these seem to cover statistics that can be exposed via
> > netdev_stat_ops, which is preferred.
> > 
> > If consistency with the PF stats is desired for VF stats, then perhaps
> > netdev_stat_ops can also be implemented for PF queues.
> 
> Netdev_stat_ops will add in another. changlogs v3 just remove it.
> > 
> >> 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);
> > 
> > ...
> 
> 

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

end of thread, other threads:[~2026-06-11 15:18 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-08 10:39 [PATCH net-next v4 0/3] net: libwx: improve VF ethtool support Mengyuan Lou
2026-06-08 10:39 ` [PATCH net-next v4 1/3] net: libwx: add support for set_ringparam in wx_ethtool_ops_vf Mengyuan Lou
2026-06-08 10:39 ` [PATCH net-next v4 2/3] net: libwx: add support for set_coalesce " Mengyuan Lou
2026-06-08 10:39 ` [PATCH net-next v4 3/3] net: libwx: support vf per-queue statistics via ethtool -S Mengyuan Lou
2026-06-11  6:48   ` Simon Horman
2026-06-11  8:46     ` mengyuanlou
2026-06-11 15:18       ` Simon Horman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.