Re: [PATCH net-next] net: wangxun: protect ring accesses with READ- and WRITE_ONCE

Simon Horman <[email protected]>
Newsgroups gmane.linux.network
Message-ID <[email protected]>
On Thu, Aug 13, 2026 at 05:51:41PM +0800, Mengyuan Lou wrote:
> In wx_update_stats(), the ring pointers wx->rx_ring[i] and wx->tx_ring[i]
> can become NULL during queue teardown or reconfiguration (e.g., via
> wx_free_q_vector()).
> 
> READ_ONCE should be used when reading rings prior to accessing the
> statistics pointer to ensure protected access. As well as the
> corresponding WRITE_ONCE usage when allocating and freeing the rings.

Hi Mengyuan,

As observed in an AI-generated review of this patch [1], this patch is
doing a bit more than adding READ_ONCE/WRITE_ONCE.  It also adds an RCU
read-side critical section (the most important part of the change, IMHO),
and some NULL checks. It might be nice to extend this description somehow.

[1] https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260813095141.88227-1-mengyuanlou%40net-swift.com

> 
> Signed-off-by: Mengyuan Lou <[email protected]>
> ---
>  drivers/net/ethernet/wangxun/libwx/wx_hw.c  | 20 ++++++++++++++++----
>  drivers/net/ethernet/wangxun/libwx/wx_lib.c |  8 ++++----
>  2 files changed, 20 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
> index 122c4952d203..096fe7f3d84f 100644
> --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
> +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
> @@ -2893,10 +2893,13 @@ void wx_update_stats(struct wx *wx)
>  
>  	spin_lock(&wx->hw_stats_lock);
>  
> +	rcu_read_lock();
>  	/* 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];
> +		struct wx_ring *rx_ring = READ_ONCE(wx->rx_ring[i]);
>  
> +		if (!rx_ring)
> +			continue;
>  		non_eop_descs += rx_ring->rx_stats.non_eop_descs;
>  		alloc_rx_buff_failed += rx_ring->rx_stats.alloc_rx_buff_failed;
>  		hw_csum_rx_good += rx_ring->rx_stats.csum_good_cnt;
> @@ -2912,19 +2915,28 @@ void wx_update_stats(struct wx *wx)
>  		u64 rsc_flush = 0;
>  
>  		for (i = 0; i < wx->num_rx_queues; i++) {
> -			rsc_count += wx->rx_ring[i]->rx_stats.rsc_count;
> -			rsc_flush += wx->rx_ring[i]->rx_stats.rsc_flush;
> +			struct wx_ring *rx_ring = READ_ONCE(wx->rx_ring[i]);
> +
> +			if (!rx_ring)
> +				continue;
> +
> +			rsc_count += rx_ring->rx_stats.rsc_count;
> +			rsc_flush += rx_ring->rx_stats.rsc_flush;
>  		}
>  		wx->rsc_count = rsc_count;
>  		wx->rsc_flush = rsc_flush;
>  	}
>  
>  	for (i = 0; i < wx->num_tx_queues; i++) {
> -		struct wx_ring *tx_ring = wx->tx_ring[i];
> +		struct wx_ring *tx_ring = READ_ONCE(wx->tx_ring[i]);
> +
> +		if (!tx_ring)
> +			continue;
>  
>  		restart_queue += tx_ring->tx_stats.restart_queue;
>  		tx_busy += tx_ring->tx_stats.tx_busy;
>  	}
> +	rcu_read_unlock();
>  	wx->restart_queue = restart_queue;
>  	wx->tx_busy = tx_busy;
>  

A littler further down in this function there is a call to
wx_update_xoff_rx_lfc().

And since commit 22d95e93c05b ("net: wangxun: add Tx timeout process")
that function includes the following loop:


	for (i = 0; i < wx->num_tx_queues; i++)
		clear_bit(WX_HANG_CHECK_ARMED, wx->tx_ring[i]->state);

So I am wondering of this access to wx->tx_ring should be protected.
E.g. by extending the RCU read-side critical section to also cover
the call to wx_update_xoff_rx_lfc(), and by using READ_ONCE in
the loop above.

Observed with some assistance from Goose:gemini-3.1-flash-lite

...
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.