Thread (3 messages) 3 messages, 1 author, 2d ago
DORMANTno replies

[RFC PATCH net 2/2] net/ncsi: stop device work before freeing channels

From: Runyu Xiao <hidden>
Date: 2026-06-27 09:27:32
Also in: lkml
Subsystem: ncsi library, networking [general], the rest · Maintainers: Samuel Mendoza-Jonas, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

ncsi_unregister_dev() tears down packages and channels before it
disables the NCSI device work item. Current trees already stop the work
before freeing ndp itself, but a teardown window remains where a running
or already scheduled ncsi_dev_work() can still reach package/channel
readers after ncsi_remove_package() has freed the underlying objects.

One visible path is the configuration flow through ncsi_channel_is_tx(),
which walks package channels and ndp->channel_queue while choosing a
transmit channel. Channel queue entries are struct ncsi_channel objects
owned by the package channel lists, and ncsi_remove_channel() frees
those objects during package removal.

Disable the device work before package/channel teardown. Also clear any
remaining channel_queue links while the channel objects are still alive,
so no stale queue membership is carried into teardown.

This was found by our static analysis tool and then manually reviewed
against the current tree. CONFIG_PROVE_RCU_LIST was used as
target-matched triage evidence; the teardown change is based on the
source-level workqueue and channel lifetime review rather than on the
dynamic warning alone.

This is deliberately limited to the teardown ordering problem. It does
not change the normal package/channel RCU-list update model.

Signed-off-by: Runyu Xiao <redacted>
---
 net/ncsi/ncsi-manage.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 5316eadd8ce4..289974dff0c1 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -1956,10 +1956,18 @@ void ncsi_unregister_dev(struct ncsi_dev *nd)
 {
 	struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd);
 	struct ncsi_package *np, *tmp;
+	struct ncsi_channel *nc, *ntmp;
 	unsigned long flags;
 
 	dev_remove_pack(&ndp->ptype);
 
+	disable_work_sync(&ndp->work);
+
+	spin_lock_irqsave(&ndp->lock, flags);
+	list_for_each_entry_safe(nc, ntmp, &ndp->channel_queue, link)
+		list_del_init(&nc->link);
+	spin_unlock_irqrestore(&ndp->lock, flags);
+
 	list_for_each_entry_safe(np, tmp, &ndp->packages, node)
 		ncsi_remove_package(np);
 
@@ -1967,7 +1975,6 @@ void ncsi_unregister_dev(struct ncsi_dev *nd)
 	list_del_rcu(&ndp->node);
 	spin_unlock_irqrestore(&ncsi_dev_lock, flags);
 
-	disable_work_sync(&ndp->work);
 
 	kfree(ndp);
 }
-- 
2.34.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help