[PATCH net-next v7 4/9] tun/tap: add batched ptr_ring consume functions with netdev queue wakeup
From: Simon Schippers <hidden>
Date: 2026-01-07 21:06:15
Also in:
kvm, lkml, virtualization
Subsystem:
networking drivers, the rest, tun/tap driver · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds, Willem de Bruijn, Jason Wang
Add {tun,tap}_ring_consume_batched() that wrap
__ptr_ring_consume_batched() and wake the corresponding netdev subqueue
when consuming the entries frees space in the ptr_ring.
These wrappers are supposed to be used by vhost-net in an upcoming
commit.
Co-developed-by: Tim Gebauer <redacted>
Signed-off-by: Tim Gebauer <redacted>
Signed-off-by: Simon Schippers <redacted>
---
drivers/net/tap.c | 23 +++++++++++++++++++++++
drivers/net/tun.c | 23 +++++++++++++++++++++++
include/linux/if_tap.h | 6 ++++++
include/linux/if_tun.h | 7 +++++++
4 files changed, 59 insertions(+)
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 2442cf7ac385..7e3b4eed797c 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c@@ -774,6 +774,29 @@ static void *tap_ring_consume(struct tap_queue *q) return ptr; } +int tap_ring_consume_batched(struct file *file, void **array, int n) +{ + struct tap_queue *q = file->private_data; + struct ptr_ring *ring = &q->ring; + struct net_device *dev; + int i; + + spin_lock(&ring->consumer_lock); + + i = __ptr_ring_consume_batched(ring, array, n); + if (__ptr_ring_consume_created_space(ring, i)) { + rcu_read_lock(); + dev = rcu_dereference(q->tap)->dev; + netif_wake_subqueue(dev, q->queue_index); + rcu_read_unlock(); + } + + spin_unlock(&ring->consumer_lock); + + return i; +} +EXPORT_SYMBOL_GPL(tap_ring_consume_batched); + static ssize_t tap_do_read(struct tap_queue *q, struct iov_iter *to, int noblock, struct sk_buff *skb)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 7148f9a844a4..db3b72025cfb 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c@@ -3736,6 +3736,29 @@ struct socket *tun_get_socket(struct file *file) } EXPORT_SYMBOL_GPL(tun_get_socket); +int tun_ring_consume_batched(struct file *file, void **array, int n) +{ + struct tun_file *tfile = file->private_data; + struct ptr_ring *ring = &tfile->tx_ring; + struct net_device *dev; + int i; + + spin_lock(&ring->consumer_lock); + + i = __ptr_ring_consume_batched(ring, array, n); + if (__ptr_ring_consume_created_space(ring, i)) { + rcu_read_lock(); + dev = rcu_dereference(tfile->tun)->dev; + netif_wake_subqueue(dev, tfile->queue_index); + rcu_read_unlock(); + } + + spin_unlock(&ring->consumer_lock); + + return i; +} +EXPORT_SYMBOL_GPL(tun_ring_consume_batched); + struct ptr_ring *tun_get_tx_ring(struct file *file) { struct tun_file *tfile;
diff --git a/include/linux/if_tap.h b/include/linux/if_tap.h
index 553552fa635c..cf8b90320b8d 100644
--- a/include/linux/if_tap.h
+++ b/include/linux/if_tap.h@@ -11,6 +11,7 @@ struct socket; #if IS_ENABLED(CONFIG_TAP) struct socket *tap_get_socket(struct file *); struct ptr_ring *tap_get_ptr_ring(struct file *file); +int tap_ring_consume_batched(struct file *file, void **array, int n); #else #include <linux/err.h> #include <linux/errno.h>
@@ -22,6 +23,11 @@ static inline struct ptr_ring *tap_get_ptr_ring(struct file *f) { return ERR_PTR(-EINVAL); } +static inline int tap_ring_consume_batched(struct file *f, + void **array, int n) +{ + return 0; +} #endif /* CONFIG_TAP */ /*
diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h
index 80166eb62f41..444dda75a372 100644
--- a/include/linux/if_tun.h
+++ b/include/linux/if_tun.h@@ -22,6 +22,7 @@ struct tun_msg_ctl { #if defined(CONFIG_TUN) || defined(CONFIG_TUN_MODULE) struct socket *tun_get_socket(struct file *); struct ptr_ring *tun_get_tx_ring(struct file *file); +int tun_ring_consume_batched(struct file *file, void **array, int n); static inline bool tun_is_xdp_frame(void *ptr) {
@@ -55,6 +56,12 @@ static inline struct ptr_ring *tun_get_tx_ring(struct file *f) return ERR_PTR(-EINVAL); } +static inline int tun_ring_consume_batched(struct file *file, + void **array, int n) +{ + return 0; +} + static inline bool tun_is_xdp_frame(void *ptr) { return false;
--
2.43.0