diff mbox series

[08/10] net: wwan: core: implement TIOCINQ ioctl

Message ID 20210608040241.10658-9-ryazanov.s.a@gmail.com (mailing list archive)
State Accepted
Commit e263c5b2e8912149b49d757511d85a16c5fb432f
Delegated to: Netdev Maintainers
Headers show
Series net: WWAN subsystem improvements | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count success Link
netdev/tree_selection success Guessed tree name to be net-next
netdev/subject_prefix warning Target tree name not specified in the subject
netdev/cc_maintainers warning 1 maintainers not CCed: leon@kernel.org
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 47 lines checked
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/header_inline success Link

Commit Message

Sergey Ryazanov June 8, 2021, 4:02 a.m. UTC
It is quite common for a userpace program to fetch the buffered amount
of data in the rx queue to avoid the read block. Implement the TIOCINQ
ioctl to make the migration to the WWAN port usage smooth.

Despite the fact that the read call will return no more data than the
size of a first skb in the queue, TIOCINQ returns the entire amount of
buffered data (sum of all queued skbs). This is done to prevent the
breaking of programs that optimize reading, avoiding it if the buffered
amount of data is too small.

Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
---
 drivers/net/wwan/wwan_core.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

Comments

Loic Poulain June 8, 2021, 8:51 a.m. UTC | #1
On Tue, 8 Jun 2021 at 06:02, Sergey Ryazanov <ryazanov.s.a@gmail.com> wrote:
>
> It is quite common for a userpace program to fetch the buffered amount
> of data in the rx queue to avoid the read block. Implement the TIOCINQ
> ioctl to make the migration to the WWAN port usage smooth.
>
> Despite the fact that the read call will return no more data than the
> size of a first skb in the queue, TIOCINQ returns the entire amount of
> buffered data (sum of all queued skbs). This is done to prevent the
> breaking of programs that optimize reading, avoiding it if the buffered
> amount of data is too small.
>
> Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>

Reviewed-by: Loic Poulain <loic.poulain@linaro.org>
diff mbox series

Patch

diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c
index 9346b2661eb3..d5a197da4a41 100644
--- a/drivers/net/wwan/wwan_core.c
+++ b/drivers/net/wwan/wwan_core.c
@@ -12,6 +12,7 @@ 
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <linux/types.h>
+#include <linux/termios.h>
 #include <linux/wwan.h>
 
 /* Maximum number of minors in use */
@@ -618,6 +619,30 @@  static __poll_t wwan_port_fops_poll(struct file *filp, poll_table *wait)
 	return mask;
 }
 
+static long wwan_port_fops_ioctl(struct file *filp, unsigned int cmd,
+				 unsigned long arg)
+{
+	struct wwan_port *port = filp->private_data;
+
+	switch (cmd) {
+	case TIOCINQ: {	/* aka SIOCINQ aka FIONREAD */
+		unsigned long flags;
+		struct sk_buff *skb;
+		int amount = 0;
+
+		spin_lock_irqsave(&port->rxq.lock, flags);
+		skb_queue_walk(&port->rxq, skb)
+			amount += skb->len;
+		spin_unlock_irqrestore(&port->rxq.lock, flags);
+
+		return put_user(amount, (int __user *)arg);
+	}
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
 static const struct file_operations wwan_port_fops = {
 	.owner = THIS_MODULE,
 	.open = wwan_port_fops_open,
@@ -625,6 +650,10 @@  static const struct file_operations wwan_port_fops = {
 	.read = wwan_port_fops_read,
 	.write = wwan_port_fops_write,
 	.poll = wwan_port_fops_poll,
+	.unlocked_ioctl = wwan_port_fops_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = compat_ptr_ioctl,
+#endif
 	.llseek = noop_llseek,
 };