Subject: [PATCH net-next 8/8] netconsole: move find_skb() from netpoll

From: Breno Leitao <[email-masked]>
Date: Fri, 08 May 2026 06:29:22 -0700

find_skb() is the netconsole-specific entry into the netpoll skb
pool: every other netpoll consumer (bonding, team, vlan, bridge,
macvlan, dsa) builds its own sk_buff and never touches the pool.
With netpoll_send_udp() (its only caller) now living in netconsole,
find_skb() can join it.

Move find_skb() into drivers/net/netconsole.c as a file-static
helper, drop EXPORT_SYMBOL_GPL(find_skb) and remove its prototype
from include/linux/netpoll.h.

find_skb() calls zap_completion_queue() to drain TX completions
before allocating. zap_completion_queue() also has a second caller
inside netpoll itself (netpoll_poll_dev() runs it after each poll
to free completed skbs), so it stays in net/core/netpoll.c.
Promote it from file-static to EXPORT_SYMBOL_GPL with a forward
declaration in include/linux/netpoll.h, and drop its old
file-static forward declaration.

The skb pool's lifecycle (np->skb_pool, np->refill_wq, refill_skbs(),
refill_skbs_work_handler(), skb_pool_flush()) stays in netpoll: it
is initialised in __netpoll_setup() and torn down in
__netpoll_cleanup(), both of which remain netpoll's responsibility.
The refill work queued via schedule_work(&np->refill_wq) from the
moved find_skb() runs refill_skbs_work_handler() in netpoll without
any further plumbing.

Signed-off-by: Breno Leitao <[email-masked]>
---
 drivers/net/netconsole.c | 27 +++++++++++++++++++++++++++
 include/linux/netpoll.h  |  2 +-
 net/core/netpoll.c       | 33 ++-------------------------------
 3 files changed, 30 insertions(+), 32 deletions(-)

diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 48d2670bbdef5..817561d8b06bb 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -1653,6 +1653,33 @@ static struct notifier_block netconsole_netdev_notifier = {
 	.notifier_call  = netconsole_netdev_event,
 };
 
+static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve)
+{
+	int count = 0;
+	struct sk_buff *skb;
+
+	zap_completion_queue();
+repeat:
+
+	skb = alloc_skb(len, GFP_ATOMIC);
+	if (!skb) {
+		skb = skb_dequeue(&np->skb_pool);
+		schedule_work(&np->refill_wq);
+	}
+
+	if (!skb) {
+		if (++count < 10) {
+			netpoll_poll_dev(np->dev);
+			goto repeat;
+		}
+		return NULL;
+	}
+
+	refcount_set(&skb->users, 1);
+	skb_reserve(skb, reserve);
+	return skb;
+}
+
 static void netpoll_udp_checksum(struct netpoll *np, struct sk_buff *skb,
 				 int len)
 {
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index 1877d42ccbccf..c9a03d88263ef 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -73,7 +73,7 @@ void __netpoll_free(struct netpoll *np);
 void netpoll_cleanup(struct netpoll *np);
 void do_netpoll_cleanup(struct netpoll *np);
 netdev_tx_t netpoll_send_skb(struct netpoll *np, struct sk_buff *skb);
-struct sk_buff *find_skb(struct netpoll *np, int len, int reserve);
+void zap_completion_queue(void);
 
 #ifdef CONFIG_NETPOLL
 static inline void *netpoll_poll_lock(struct napi_struct *napi)
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index c148b3b68cec9..956528904050e 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -51,8 +51,6 @@
 	 sizeof(struct udphdr) +					\
 	 MAX_UDP_CHUNK)
 
-static void zap_completion_queue(void);
-
 static unsigned int carrier_timeout = 4;
 module_param(carrier_timeout, uint, 0644);
 
@@ -238,7 +236,7 @@ static void refill_skbs(struct netpoll *np)
 	}
 }
 
-static void zap_completion_queue(void)
+void zap_completion_queue(void)
 {
 	unsigned long flags;
 	struct softnet_data *sd = &get_cpu_var(softnet_data);
@@ -265,34 +263,7 @@ static void zap_completion_queue(void)
 
 	put_cpu_var(softnet_data);
 }
-
-struct sk_buff *find_skb(struct netpoll *np, int len, int reserve)
-{
-	int count = 0;
-	struct sk_buff *skb;
-
-	zap_completion_queue();
-repeat:
-
-	skb = alloc_skb(len, GFP_ATOMIC);
-	if (!skb) {
-		skb = skb_dequeue(&np->skb_pool);
-		schedule_work(&np->refill_wq);
-	}
-
-	if (!skb) {
-		if (++count < 10) {
-			netpoll_poll_dev(np->dev);
-			goto repeat;
-		}
-		return NULL;
-	}
-
-	refcount_set(&skb->users, 1);
-	skb_reserve(skb, reserve);
-	return skb;
-}
-EXPORT_SYMBOL_GPL(find_skb);
+EXPORT_SYMBOL_GPL(zap_completion_queue);
 
 static int netpoll_owner_active(struct net_device *dev)
 {

-- 
2.53.0-Meta