Netdev List
 help / color / mirror / Atom feed
* [PATCH net v3] net: libwx: protect ring accesses with RCU
@ 2026-08-24 10:36 Mengyuan Lou
  2026-08-26 15:34 ` Simon Horman
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Mengyuan Lou @ 2026-08-24 10:36 UTC (permalink / raw)
  To: netdev
  Cc: jiawenwu, duanqiangwen, linglingzhang, andrew+netdev, davem,
	edumazet, kuba, pabeni, Mengyuan Lou

During queue teardown or channel reconfiguration (e.g. via ethtool -L),
ring pointers in wx->rx_ring[] and wx->tx_ring[] can be cleared to NULL
and freed asynchronously via kfree_rcu().

Concurrency between interface reconfiguration and background tasks (such
as service tasks or dev_get_stats) can result in NULL pointer dereferences
or Use-After-Free (UAF) issues when accessing per-queue structures.
Specifically:
1. wx_update_stats() accesses per-queue Rx, RSC, and Tx rings without RCU
   read-side protection, and lacked NULL checks in the RSC accumulation
   loop.
2. wx_update_xoff_rx_lfc() walks wx->tx_ring[] and modifies ring->state
   without RCU protection or NULL checks, risking a kernel panic when flow
   control pause frames are received during queue teardown.
3. Queue status checks in wx_err.c and PTP watchdog in wx_ptp.c dereference
   ring pointers without RCU read-side critical sections or NULL checks.
4. Queue assignment in wx_alloc_q_vector() used plain stores without
   release barrier semantics needed for lockless RCU readers.

Fix these by:
1. Enclosing queue statistics gathering in wx_update_stats(),
   xoff processing in wx_update_xoff_rx_lfc(), error handling in wx_err.c,
   and PTP status checks in wx_ptp.c inside
   rcu_read_lock() / rcu_read_unlock() sections.
2. Replacing unprotected accesses with rcu_dereference() and adding NULL
   checks when traversing wx->rx_ring[] and wx->tx_ring[].
3. Using rcu_assign_pointer() when publishing or clearing ring pointers in
   wx_alloc_q_vector() and wx_free_q_vector().

Fixes: 46b92e10d631 ("net: libwx: support hardware statistics")
Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
---
Changelogs:
v3:
- Replaced READ_ONCE() with rcu_dereference() when reading __rcu annotated
  rx_ring and tx_ring pointers to fix Sparse static checker warnings and
  enable Lockdep runtime validation.
- Wrapped wx_update_xoff_rx_lfc() with its own rcu_read_lock() and
  rcu_read_unlock() section to ensure self-contained protection regardless
  of caller context.
- Extended RCU read-side critical sections and NULL pointer checks to other
  background tasks accessing ring arrays, including wx_ring_tx_pending(),
  wx_detect_tx_hang() in wx_err.c, and wx_ptp_rx_hang() in wx_ptp.c.
- Updated commit message to accurately reflect the use of rcu_dereference()
  and the expanded scope of protected functions.
v2: https://lore.kernel.org/netdev/20260818100841.37483-1-mengyuanlou@net-swift.com/
- Moved rcu_read_unlock() after wx_update_xoff_rx_lfc() in wx_update_stats()
  to ensure flow control processing remains fully protected within the RCU
  read-side critical section.
- Replaced WRITE_ONCE() with rcu_assign_pointer() when assigning and clearing
  ring pointers in wx_alloc_q_vector() and wx_free_q_vector(), providing
  proper release memory barrier semantics for lockless RCU readers.
- Added __rcu annotations to tx_ring and rx_ring in struct wx (wx_type.h) to
  align with Linux kernel RCU coding standards and fix Sparse warnings.
v1: https://lore.kernel.org/netdev/20260813095141.88227-1-mengyuanlou@net-swift.com/
---
 drivers/net/ethernet/wangxun/libwx/wx_err.c  | 20 ++++++++++---
 drivers/net/ethernet/wangxun/libwx/wx_hw.c   | 31 ++++++++++++++++----
 drivers/net/ethernet/wangxun/libwx/wx_lib.c  | 12 ++++----
 drivers/net/ethernet/wangxun/libwx/wx_ptp.c  |  6 +++-
 drivers/net/ethernet/wangxun/libwx/wx_type.h |  4 +--
 5 files changed, 54 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_err.c b/drivers/net/ethernet/wangxun/libwx/wx_err.c
index b56fbdc959de..8eadb4d3abcf 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_err.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_err.c
@@ -201,12 +201,18 @@ static bool wx_ring_tx_pending(struct wx *wx)
 {
 	int i;
 
+	rcu_read_lock();
 	for (i = 0; i < wx->num_tx_queues; i++) {
-		struct wx_ring *tx_ring = wx->tx_ring[i];
+		struct wx_ring *tx_ring = rcu_dereference(wx->tx_ring[i]);
 
-		if (tx_ring->next_to_use != tx_ring->next_to_clean)
+		if (!tx_ring)
+			continue;
+		if (tx_ring->next_to_use != tx_ring->next_to_clean) {
+			rcu_read_unlock();
 			return true;
+		}
 	}
+	rcu_read_unlock();
 
 	return false;
 }
@@ -264,8 +270,14 @@ static void wx_detect_tx_hang(struct wx *wx)
 
 	/* Force detection of hung controller */
 	if (netif_carrier_ok(wx->netdev)) {
-		for (i = 0; i < wx->num_tx_queues; i++)
-			set_bit(WX_TX_DETECT_HANG, wx->tx_ring[i]->state);
+		rcu_read_lock();
+		for (i = 0; i < wx->num_tx_queues; i++) {
+			struct wx_ring *tx_ring = rcu_dereference(wx->tx_ring[i]);
+
+			if (tx_ring)
+				set_bit(WX_TX_DETECT_HANG, tx_ring->state);
+		}
+		rcu_read_unlock();
 	}
 }
 
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 122c4952d203..96ce3a4bbec7 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -2870,8 +2870,15 @@ static void wx_update_xoff_rx_lfc(struct wx *wx)
 	if (!data)
 		return;
 
-	for (i = 0; i < wx->num_tx_queues; i++)
-		clear_bit(WX_HANG_CHECK_ARMED, wx->tx_ring[i]->state);
+	rcu_read_lock();
+	for (i = 0; i < wx->num_tx_queues; i++) {
+		struct wx_ring *tx_ring = rcu_dereference(wx->tx_ring[i]);
+
+		if (!tx_ring)
+			continue;
+		clear_bit(WX_HANG_CHECK_ARMED, tx_ring->state);
+	}
+	rcu_read_unlock();
 }
 
 /**
@@ -2893,10 +2900,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 = rcu_dereference(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 +2922,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 = rcu_dereference(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 = rcu_dereference(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;
 
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
index ed5aad7857bd..423b14c56949 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -2191,7 +2191,7 @@ static int wx_alloc_q_vector(struct wx *wx,
 		ring->queue_index = txr_idx;
 
 		/* assign ring to wx */
-		wx->tx_ring[txr_idx] = ring;
+		rcu_assign_pointer(wx->tx_ring[txr_idx], ring);
 
 		/* update count and index */
 		txr_count--;
@@ -2217,7 +2217,7 @@ static int wx_alloc_q_vector(struct wx *wx,
 		ring->queue_index = rxr_idx;
 
 		/* assign ring to wx */
-		wx->rx_ring[rxr_idx] = ring;
+		rcu_assign_pointer(wx->rx_ring[rxr_idx], ring);
 
 		/* update count and index */
 		rxr_count--;
@@ -2245,10 +2245,10 @@ static void wx_free_q_vector(struct wx *wx, int v_idx)
 	struct wx_ring *ring;
 
 	wx_for_each_ring(ring, q_vector->tx)
-		wx->tx_ring[ring->queue_index] = NULL;
+		rcu_assign_pointer(wx->tx_ring[ring->queue_index], NULL);
 
 	wx_for_each_ring(ring, q_vector->rx)
-		wx->rx_ring[ring->queue_index] = NULL;
+		rcu_assign_pointer(wx->rx_ring[ring->queue_index], NULL);
 
 	wx->q_vector[v_idx] = NULL;
 	netif_napi_del(&q_vector->napi);
@@ -3097,7 +3097,7 @@ void wx_get_stats64(struct net_device *netdev,
 
 	rcu_read_lock();
 	for (i = 0; i < wx->num_rx_queues; i++) {
-		struct wx_ring *ring = READ_ONCE(wx->rx_ring[i]);
+		struct wx_ring *ring = rcu_dereference(wx->rx_ring[i]);
 		u64 bytes, packets;
 		unsigned int start;
 
@@ -3113,7 +3113,7 @@ void wx_get_stats64(struct net_device *netdev,
 	}
 
 	for (i = 0; i < wx->num_tx_queues; i++) {
-		struct wx_ring *ring = READ_ONCE(wx->tx_ring[i]);
+		struct wx_ring *ring = rcu_dereference(wx->tx_ring[i]);
 		u64 bytes, packets;
 		unsigned int start;
 
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ptp.c b/drivers/net/ethernet/wangxun/libwx/wx_ptp.c
index 3eea647c4742..47b1599a1afa 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ptp.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ptp.c
@@ -274,11 +274,15 @@ static void wx_ptp_rx_hang(struct wx *wx)
 
 	/* determine the most recent watchdog or rx_timestamp event */
 	rx_event = wx->last_rx_ptp_check;
+	rcu_read_lock();
 	for (n = 0; n < wx->num_rx_queues; n++) {
-		rx_ring = wx->rx_ring[n];
+		rx_ring = rcu_dereference(wx->rx_ring[n]);
+		if (!rx_ring)
+			continue;
 		if (time_after(rx_ring->last_rx_timestamp, rx_event))
 			rx_event = rx_ring->last_rx_timestamp;
 	}
+	rcu_read_unlock();
 
 	/* only need to read the high RXSTMP register to clear the lock */
 	if (time_is_before_jiffies(rx_event + 5 * HZ)) {
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 2eba5ab59925..ec75ca116979 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -1359,8 +1359,8 @@ struct wx {
 	u32 tx_ring_count;
 	u32 rx_ring_count;
 
-	struct wx_ring *tx_ring[64] ____cacheline_aligned_in_smp;
-	struct wx_ring *rx_ring[64];
+	struct wx_ring __rcu *tx_ring[64] ____cacheline_aligned_in_smp;
+	struct wx_ring __rcu *rx_ring[64];
 	struct wx_q_vector *q_vector[64];
 	int num_rx_pools;
 	int num_rx_queues_per_pool;
-- 
2.30.1


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

* Re: [PATCH net v3] net: libwx: protect ring accesses with RCU
  2026-08-24 10:36 [PATCH net v3] net: libwx: protect ring accesses with RCU Mengyuan Lou
@ 2026-08-26 15:34 ` Simon Horman
  2026-08-27 10:15   ` mengyuanlou
  2026-08-26 20:27 ` kernel test robot
  2026-08-28  3:34 ` kernel test robot
  2 siblings, 1 reply; 5+ messages in thread
From: Simon Horman @ 2026-08-26 15:34 UTC (permalink / raw)
  To: Mengyuan Lou
  Cc: netdev, jiawenwu, duanqiangwen, linglingzhang, andrew+netdev,
	davem, edumazet, kuba, pabeni

On Mon, Aug 24, 2026 at 06:36:06PM +0800, Mengyuan Lou wrote:
> During queue teardown or channel reconfiguration (e.g. via ethtool -L),
> ring pointers in wx->rx_ring[] and wx->tx_ring[] can be cleared to NULL
> and freed asynchronously via kfree_rcu().
> 
> Concurrency between interface reconfiguration and background tasks (such
> as service tasks or dev_get_stats) can result in NULL pointer dereferences
> or Use-After-Free (UAF) issues when accessing per-queue structures.
> Specifically:
> 1. wx_update_stats() accesses per-queue Rx, RSC, and Tx rings without RCU
>    read-side protection, and lacked NULL checks in the RSC accumulation
>    loop.
> 2. wx_update_xoff_rx_lfc() walks wx->tx_ring[] and modifies ring->state
>    without RCU protection or NULL checks, risking a kernel panic when flow
>    control pause frames are received during queue teardown.
> 3. Queue status checks in wx_err.c and PTP watchdog in wx_ptp.c dereference
>    ring pointers without RCU read-side critical sections or NULL checks.
> 4. Queue assignment in wx_alloc_q_vector() used plain stores without
>    release barrier semantics needed for lockless RCU readers.
> 
> Fix these by:
> 1. Enclosing queue statistics gathering in wx_update_stats(),
>    xoff processing in wx_update_xoff_rx_lfc(), error handling in wx_err.c,
>    and PTP status checks in wx_ptp.c inside
>    rcu_read_lock() / rcu_read_unlock() sections.
> 2. Replacing unprotected accesses with rcu_dereference() and adding NULL
>    checks when traversing wx->rx_ring[] and wx->tx_ring[].
> 3. Using rcu_assign_pointer() when publishing or clearing ring pointers in
>    wx_alloc_q_vector() and wx_free_q_vector().
> 
> Fixes: 46b92e10d631 ("net: libwx: support hardware statistics")
> Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
> ---
> Changelogs:
> v3:
> - Replaced READ_ONCE() with rcu_dereference() when reading __rcu annotated
>   rx_ring and tx_ring pointers to fix Sparse static checker warnings and
>   enable Lockdep runtime validation.

Hi Mengyuan,

As you may be aware the change above has introduced a large number of new
Sparse warnings (~50). However, I believe that the approach taken here is
correct and those warnings do not reflect bugs added by this patch.

So I would like to suggest that they should not impede progress of this
patch. And that, rather, as a follow-up an audit is conducted of them.
Any latent bugs can result in patches for net. And non-bugs can be
addressed as follow-up for net-next.

> - Wrapped wx_update_xoff_rx_lfc() with its own rcu_read_lock() and
>   rcu_read_unlock() section to ensure self-contained protection regardless
>   of caller context.
> - Extended RCU read-side critical sections and NULL pointer checks to other
>   background tasks accessing ring arrays, including wx_ring_tx_pending(),
>   wx_detect_tx_hang() in wx_err.c, and wx_ptp_rx_hang() in wx_ptp.c.
> - Updated commit message to accurately reflect the use of rcu_dereference()
>   and the expanded scope of protected functions.
> v2: https://lore.kernel.org/netdev/20260818100841.37483-1-mengyuanlou@net-swift.com/
> - Moved rcu_read_unlock() after wx_update_xoff_rx_lfc() in wx_update_stats()
>   to ensure flow control processing remains fully protected within the RCU
>   read-side critical section.
> - Replaced WRITE_ONCE() with rcu_assign_pointer() when assigning and clearing
>   ring pointers in wx_alloc_q_vector() and wx_free_q_vector(), providing
>   proper release memory barrier semantics for lockless RCU readers.
> - Added __rcu annotations to tx_ring and rx_ring in struct wx (wx_type.h) to
>   align with Linux kernel RCU coding standards and fix Sparse warnings.
> v1: https://lore.kernel.org/netdev/20260813095141.88227-1-mengyuanlou@net-swift.com/

Reviewed-by: Simon Horman <horms@kernel.org>


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

* Re: [PATCH net v3] net: libwx: protect ring accesses with RCU
  2026-08-24 10:36 [PATCH net v3] net: libwx: protect ring accesses with RCU Mengyuan Lou
  2026-08-26 15:34 ` Simon Horman
