[PATCH] serial: 8250: respect rts_before_send before sending chars

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

 



serial8250_tx_chars() is called from several places and the callers don't
consider that sending might not be allowed yet because the
rts_before_send delay isn't over yet.

So teach serial8250_tx_chars() about rts_before_send and delay the
request accordingly if required.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx>
---
Cc: Tomas Melin <tomas.melin@xxxxxxxxxxx>
Cc: Daniel Golle <daniel@xxxxxxxxxxxxxx>
Cc: Ricardo Ribalda Delgado <ricardo.ribalda@xxxxxxxxx>
Cc: Lukas Wunner <lukas@xxxxxxxxx>
Cc: Aaron Sierra <asierra@xxxxxxxxxxx>
Cc: Rafael Gago <rafael.gago@xxxxxxxxx>
Cc: Daniel Jedrychowski <avistel@xxxxxxxxx>

Hello,

on a powerpc (MPC8313) this patch prevents sending characters too early
after an edge on CTS is detected. As the 8250 driver is quite "advanced"
I'd welcome testing feedback for other chip variants, so I added a few
people to Cc who did rs485 stuff in the past.

 drivers/tty/serial/8250/8250_port.c | 31 +++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 3f779d25ec0c..d8d7456f8ec3 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1548,6 +1548,8 @@ static void serial8250_stop_tx(struct uart_port *port)
 	serial8250_rpm_put(up);
 }
 
+static void __serial8250_tx_chars(struct uart_8250_port *up);
+
 static inline void __start_tx(struct uart_port *port)
 {
 	struct uart_8250_port *up = up_to_u8250p(port);
@@ -1565,7 +1567,7 @@ static inline void __start_tx(struct uart_port *port)
 			lsr = serial_in(up, UART_LSR);
 			up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
 			if (lsr & UART_LSR_THRE)
-				serial8250_tx_chars(up);
+				__serial8250_tx_chars(up);
 		}
 	}
 
@@ -1765,7 +1767,7 @@ unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
 }
 EXPORT_SYMBOL_GPL(serial8250_rx_chars);
 
-void serial8250_tx_chars(struct uart_8250_port *up)
+static void __serial8250_tx_chars(struct uart_8250_port *up)
 {
 	struct uart_port *port = &up->port;
 	struct circ_buf *xmit = &port->state->xmit;
@@ -1813,6 +1815,31 @@ void serial8250_tx_chars(struct uart_8250_port *up)
 	if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))
 		__stop_tx(up);
 }
+
+/* called with port->lock taken and irqs off */
+void serial8250_tx_chars(struct uart_8250_port *up)
+{
+	struct uart_8250_em485 *em485;
+
+	em485 = up->em485;
+	if (em485) {
+		if (em485->active_timer == &em485->start_tx_timer)
+			/*
+			 * Still waiting for rts_before_send delay. When the
+			 * timer triggers it will start tx.
+			 */
+			return;
+
+		/*
+		 * tx might have finshed before and the driver waits for
+		 * rts_after_send. Now as there is new data to be sent this
+		 * is void.
+		 */
+		em485->active_timer = NULL;
+	}
+
+	__serial8250_tx_chars(up);
+}
 EXPORT_SYMBOL_GPL(serial8250_tx_chars);
 
 /* Caller holds uart port lock */
-- 
2.19.0




[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux