diff mbox series

[net,2/5] net: wangxun: fix error statistics when the device is reset

Message ID 20240416062952.14196-3-jiawenwu@trustnetic.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series Wangxun fixes | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 926 this patch: 926
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 6 of 6 maintainers
netdev/build_clang success Errors and warnings before: 937 this patch: 937
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 937 this patch: 937
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 129 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 22 this patch: 22
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-04-16--12-00 (tests: 957)

Commit Message

Jiawen Wu April 16, 2024, 6:29 a.m. UTC
Add flag for reset state to avoid reading statistics when hardware
is reset.

Fixes: 883b5984a5d2 ("net: wangxun: add ethtool_ops for ring parameters")
Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/ethernet/wangxun/libwx/wx_hw.c    |  3 +++
 drivers/net/ethernet/wangxun/libwx/wx_type.h  |  6 +++++
 .../net/ethernet/wangxun/ngbe/ngbe_ethtool.c  | 24 +++++++++++++++----
 .../ethernet/wangxun/txgbe/txgbe_ethtool.c    | 24 +++++++++++++++----
 4 files changed, 47 insertions(+), 10 deletions(-)

Comments

Francois Romieu April 16, 2024, 10:17 a.m. UTC | #1
Jiawen Wu <jiawenwu@trustnetic.com> :
> Add flag for reset state to avoid reading statistics when hardware
> is reset.
> 
> Fixes: 883b5984a5d2 ("net: wangxun: add ethtool_ops for ring parameters")
> Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
> ---
>  drivers/net/ethernet/wangxun/libwx/wx_hw.c    |  3 +++
>  drivers/net/ethernet/wangxun/libwx/wx_type.h  |  6 +++++
>  .../net/ethernet/wangxun/ngbe/ngbe_ethtool.c  | 24 +++++++++++++++----
>  .../ethernet/wangxun/txgbe/txgbe_ethtool.c    | 24 +++++++++++++++----
>  4 files changed, 47 insertions(+), 10 deletions(-)
> 
[...]
> diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
> index 786a652ae64f..0e85c5a6633e 100644
> --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
> +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
> @@ -52,7 +52,8 @@ static int ngbe_set_ringparam(struct net_device *netdev,
>  	struct wx *wx = netdev_priv(netdev);
>  	u32 new_rx_count, new_tx_count;
>  	struct wx_ring *temp_ring;
> -	int i;
> +	u8 timeout = 50;
> +	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);
> @@ -64,6 +65,15 @@ static int ngbe_set_ringparam(struct net_device *netdev,
>  	    new_rx_count == wx->rx_ring_count)
>  		return 0;
>  
> +	while (test_and_set_bit(WX_STATE_RESETTING, wx->state)) {
> +		timeout--;
> +		if (!timeout) {
> +			err = -EBUSY;
> +			goto clear_reset;
> +		}
> +		usleep_range(1000, 2000);
> +	}
> +

This code appears twice. It may be factored out.

[...]
> @@ -89,7 +101,9 @@ static int ngbe_set_ringparam(struct net_device *netdev,
>  	wx_configure(wx);
>  	ngbe_up(wx);
>  
> -	return 0;
> +clear_reset:
> +	clear_bit(WX_STATE_RESETTING, wx->state);
> +	return err;
>  }

This function always clears the bit but it does not necessarily owns it.
Andrew Lunn April 16, 2024, 2:56 p.m. UTC | #2
On Tue, Apr 16, 2024 at 02:29:49PM +0800, Jiawen Wu wrote:
> Add flag for reset state to avoid reading statistics when hardware
> is reset.

This explains the what, which you can also get by reading the code
change. The commit message should also explain the why? What goes
wrong if you read the statistics when the hardware is in reset? Do you
get 42 for every statistic? Does the hardware lockup and the reset
never completes?

      Andrew
Jiawen Wu April 24, 2024, 7:53 a.m. UTC | #3
On Tue, April 16, 2024 10:56 PM, Andrew Lunn wrote:
> On Tue, Apr 16, 2024 at 02:29:49PM +0800, Jiawen Wu wrote:
> > Add flag for reset state to avoid reading statistics when hardware
> > is reset.
> 
> This explains the what, which you can also get by reading the code
> change. The commit message should also explain the why? What goes
> wrong if you read the statistics when the hardware is in reset? Do you
> get 42 for every statistic? Does the hardware lockup and the reset
> never completes?

I think I should discard this patch, and add the resetting flag to the patch 5/5 to avoid
device reset collision. Since wx_update_stats() is called in txgbe_disable_device() while
device is resetting. And I haven't found a situation that causes statistics confusion.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 945c13d1a982..e4e6a14c4efc 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -2285,6 +2285,9 @@  void wx_update_stats(struct wx *wx)
 	u64 restart_queue = 0, tx_busy = 0;
 	u32 i;
 
+	if (test_bit(WX_STATE_RESETTING, wx->state))
+		return;
+
 	/* gather some stats to the wx struct that are per queue */
 	for (i = 0; i < wx->num_rx_queues; i++) {
 		struct wx_ring *rx_ring = wx->rx_ring[i];
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 1fdeb464d5f4..3726ec2fec06 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -982,8 +982,14 @@  struct wx_hw_stats {
 	u64 qmprc;
 };
 
+enum wx_state {
+	WX_STATE_RESETTING,
+	WX_STATE_NBITS,		/* must be last */
+};
+
 struct wx {
 	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+	DECLARE_BITMAP(state, WX_STATE_NBITS);
 
 	void *priv;
 	u8 __iomem *hw_addr;
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
index 786a652ae64f..0e85c5a6633e 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
@@ -52,7 +52,8 @@  static int ngbe_set_ringparam(struct net_device *netdev,
 	struct wx *wx = netdev_priv(netdev);
 	u32 new_rx_count, new_tx_count;
 	struct wx_ring *temp_ring;
-	int i;
+	u8 timeout = 50;
+	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);
@@ -64,6 +65,15 @@  static int ngbe_set_ringparam(struct net_device *netdev,
 	    new_rx_count == wx->rx_ring_count)
 		return 0;
 
+	while (test_and_set_bit(WX_STATE_RESETTING, wx->state)) {
+		timeout--;
+		if (!timeout) {
+			err = -EBUSY;
+			goto clear_reset;
+		}
+		usleep_range(1000, 2000);
+	}
+
 	if (!netif_running(wx->netdev)) {
 		for (i = 0; i < wx->num_tx_queues; i++)
 			wx->tx_ring[i]->count = new_tx_count;
@@ -72,14 +82,16 @@  static int ngbe_set_ringparam(struct net_device *netdev,
 		wx->tx_ring_count = new_tx_count;
 		wx->rx_ring_count = new_rx_count;
 
-		return 0;
+		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_array(i, sizeof(struct wx_ring), GFP_KERNEL);
-	if (!temp_ring)
-		return -ENOMEM;
+	if (!temp_ring) {
+		err = -ENOMEM;
+		goto clear_reset;
+	}
 
 	ngbe_down(wx);
 
@@ -89,7 +101,9 @@  static int ngbe_set_ringparam(struct net_device *netdev,
 	wx_configure(wx);
 	ngbe_up(wx);
 
-	return 0;
+clear_reset:
+	clear_bit(WX_STATE_RESETTING, wx->state);
+	return err;
 }
 
 static int ngbe_set_channels(struct net_device *dev,
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
index db675512ce4d..216599bbf9de 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
@@ -19,7 +19,8 @@  static int txgbe_set_ringparam(struct net_device *netdev,
 	struct wx *wx = netdev_priv(netdev);
 	u32 new_rx_count, new_tx_count;
 	struct wx_ring *temp_ring;
-	int i;
+	u8 timeout = 50;
+	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);
@@ -31,6 +32,15 @@  static int txgbe_set_ringparam(struct net_device *netdev,
 	    new_rx_count == wx->rx_ring_count)
 		return 0;
 
+	while (test_and_set_bit(WX_STATE_RESETTING, wx->state)) {
+		timeout--;
+		if (!timeout) {
+			err = -EBUSY;
+			goto clear_reset;
+		}
+		usleep_range(1000, 2000);
+	}
+
 	if (!netif_running(wx->netdev)) {
 		for (i = 0; i < wx->num_tx_queues; i++)
 			wx->tx_ring[i]->count = new_tx_count;
@@ -39,14 +49,16 @@  static int txgbe_set_ringparam(struct net_device *netdev,
 		wx->tx_ring_count = new_tx_count;
 		wx->rx_ring_count = new_rx_count;
 
-		return 0;
+		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_array(i, sizeof(struct wx_ring), GFP_KERNEL);
-	if (!temp_ring)
-		return -ENOMEM;
+	if (!temp_ring) {
+		err = -ENOMEM;
+		goto clear_reset;
+	}
 
 	txgbe_down(wx);
 
@@ -55,7 +67,9 @@  static int txgbe_set_ringparam(struct net_device *netdev,
 
 	txgbe_up(wx);
 
-	return 0;
+clear_reset:
+	clear_bit(WX_STATE_RESETTING, wx->state);
+	return err;
 }
 
 static int txgbe_set_channels(struct net_device *dev,