@ 2026-08-26 20:27 ` kernel test robot
  2026-08-28  3:34 ` kernel test robot
  2 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2026-08-26 20:27 UTC (permalink / raw)
  To: Mengyuan Lou, netdev
  Cc: oe-kbuild-all, jiawenwu, duanqiangwen, linglingzhang,
	andrew+netdev, davem, edumazet, kuba, pabeni, Mengyuan Lou

Hi Mengyuan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on net/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Mengyuan-Lou/net-libwx-protect-ring-accesses-with-RCU/20260824-183606
base:   net/main
patch link:    https://lore.kernel.org/r/20260824103606.303-1-mengyuanlou%40net-swift.com
patch subject: [PATCH net v3] net: libwx: protect ring accesses with RCU
config: microblaze-randconfig-r133-20260826 (https://download.01.org/0day-ci/archive/20260827/202608270436.2nJKiNXZ-lkp@intel.com/config)
compiler: microblaze-linux-gcc (GCC) 8.5.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260827/202608270436.2nJKiNXZ-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202608270436.2nJKiNXZ-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:208:54: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct wx_ring *rx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:208:54: sparse:     expected struct wx_ring *rx_ring
   drivers/net/ethernet/wangxun/libwx/wx_vf_common.c:208:54: sparse:     got struct wx_ring [noderef] __rcu *
--
>> drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c:179:56: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected struct wx_ring *ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c:179:56: sparse:     expected struct wx_ring *ring
   drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c:179:56: sparse:     got struct wx_ring [noderef] __rcu *
--
>> drivers/net/ethernet/wangxun/libwx/wx_ethtool.c:158:22: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct wx_ring *ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_ethtool.c:158:22: sparse:     expected struct wx_ring *ring
   drivers/net/ethernet/wangxun/libwx/wx_ethtool.c:158:22: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_ethtool.c:173:22: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct wx_ring *ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_ethtool.c:173:22: sparse:     expected struct wx_ring *ring
   drivers/net/ethernet/wangxun/libwx/wx_ethtool.c:173:22: sparse:     got struct wx_ring [noderef] __rcu *
>> drivers/net/ethernet/wangxun/libwx/wx_ethtool.c:808:36: sparse: sparse: dereference of noderef expression
   drivers/net/ethernet/wangxun/libwx/wx_ethtool.c:810:36: sparse: sparse: dereference of noderef expression
--
>> drivers/net/ethernet/wangxun/libwx/wx_lib.c:1717:17: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct wx_ring *tx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:1717:17: sparse:     expected struct wx_ring *tx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:1717:17: sparse:     got struct wx_ring [noderef] __rcu *
>> drivers/net/ethernet/wangxun/libwx/wx_lib.c:2662:45: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *rx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2662:45: sparse:     expected struct wx_ring *rx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2662:45: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2704:49: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *rx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2704:49: sparse:     expected struct wx_ring *rx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2704:49: sparse:     got struct wx_ring [noderef] __rcu *
>> drivers/net/ethernet/wangxun/libwx/wx_lib.c:2778:45: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *tx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2778:45: sparse:     expected struct wx_ring *tx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2778:45: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2826:49: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *tx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2826:49: sparse:     expected struct wx_ring *tx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2826:49: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2936:56: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *rx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2936:56: sparse:     expected struct wx_ring *rx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2936:56: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2948:49: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *rx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2948:49: sparse:     expected struct wx_ring *rx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2948:49: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3039:56: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *tx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3039:56: sparse:     expected struct wx_ring *tx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3039:56: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3051:49: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *tx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3051:49: sparse:     expected struct wx_ring *tx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3051:49: sparse:     got struct wx_ring [noderef] __rcu *
>> drivers/net/ethernet/wangxun/libwx/wx_lib.c:3327:58: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void const * @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3327:58: sparse:     expected void const *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3327:58: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3343:57: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *tx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3343:57: sparse:     expected struct wx_ring *tx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3343:57: sparse:     got struct wx_ring [noderef] __rcu *
>> drivers/net/ethernet/wangxun/libwx/wx_lib.c:3345:43: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void * @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3345:43: sparse:     expected void *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3345:43: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3355:58: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void const * @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3355:58: sparse:     expected void const *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3355:58: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3371:57: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *rx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3371:57: sparse:     expected struct wx_ring *rx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3371:57: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3372:43: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void * @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3372:43: sparse:     expected void *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3372:43: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c: note: in included file (through include/linux/if_ether.h, include/linux/etherdevice.h):
   include/linux/skbuff.h:2904:28: sparse: sparse: unsigned value that used to be signed checked against zero?
   include/linux/skbuff.h:2904:28: sparse: signed value source
>> drivers/net/ethernet/wangxun/libwx/wx_lib.c:2061:36: sparse: sparse: dereference of noderef expression
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2068:36: sparse: sparse: dereference of noderef expression
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2075:36: sparse: sparse: dereference of noderef expression
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2080:36: sparse: sparse: dereference of noderef expression
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2101:28: sparse: sparse: dereference of noderef expression
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2104:28: sparse: sparse: dereference of noderef expression
--
>> drivers/net/ethernet/wangxun/libwx/wx_hw.c:1602:51: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct wx_ring *ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:1602:51: sparse:     expected struct wx_ring *ring
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:1602:51: sparse:     got struct wx_ring [noderef] __rcu *
>> drivers/net/ethernet/wangxun/libwx/wx_hw.c:1800:25: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct wx_ring *rx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:1800:25: sparse:     expected struct wx_ring *rx_ring
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:1800:25: sparse:     got struct wx_ring [noderef] __rcu *
>> drivers/net/ethernet/wangxun/libwx/wx_hw.c:2025:53: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected struct wx_ring *ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:2025:53: sparse:     expected struct wx_ring *ring
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:2025:53: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:2251:53: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected struct wx_ring *ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:2251:53: sparse:     expected struct wx_ring *ring
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:2251:53: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:2842:58: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected struct wx_ring *ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:2842:58: sparse:     expected struct wx_ring *ring
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:2842:58: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:2845:59: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected struct wx_ring *ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:2845:59: sparse:     expected struct wx_ring *ring
   drivers/net/ethernet/wangxun/libwx/wx_hw.c:2845:59: sparse:     got struct wx_ring [noderef] __rcu *
--
>> drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c:40:36: sparse: sparse: dereference of noderef expression
   drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c:42:36: sparse: sparse: dereference of noderef expression
--
>> drivers/net/ethernet/wangxun/ngbe/ngbe_main.c:409:52: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected struct wx_ring *ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/ngbe/ngbe_main.c:409:52: sparse:     expected struct wx_ring *ring
   drivers/net/ethernet/wangxun/ngbe/ngbe_main.c:409:52: sparse:     got struct wx_ring [noderef] __rcu *
>> drivers/net/ethernet/wangxun/ngbe/ngbe_main.c:425:41: sparse: sparse: dereference of noderef expression

vim +1717 drivers/net/ethernet/wangxun/libwx/wx_lib.c

09a508800952f8 Mengyuan Lou 2023-02-03  1696  
09a508800952f8 Mengyuan Lou 2023-02-03  1697  netdev_tx_t wx_xmit_frame(struct sk_buff *skb,
09a508800952f8 Mengyuan Lou 2023-02-03  1698  			  struct net_device *netdev)
09a508800952f8 Mengyuan Lou 2023-02-03  1699  {
09a508800952f8 Mengyuan Lou 2023-02-03  1700  	unsigned int r_idx = skb->queue_mapping;
09a508800952f8 Mengyuan Lou 2023-02-03  1701  	struct wx *wx = netdev_priv(netdev);
09a508800952f8 Mengyuan Lou 2023-02-03  1702  	struct wx_ring *tx_ring;
09a508800952f8 Mengyuan Lou 2023-02-03  1703  
09a508800952f8 Mengyuan Lou 2023-02-03  1704  	if (!netif_carrier_ok(netdev)) {
09a508800952f8 Mengyuan Lou 2023-02-03  1705  		dev_kfree_skb_any(skb);
09a508800952f8 Mengyuan Lou 2023-02-03  1706  		return NETDEV_TX_OK;
09a508800952f8 Mengyuan Lou 2023-02-03  1707  	}
09a508800952f8 Mengyuan Lou 2023-02-03  1708  
09a508800952f8 Mengyuan Lou 2023-02-03  1709  	/* The minimum packet size for olinfo paylen is 17 so pad the skb
09a508800952f8 Mengyuan Lou 2023-02-03  1710  	 * in order to meet this minimum size requirement.
09a508800952f8 Mengyuan Lou 2023-02-03  1711  	 */
09a508800952f8 Mengyuan Lou 2023-02-03  1712  	if (skb_put_padto(skb, 17))
09a508800952f8 Mengyuan Lou 2023-02-03  1713  		return NETDEV_TX_OK;
09a508800952f8 Mengyuan Lou 2023-02-03  1714  
09a508800952f8 Mengyuan Lou 2023-02-03  1715  	if (r_idx >= wx->num_tx_queues)
09a508800952f8 Mengyuan Lou 2023-02-03  1716  		r_idx = r_idx % wx->num_tx_queues;
09a508800952f8 Mengyuan Lou 2023-02-03 @1717  	tx_ring = wx->tx_ring[r_idx];
09a508800952f8 Mengyuan Lou 2023-02-03  1718  
09a508800952f8 Mengyuan Lou 2023-02-03  1719  	return wx_xmit_frame_ring(skb, tx_ring);
09a508800952f8 Mengyuan Lou 2023-02-03  1720  }
09a508800952f8 Mengyuan Lou 2023-02-03  1721  EXPORT_SYMBOL(wx_xmit_frame);
09a508800952f8 Mengyuan Lou 2023-02-03  1722  

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH net v3] net: libwx: protect ring accesses with RCU
  2026-08-26 15:34 ` Simon Horman
@ 2026-08-27 10:15   ` mengyuanlou
  0 siblings, 0 replies; 5+ messages in thread
