[PATCH] Proper RTS control when buffers fill

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

 



Enables usb generic functions for throttle/unthrottle to prevent USB data
loss. CP210x hardware disables RTS but leaves CTS when in hardware flow
control mode and port is closed. When re-opening the serial port, if CTS
is enabled, then RTS must be re-enabled inside the driver.

Signed-off-by: Brant Merryman <brant.merryman@xxxxxxxxxx>
---
 drivers/usb/serial/cp210x.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index f5143eedbc48..fd54181e741b 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -272,6 +272,8 @@ static struct usb_serial_driver cp210x_device = {
 	.break_ctl		= cp210x_break_ctl,
 	.set_termios		= cp210x_set_termios,
 	.tx_empty		= cp210x_tx_empty,
+	.throttle		= usb_serial_generic_throttle,
+	.unthrottle		= usb_serial_generic_unthrottle,
 	.tiocmget		= cp210x_tiocmget,
 	.tiocmset		= cp210x_tiocmset,
 	.attach			= cp210x_attach,
@@ -915,6 +917,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
 	u32 baud;
 	u16 bits;
 	u32 ctl_hs;
+	u32 flow_repl;
 
 	cp210x_read_u32_reg(port, CP210X_GET_BAUDRATE, &baud);
 
@@ -1013,8 +1016,24 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
 	cp210x_read_reg_block(port, CP210X_GET_FLOW, &flow_ctl,
 			sizeof(flow_ctl));
 	ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake);
+	flow_repl = le32_to_cpu(flow_ctl.ulFlowReplace);
+	/* CP210x hardware disables RTS but leaves CTS when in hardware
+	 * flow control mode and port is closed.
+	 * This allows data to flow out, but new data will not come into
+	 * the port. When re-opening the port, if CTS is enabled, then RTS
+	 * must be re-enabled. in the driver
+	 */
 	if (ctl_hs & CP210X_SERIAL_CTS_HANDSHAKE) {
 		dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__);
+		flow_repl &= ~CP210X_SERIAL_RTS_MASK;
+		flow_repl |= CP210X_SERIAL_RTS_SHIFT(
+			CP210X_SERIAL_RTS_FLOW_CTL);
+
+		flow_ctl.ulControlHandshake = cpu_to_le32(ctl_hs);
+		flow_ctl.ulFlowReplace = cpu_to_le32(flow_repl);
+		cp210x_write_reg_block(port, CP210X_SET_FLOW,
+			&flow_ctl, sizeof(flow_ctl));
+
 		cflag |= CRTSCTS;
 	} else {
 		dev_dbg(dev, "%s - flow control = NONE\n", __func__);
-- 



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

  Powered by Linux