[PATCH] Re: Serial: UART_BUG_TXEN race conditions

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

 



On Mon, Jun 26, 2006 at 09:25:36PM +0100, Russell King wrote:

> > 1. What if the IIR actually equals UART_IIR_THRI at that point? The
> >    read access will clear the interrupt condition and the workaround
> >    will effect the actual opposite of its intention: Neither
> >    serial8250_start_tx() nor the interrupt handler will start
> >    transmitting characters for the ring buffer.
> 
> Gah, looks like you're right - reading the IIR will clear the transmit
> pending interrupt, so we should probably just load the transmitter up
> with characters anyway if the TEMT bit is set.

Proposed patch. It's my first submission, I hope it meets this list's
standards.
The patch drops the buggy UART detection and always writes a first load
of characters into the transmitter FIFO if it's currently idle. This
should be fine for both well-behaved and broken UARTs.

Cheers,
Ingo


Signed-off-by: Ingo van Lil <[email protected]>
---

diff -u linux-2.6.17.1/drivers/serial/8250.c.orig linux-2.6.17.1/drivers/serial/8250.c
--- linux-2.6.17.1/drivers/serial/8250.c.orig	2006-06-27 21:37:41.000000000 +0200
+++ linux-2.6.17.1/drivers/serial/8250.c	2006-06-27 21:56:20.000000000 +0200
@@ -1119,18 +1119,13 @@
 static void serial8250_start_tx(struct uart_port *port)
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	unsigned char lsr;
 
 	if (!(up->ier & UART_IER_THRI)) {
 		up->ier |= UART_IER_THRI;
 		serial_out(up, UART_IER, up->ier);
-
-		if (up->bugs & UART_BUG_TXEN) {
-			unsigned char lsr, iir;
-			lsr = serial_in(up, UART_LSR);
-			iir = serial_in(up, UART_IIR);
-			if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)
-				transmit_chars(up);
-		}
+		lsr = serial_in(up, UART_LSR);
+		if (lsr & UART_LSR_TEMT) transmit_chars(up);
 	}
 
 	/*
@@ -1529,7 +1524,6 @@
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
 	unsigned long flags;
-	unsigned char lsr, iir;
 	int retval;
 
 	up->capabilities = uart_config[up->port.type].flags;
@@ -1634,25 +1628,6 @@
 
 	serial8250_set_mctrl(&up->port, up->port.mctrl);
 
-	/*
-	 * Do a quick test to see if we receive an
-	 * interrupt when we enable the TX irq.
-	 */
-	serial_outp(up, UART_IER, UART_IER_THRI);
-	lsr = serial_in(up, UART_LSR);
-	iir = serial_in(up, UART_IIR);
-	serial_outp(up, UART_IER, 0);
-
-	if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
-		if (!(up->bugs & UART_BUG_TXEN)) {
-			up->bugs |= UART_BUG_TXEN;
-			pr_debug("ttyS%d - enabling bad tx status workarounds\n",
-				 port->line);
-		}
-	} else {
-		up->bugs &= ~UART_BUG_TXEN;
-	}
-
 	spin_unlock_irqrestore(&up->port.lock, flags);
 
 	/*
diff -u linux-2.6.17.1/drivers/serial/8250.h.orig linux-2.6.17.1/drivers/serial/8250.h
--- linux-2.6.17.1/drivers/serial/8250.h.orig	2006-06-27 21:46:13.000000000 +0200
+++ linux-2.6.17.1/drivers/serial/8250.h	2006-06-27 21:46:35.000000000 +0200
@@ -48,8 +48,7 @@
 #define UART_CAP_UUE	(1 << 12)	/* UART needs IER bit 6 set (Xscale) */
 
 #define UART_BUG_QUOT	(1 << 0)	/* UART has buggy quot LSB */
-#define UART_BUG_TXEN	(1 << 1)	/* UART has buggy TX IIR status */
-#define UART_BUG_NOMSR	(1 << 2)	/* UART has buggy MSR status bits (Au1x00) */
+#define UART_BUG_NOMSR	(1 << 1)	/* UART has buggy MSR status bits (Au1x00) */
 
 #define PROBE_RSA	(1 << 0)
 #define PROBE_ANY	(~0)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux