All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ladislav Michl <ladis@linux-mips.org>
To: linux-usb@vger.kernel.org, linux-serial@vger.kernel.org
Cc: "Felipe Balbi" <balbi@kernel.org>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Michał Mirosław" <mirq-linux@rere.qmqm.pl>
Subject: [PATCH v2 4/5] usb: gadget: u_serial: Fix starving write
Date: Sat, 13 Jul 2019 23:11:58 +0200	[thread overview]
Message-ID: <20190713211158.GE25753@lenoch> (raw)
In-Reply-To: <20190713210853.GA25753@lenoch>

Writing to ttyGS unconnected to host currently fills port_write_buf
which then causes gs_write_room to return 0 and boot hangs waiting
for connection.
Fix that by dropping previsous data if free space in port_write_buf
reaches treshold and host is unconnected.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 Changes:
 - v2: New patch

 drivers/usb/gadget/function/u_serial.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c
index 558a6929ce68..2dd6e1211d4a 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -79,6 +79,7 @@
  */
 #define QUEUE_SIZE		16
 #define WRITE_BUF_SIZE		8192		/* TX only */
+#define WRITE_BUF_TRESHOLD	1024
 #define GS_CONSOLE_BUF_SIZE	8192
 
 /* console info */
@@ -562,7 +563,7 @@ static int gs_start_io(struct gs_port *port)
 
 	/* unblock any pending writes into our circular buffer */
 	if (started) {
-		tty_wakeup(port->port.tty);
+		gs_start_tx(port);
 	} else {
 		gs_free_requests(ep, head, &port->read_allocated);
 		gs_free_requests(port->port_usb->in, &port->write_pool,
@@ -758,6 +759,7 @@ static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
 	struct gs_port	*port = tty->driver_data;
 	unsigned long	flags;
+	int		avail, cnt;
 
 	pr_vdebug("gs_write: ttyGS%d (%p) writing %d bytes\n",
 			port->port_num, tty, count);
@@ -766,8 +768,16 @@ static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
 	if (count)
 		count = kfifo_in(&port->port_write_buf, buf, count);
 	/* treat count == 0 as flush_chars() */
-	if (port->port_usb)
+	if (port->port_usb) {
 		gs_start_tx(port);
+	} else {
+		avail = kfifo_avail(&port->port_write_buf);
+		if (avail < WRITE_BUF_TRESHOLD) {
+			cnt = WRITE_BUF_TRESHOLD - avail;
+			while (cnt--)
+				kfifo_skip(&port->port_write_buf);
+		}
+	}
 	spin_unlock_irqrestore(&port->port_lock, flags);
 
 	return count;
@@ -784,6 +794,9 @@ static int gs_put_char(struct tty_struct *tty, unsigned char ch)
 
 	spin_lock_irqsave(&port->port_lock, flags);
 	status = kfifo_put(&port->port_write_buf, ch);
+	if (!port->port_usb &&
+	     kfifo_avail(&port->port_write_buf) < WRITE_BUF_TRESHOLD)
+		kfifo_skip(&port->port_write_buf);
 	spin_unlock_irqrestore(&port->port_lock, flags);
 
 	return status;
@@ -799,6 +812,8 @@ static void gs_flush_chars(struct tty_struct *tty)
 	spin_lock_irqsave(&port->port_lock, flags);
 	if (port->port_usb)
 		gs_start_tx(port);
+	else
+		kfifo_reset_out(&port->port_write_buf);
 	spin_unlock_irqrestore(&port->port_lock, flags);
 }
 
@@ -806,11 +821,10 @@ static int gs_write_room(struct tty_struct *tty)
 {
 	struct gs_port	*port = tty->driver_data;
 	unsigned long	flags;
-	int		room = 0;
+	int		room;
 
 	spin_lock_irqsave(&port->port_lock, flags);
-	if (port->port_usb)
-		room = kfifo_avail(&port->port_write_buf);
+	room = kfifo_avail(&port->port_write_buf);
 	spin_unlock_irqrestore(&port->port_lock, flags);
 
 	pr_vdebug("gs_write_room: (%d,%p) room=%d\n",
@@ -823,7 +837,7 @@ static int gs_chars_in_buffer(struct tty_struct *tty)
 {
 	struct gs_port	*port = tty->driver_data;
 	unsigned long	flags;
-	int		chars = 0;
+	int		chars;
 
 	spin_lock_irqsave(&port->port_lock, flags);
 	chars = kfifo_len(&port->port_write_buf);
-- 
2.22.0


  parent reply	other threads:[~2019-07-13 21:12 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-13 21:08 [PATCH v2 0/5] usb: gadget: u_serial: Fix and cleanup Ladislav Michl
2019-07-13 21:10 ` [PATCH v2 1/5] usb: gadget: u_serial: Fix console_req complete event race Ladislav Michl
2019-07-13 21:10 ` [PATCH v2 2/5] usb: gadget: u_serial: Remove console specific alloc/free req functions Ladislav Michl
2019-07-13 21:11 ` [PATCH v2 3/5] usb: gadget: u_serial: Fix console_req access race Ladislav Michl
2019-07-13 21:11 ` Ladislav Michl [this message]
2019-07-13 21:12 ` [PATCH v2 5/5] usb: gadget: u_serial: Use bool for req_busy Ladislav Michl
2019-07-14 10:04 ` [PATCH v2 0/5] usb: gadget: u_serial: Fix and cleanup Michał Mirosław
2019-07-14 11:37   ` Michał Mirosław
2019-07-14 13:22     ` Ladislav Michl
2019-07-15 10:40   ` Ladislav Michl

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190713211158.GE25753@lenoch \
    --to=ladis@linux-mips.org \
    --cc=balbi@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=mirq-linux@rere.qmqm.pl \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.