[Patch 2/2] usb/serial/mct_usb232: add drain on close

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I ran the following test:

  while true; do echo -n "01234567890abcdefghij" >/dev/ttyUSB0; done

The data is sent over the serial line with random loss. It occurs because
1. when echo closes ttyUSB0, there's a chance that it cancels the write URB.
2. MCT U232 buffers the last character and acks the USB data before the
   serial bits are completely sent out.

This was originally reported in Red Hat Linux bug #170490.

The fix relies on modern facilities drain_delay (approximately the
number of bytes outstanding, see case #2 above) and chars_in_buffer.
The latter did not account for the last buffer that was removed
from the kfifo but not completed yet. I considered it a bug and
changed it.

The test above works as expected with this patch applied.

Signed-off-by: Pete Zaitcev <zaitcev@xxxxxxxxxx>

---
 drivers/usb/serial/generic.c  |   11 +++++++----
 drivers/usb/serial/mct_u232.c |    3 +++
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index bbe005c..3eea1d8 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -386,12 +386,15 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
 
 	dbg("%s - port %d", __func__, port->number);
 
+	spin_lock_irqsave(&port->lock, flags);
 	if (serial->type->max_in_flight_urbs) {
-		spin_lock_irqsave(&port->lock, flags);
 		chars = port->tx_bytes_flight;
-		spin_unlock_irqrestore(&port->lock, flags);
-	} else if (serial->num_bulk_out)
-		chars = kfifo_len(port->write_fifo);
+	} else if (serial->num_bulk_out) {
+		/* This overcounts badly, but is good enough for drain wait. */
+		chars = __kfifo_len(port->write_fifo);
+		chars += port->write_urb_busy * port->bulk_out_size;
+	}
+	spin_unlock_irqrestore(&port->lock, flags);
 
 	dbg("%s - returns %d", __func__, chars);
 	return chars;
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 1d2c138..2358773 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -540,8 +540,11 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
 
 static void mct_u232_close(struct usb_serial_port *port)
 {
+
 	dbg("%s port %d", __func__, port->number);
 
+	port->port.drain_delay = 2;
+
 	if (port->serial->dev) {
 		/* shutdown our urbs */
 		usb_kill_urb(port->write_urb);
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux