Re: Someting's busted with serial in 2.6.11 latest

From: Steven Cole
Date: Thu Mar 10 2005 - 19:05:57 EST


On Thursday 10 March 2005 03:59 pm, Russell King wrote:
> On Thu, Mar 10, 2005 at 03:40:11PM -0700, Steven Cole wrote:
> > I'll test current bk tonight, but I don't see any recent fix to
> > drivers/serial/8250.c when browsing linux.bkbits.net/linux-2.6.
>
> Ok, so Stephen's bug is already fixed. After testing the latest bk, if
> you find your bug isn't resolved, please try to isolate the change by
> applying this patch. If this doesn't resolve it, then your change of
> behaviour hasn't been caused by changes to 8250.c, but must be down to
> some other part of the kernel.
>
> ===== linux-2.6-rmk/drivers/serial/8250.c 1.97 vs 1.95 =====
> --- 1.97/drivers/serial/8250.c 2005-03-08 10:04:55 +00:00
> +++ 1.95/drivers/serial/8250.c 2005-02-28 16:05:18 +00:00
> @@ -642,7 +642,6 @@
> static void autoconfig_16550a(struct uart_8250_port *up)
> {
> unsigned char status1, status2;
> - unsigned int iersave;
>
> up->port.type = PORT_16550A;
> up->capabilities |= UART_CAP_FIFO;
> @@ -729,7 +728,6 @@
> serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
> status2 = serial_in(up, UART_IIR) >> 5;
> serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
> - serial_outp(up, UART_LCR, 0);
>
> DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
>
> @@ -738,40 +736,6 @@
> up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
> return;
> }
> -
> - /*
> - * Try writing and reading the UART_IER_UUE bit (b6).
> - * If it works, this is probably one of the Xscale platform's
> - * internal UARTs.
> - * We're going to explicitly set the UUE bit to 0 before
> - * trying to write and read a 1 just to make sure it's not
> - * already a 1 and maybe locked there before we even start start.
> - */
> - iersave = serial_in(up, UART_IER);
> - serial_outp(up, UART_IER, iersave & ~UART_IER_UUE);
> - if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
> - /*
> - * OK it's in a known zero state, try writing and reading
> - * without disturbing the current state of the other bits.
> - */
> - serial_outp(up, UART_IER, iersave | UART_IER_UUE);
> - if (serial_in(up, UART_IER) & UART_IER_UUE) {
> - /*
> - * It's an Xscale.
> - * We'll leave the UART_IER_UUE bit set to 1 (enabled).
> - */
> - DEBUG_AUTOCONF("Xscale ");
> - up->port.type = PORT_XSCALE;
> - return;
> - }
> - } else {
> - /*
> - * If we got here we couldn't force the IER_UUE bit to 0.
> - * Log it and continue.
> - */
> - DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
> - }
> - serial_outp(up, UART_IER, iersave);
> }
>
> /*
>
>
I am currently doing a bk pull from linux.bkbits.net/linux-2.6, and can test the above
patch if dialup via a serial modem breaks again, but I think I already know the answer.

I first noticed this _after_ the last one-line change to drivers/serial/8250.c.
Last night, after establishing that 2.6.11-bk1 was the earliest kernel to have the problem,
and reverting the Xscale patch fixed it, I tried with last night's bk-current.
It also failed as previously described, and worked with the Xscale patch reverted.

Here is a snippet from dmesg from my current kernel (with Xscale reverted) working
on dialup.via serial modem.

[ 43.034336] serio: i8042 AUX port at 0x60,0x64 irq 12
[ 43.034520] serio: i8042 KBD port at 0x60,0x64 irq 1
[ 43.034616] Serial: 8250/16550 driver $Revision: 1.90 $ 8 ports, IRQ sharing disabled
[ 43.034924] ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[ 43.038087] pnp: Device 00:01.00 activated.
[ 43.038329] ttyS1 at I/O 0x2f8 (irq = 10) is a 16550A

For completeness, here is the patch I applied with patch -p1 -R:

Steven
diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c
--- a/drivers/serial/8250.c 2005-02-28 08:05:18 -08:00
+++ b/drivers/serial/8250.c 2005-01-24 08:00:57 -08:00
@@ -642,6 +642,7 @@
static void autoconfig_16550a(struct uart_8250_port *up)
{
unsigned char status1, status2;
+ unsigned int iersave;

up->port.type = PORT_16550A;
up->capabilities |= UART_CAP_FIFO;
@@ -736,6 +737,40 @@
up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
return;
}
+
+ /*
+ * Try writing and reading the UART_IER_UUE bit (b6).
+ * If it works, this is probably one of the Xscale platform's
+ * internal UARTs.
+ * We're going to explicitly set the UUE bit to 0 before
+ * trying to write and read a 1 just to make sure it's not
+ * already a 1 and maybe locked there before we even start start.
+ */
+ iersave = serial_in(up, UART_IER);
+ serial_outp(up, UART_IER, iersave & ~UART_IER_UUE);
+ if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
+ /*
+ * OK it's in a known zero state, try writing and reading
+ * without disturbing the current state of the other bits.
+ */
+ serial_outp(up, UART_IER, iersave | UART_IER_UUE);
+ if (serial_in(up, UART_IER) & UART_IER_UUE) {
+ /*
+ * It's an Xscale.
+ * We'll leave the UART_IER_UUE bit set to 1 (enabled).
+ */
+ DEBUG_AUTOCONF("Xscale ");
+ up->port.type = PORT_XSCALE;
+ return;
+ }
+ } else {
+ /*
+ * If we got here we couldn't force the IER_UUE bit to 0.
+ * Log it and continue.
+ */
+ DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
+ }
+ serial_outp(up, UART_IER, iersave);
}

/*