* [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