From: mengyuanlou @ 2026-08-27 10:15 UTC (permalink / raw)
  To: Simon Horman
  Cc: netdev, jiawenwu, duanqiangwen, linglingzhang, andrew+netdev,
	davem, edumazet, kuba, pabeni



> 2026年8月26日 23:34,Simon Horman <horms@kernel.org> 写道:
> 
> On Mon, Aug 24, 2026 at 06:36:06PM +0800, Mengyuan Lou wrote:
>> During queue teardown or channel reconfiguration (e.g. via ethtool -L),
>> ring pointers in wx->rx_ring[] and wx->tx_ring[] can be cleared to NULL
>> and freed asynchronously via kfree_rcu().
>> 
>> Concurrency between interface reconfiguration and background tasks (such
>> as service tasks or dev_get_stats) can result in NULL pointer dereferences
>> or Use-After-Free (UAF) issues when accessing per-queue structures.
>> Specifically:
>> 1. wx_update_stats() accesses per-queue Rx, RSC, and Tx rings without RCU
>>    read-side protection, and lacked NULL checks in the RSC accumulation
>>   loop.
>> 2. wx_update_xoff_rx_lfc() walks wx->tx_ring[] and modifies ring->state
>>   without RCU protection or NULL checks, risking a kernel panic when flow
>>   control pause frames are received during queue teardown.
>> 3. Queue status checks in wx_err.c and PTP watchdog in wx_ptp.c dereference
>>   ring pointers without RCU read-side critical sections or NULL checks.
>> 4. Queue assignment in wx_alloc_q_vector() used plain stores without
>>   release barrier semantics needed for lockless RCU readers.
>> 
>> Fix these by:
>> 1. Enclosing queue statistics gathering in wx_update_stats(),
>>   xoff processing in wx_update_xoff_rx_lfc(), error handling in wx_err.c,
>>   and PTP status checks in wx_ptp.c inside
>>   rcu_read_lock() / rcu_read_unlock() sections.
>> 2. Replacing unprotected accesses with rcu_dereference() and adding NULL
>>   checks when traversing wx->rx_ring[] and wx->tx_ring[].
>> 3. Using rcu_assign_pointer() when publishing or clearing ring pointers in
>>   wx_alloc_q_vector() and wx_free_q_vector().
>> 
>> Fixes: 46b92e10d631 ("net: libwx: support hardware statistics")
>> Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
>> ---
>> Changelogs:
>> v3:
>> - Replaced READ_ONCE() with rcu_dereference() when reading __rcu annotated
>>  rx_ring and tx_ring pointers to fix Sparse static checker warnings and
>>  enable Lockdep runtime validation.
> 
> Hi Mengyuan,
> 
> As you may be aware the change above has introduced a large number of new
> Sparse warnings (~50). However, I believe that the approach taken here is
> correct and those warnings do not reflect bugs added by this patch.
> 
> So I would like to suggest that they should not impede progress of this
> patch. And that, rather, as a follow-up an audit is conducted of them.
> Any latent bugs can result in patches for net. And non-bugs can be
> addressed as follow-up for net-next.


