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 <[email protected]> Signed-off-by: Tim Gebauer <[email protected]> Signed-off-by: Simon Schippers <[email protected]> --- 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