Thanks for review.

Originally, I planned to use WRITE_ONCE and READ_ONCE.
And sashiko suggest that rcu_assign_pointer() and rcu_dereference().

https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260813095141.88227-1-mengyuanlou%40net-swift.com
----
The ring is initialized with plain stores just above this publish (dev,
netdev, q_vector, count, queue_index, plus syncp and the stats union from
kzalloc_flex()), and the consumers read the pointer locklessly:
wx_update_stats() after this patch and wx_get_stats64(). On a weakly ordered
CPU, can a reader see the published pointer before those initialization
stores, and accumulate stale slab contents into wx->non_eop_descs and
friends?Given that the free side is kfree_rcu(q_vector, rcu), would
rcu_assign_pointer() here (and rcu_dereference() plus __rcu annotation on
wx->tx_ring[]/wx->rx_ring[] on the read side) express the intended protocol
more directly than the READ_ONCE()/WRITE_ONCE() pair?
—

It is actually always be used in arm/riscv/sw CPU. 


https://sashiko.dev/#/patchset/20260824103606.303-1-mengyuanlou%40net-swift.com

> diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
> index 2eba5ab599252..ec75ca1169796 100644
> --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
> +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
> @@ -1359,8 +1359,8 @@ struct wx {
> u32 tx_ring_count;
> u32 rx_ring_count;
> 
> - struct wx_ring *tx_ring[64] ____cacheline_aligned_in_smp;
> - struct wx_ring *rx_ring[64];
> + struct wx_ring __rcu *tx_ring[64] ____cacheline_aligned_in_smp;
> + struct wx_ring __rcu *rx_ring[64];

Does adding the __rcu annotation here cause Sparse warnings in other parts
of the driver that still access these pointers directly?


For example,
in drivers/net/ethernet/wangxun/libwx/wx_ethtool.c:wx_get_ethtool_stats():  
—- Rtnl_lock protect it.

ring = wx->tx_ring[j];In drivers/net/ethernet/wangxun/libwx/wx_lib.c:wx_xmit_frame():
tx_ring = wx->tx_ring[r_idx];
—- Fast Path / Datapath

in drivers/net/ethernet/wangxun/libwx/wx_hw.c:wx_vlan_strip_control():
struct wx_ring *ring = wx->rx_ring[I];
—- wx_configure path

Since these accesses don't use rcu_dereference_protected() or
rtnl_dereference(), could they generate "incorrect type in assignment"
warnings from Sparse, even though they may be safely serialized by other
locks?

To slove these warnings cost a lot.
Should I use rcu_assign_pointer() and rcu_dereference()?
Or fallback to WRITE_ONCE and READ_ONCE.


> 
>> - Wrapped wx_update_xoff_rx_lfc() with its own rcu_read_lock() and
>>  rcu_read_unlock() section to ensure self-contained protection regardless
>>  of caller context.
>> - Extended RCU read-side critical sections and NULL pointer checks to other
>>  background tasks accessing ring arrays, including wx_ring_tx_pending(),
>>  wx_detect_tx_hang() in wx_err.c, and wx_ptp_rx_hang() in wx_ptp.c.
>> - Updated commit message to accurately reflect the use of rcu_dereference()
>>  and the expanded scope of protected functions.
>> v2: https://lore.kernel.org/netdev/20260818100841.37483-1-mengyuanlou@net-swift.com/
>> - Moved rcu_read_unlock() after wx_update_xoff_rx_lfc() in wx_update_stats()
>>   to ensure flow control processing remains fully protected within the RCU
>>   read-side critical section.
>> - Replaced WRITE_ONCE() with rcu_assign_pointer() when assigning and clearing
>>   ring pointers in wx_alloc_q_vector() and wx_free_q_vector(), providing
>>   proper release memory barrier semantics for lockless RCU readers.
>> - Added __rcu annotations to tx_ring and rx_ring in struct wx (wx_type.h) to
>>   align with Linux kernel RCU coding standards and fix Sparse warnings.
>> v1: https://lore.kernel.org/netdev/20260813095141.88227-1-mengyuanlou@net-swift.com/
> 
> Reviewed-by: Simon Horman <horms@kernel.org>
> 
> 


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

* Re: [PATCH net v3] net: libwx: protect ring accesses with RCU
  2026-08-24 10:36 [PATCH net v3] net: libwx: protect ring accesses with RCU Mengyuan Lou
  2026-08-26 15:34 ` Simon Horman
  2026-08-26 20:27 ` kernel test robot
@ 2026-08-28  3:34 ` kernel test robot
  2 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2026-08-28  3:34 UTC (permalink / raw)
  To: Mengyuan Lou, netdev
  Cc: oe-kbuild-all, jiawenwu, duanqiangwen, linglingzhang,
	andrew+netdev, davem, edumazet, kuba, pabeni, Mengyuan Lou

Hi Mengyuan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on net/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Mengyuan-Lou/net-libwx-protect-ring-accesses-with-RCU/20260824-183606
base:   net/main
patch link:    https://lore.kernel.org/r/20260824103606.303-1-mengyuanlou%40net-swift.com
patch subject: [PATCH net v3] net: libwx: protect ring accesses with RCU
config: csky-randconfig-r113-20260826 (https://download.01.org/0day-ci/archive/20260828/202608281122.ImEa1DuX-lkp@intel.com/config)
compiler: csky-linux-gcc (GCC) 15.2.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260828/202608281122.ImEa1DuX-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202608281122.ImEa1DuX-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:1717:17: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct wx_ring *tx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:1717:17: sparse:     expected struct wx_ring *tx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:1717:17: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2662:45: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *rx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2662:45: sparse:     expected struct wx_ring *rx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2662:45: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2704:49: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *rx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2704:49: sparse:     expected struct wx_ring *rx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2704:49: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2778:45: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *tx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2778:45: sparse:     expected struct wx_ring *tx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2778:45: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2826:49: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *tx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2826:49: sparse:     expected struct wx_ring *tx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2826:49: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2936:56: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *rx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2936:56: sparse:     expected struct wx_ring *rx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2936:56: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2948:49: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *rx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2948:49: sparse:     expected struct wx_ring *rx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2948:49: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3039:56: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *tx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3039:56: sparse:     expected struct wx_ring *tx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3039:56: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3051:49: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *tx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3051:49: sparse:     expected struct wx_ring *tx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3051:49: sparse:     got struct wx_ring [noderef] __rcu *
>> drivers/net/ethernet/wangxun/libwx/wx_lib.c:3327:58: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void const *from @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3327:58: sparse:     expected void const *from
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3327:58: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3343:57: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *tx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3343:57: sparse:     expected struct wx_ring *tx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3343:57: sparse:     got struct wx_ring [noderef] __rcu *
>> drivers/net/ethernet/wangxun/libwx/wx_lib.c:3345:43: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void *to @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3345:43: sparse:     expected void *to
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3345:43: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3355:58: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void const *from @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3355:58: sparse:     expected void const *from
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3355:58: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3371:57: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct wx_ring *rx_ring @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3371:57: sparse:     expected struct wx_ring *rx_ring
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3371:57: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3372:43: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void *to @@     got struct wx_ring [noderef] __rcu * @@
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3372:43: sparse:     expected void *to
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:3372:43: sparse:     got struct wx_ring [noderef] __rcu *
   drivers/net/ethernet/wangxun/libwx/wx_lib.c: note: in included file (through include/linux/if_ether.h, include/linux/etherdevice.h):
   include/linux/skbuff.h:2904:28: sparse: sparse: unsigned value that used to be signed checked against zero?
   include/linux/skbuff.h:2904:28: sparse: signed value source
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2061:36: sparse: sparse: dereference of noderef expression
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2068:36: sparse: sparse: dereference of noderef expression
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2075:36: sparse: sparse: dereference of noderef expression
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2080:36: sparse: sparse: dereference of noderef expression
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2101:28: sparse: sparse: dereference of noderef expression
   drivers/net/ethernet/wangxun/libwx/wx_lib.c:2104:28: sparse: sparse: dereference of noderef expression

vim +3327 drivers/net/ethernet/wangxun/libwx/wx_lib.c

3b05aa997c4914 Jiawen Wu    2025-04-21  3314  
0ce45ae881fd90 Mengyuan Lou 2026-07-10  3315  int wx_set_ring(struct wx *wx, u32 new_tx_count,
883b5984a5d290 Jiawen Wu    2024-01-03  3316  		u32 new_rx_count, struct wx_ring *temp_ring)
883b5984a5d290 Jiawen Wu    2024-01-03  3317  {
883b5984a5d290 Jiawen Wu    2024-01-03  3318  	int i, err = 0;
883b5984a5d290 Jiawen Wu    2024-01-03  3319  
883b5984a5d290 Jiawen Wu    2024-01-03  3320  	/* Setup new Tx resources and free the old Tx resources in that order.
883b5984a5d290 Jiawen Wu    2024-01-03  3321  	 * We can then assign the new resources to the rings via a memcpy.
883b5984a5d290 Jiawen Wu    2024-01-03  3322  	 * The advantage to this approach is that we are guaranteed to still
883b5984a5d290 Jiawen Wu    2024-01-03  3323  	 * have resources even in the case of an allocation failure.
883b5984a5d290 Jiawen Wu    2024-01-03  3324  	 */
883b5984a5d290 Jiawen Wu    2024-01-03  3325  	if (new_tx_count != wx->tx_ring_count) {
883b5984a5d290 Jiawen Wu    2024-01-03  3326  		for (i = 0; i < wx->num_tx_queues; i++) {
883b5984a5d290 Jiawen Wu    2024-01-03 @3327  			memcpy(&temp_ring[i], wx->tx_ring[i],
883b5984a5d290 Jiawen Wu    2024-01-03  3328  			       sizeof(struct wx_ring));
883b5984a5d290 Jiawen Wu    2024-01-03  3329  
883b5984a5d290 Jiawen Wu    2024-01-03  3330  			temp_ring[i].count = new_tx_count;
883b5984a5d290 Jiawen Wu    2024-01-03  3331  			err = wx_setup_tx_resources(&temp_ring[i]);
883b5984a5d290 Jiawen Wu    2024-01-03  3332  			if (err) {
883b5984a5d290 Jiawen Wu    2024-01-03  3333  				wx_err(wx, "setup new tx resources failed, keep using the old config\n");
883b5984a5d290 Jiawen Wu    2024-01-03  3334  				while (i) {
883b5984a5d290 Jiawen Wu    2024-01-03  3335  					i--;
883b5984a5d290 Jiawen Wu    2024-01-03  3336  					wx_free_tx_resources(&temp_ring[i]);
883b5984a5d290 Jiawen Wu    2024-01-03  3337  				}
0ce45ae881fd90 Mengyuan Lou 2026-07-10  3338  				return err;
883b5984a5d290 Jiawen Wu    2024-01-03  3339  			}
883b5984a5d290 Jiawen Wu    2024-01-03  3340  		}
883b5984a5d290 Jiawen Wu    2024-01-03  3341  
883b5984a5d290 Jiawen Wu    2024-01-03  3342  		for (i = 0; i < wx->num_tx_queues; i++) {
883b5984a5d290 Jiawen Wu    2024-01-03  3343  			wx_free_tx_resources(wx->tx_ring[i]);
883b5984a5d290 Jiawen Wu    2024-01-03  3344  
883b5984a5d290 Jiawen Wu    2024-01-03 @3345  			memcpy(wx->tx_ring[i], &temp_ring[i],
883b5984a5d290 Jiawen Wu    2024-01-03  3346  			       sizeof(struct wx_ring));
883b5984a5d290 Jiawen Wu    2024-01-03  3347  		}
883b5984a5d290 Jiawen Wu    2024-01-03  3348  
883b5984a5d290 Jiawen Wu    2024-01-03  3349  		wx->tx_ring_count = new_tx_count;
883b5984a5d290 Jiawen Wu    2024-01-03  3350  	}
883b5984a5d290 Jiawen Wu    2024-01-03  3351  
883b5984a5d290 Jiawen Wu    2024-01-03  3352  	/* Repeat the process for the Rx rings if needed */
883b5984a5d290 Jiawen Wu    2024-01-03  3353  	if (new_rx_count != wx->rx_ring_count) {
883b5984a5d290 Jiawen Wu    2024-01-03  3354  		for (i = 0; i < wx->num_rx_queues; i++) {
883b5984a5d290 Jiawen Wu    2024-01-03  3355  			memcpy(&temp_ring[i], wx->rx_ring[i],
883b5984a5d290 Jiawen Wu    2024-01-03  3356  			       sizeof(struct wx_ring));
883b5984a5d290 Jiawen Wu    2024-01-03  3357  
883b5984a5d290 Jiawen Wu    2024-01-03  3358  			temp_ring[i].count = new_rx_count;
883b5984a5d290 Jiawen Wu    2024-01-03  3359  			err = wx_setup_rx_resources(&temp_ring[i]);
883b5984a5d290 Jiawen Wu    2024-01-03  3360  			if (err) {
883b5984a5d290 Jiawen Wu    2024-01-03  3361  				wx_err(wx, "setup new rx resources failed, keep using the old config\n");
883b5984a5d290 Jiawen Wu    2024-01-03  3362  				while (i) {
883b5984a5d290 Jiawen Wu    2024-01-03  3363  					i--;
883b5984a5d290 Jiawen Wu    2024-01-03  3364  					wx_free_rx_resources(&temp_ring[i]);
883b5984a5d290 Jiawen Wu    2024-01-03  3365  				}
0ce45ae881fd90 Mengyuan Lou 2026-07-10  3366  				return err;
883b5984a5d290 Jiawen Wu    2024-01-03  3367  			}
883b5984a5d290 Jiawen Wu    2024-01-03  3368  		}
883b5984a5d290 Jiawen Wu    2024-01-03  3369  
883b5984a5d290 Jiawen Wu    2024-01-03  3370  		for (i = 0; i < wx->num_rx_queues; i++) {
883b5984a5d290 Jiawen Wu    2024-01-03  3371  			wx_free_rx_resources(wx->rx_ring[i]);
883b5984a5d290 Jiawen Wu    2024-01-03  3372  			memcpy(wx->rx_ring[i], &temp_ring[i],
883b5984a5d290 Jiawen Wu    2024-01-03  3373  			       sizeof(struct wx_ring));
883b5984a5d290 Jiawen Wu    2024-01-03  3374  		}
883b5984a5d290 Jiawen Wu    2024-01-03  3375  
883b5984a5d290 Jiawen Wu    2024-01-03  3376  		wx->rx_ring_count = new_rx_count;
883b5984a5d290 Jiawen Wu    2024-01-03  3377  	}
0ce45ae881fd90 Mengyuan Lou 2026-07-10  3378  	return 0;
883b5984a5d290 Jiawen Wu    2024-01-03  3379  }
883b5984a5d290 Jiawen Wu    2024-01-03  3380  EXPORT_SYMBOL(wx_set_ring);
883b5984a5d290 Jiawen Wu    2024-01-03  3381  

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

end of thread, other threads:[~2026-08-28  3:34 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-24 10:36 [PATCH net v3] net: libwx: protect ring accesses with RCU Mengyuan Lou
2026-08-26 15:34 ` Simon Horman
2026-08-27 10:15   ` mengyuanlou
2026-08-26 20:27 ` kernel test robot
2026-08-28  3:34 ` kernel test robot

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