From mboxrd@z Thu Jan 1 00:00:00 1970 From: vb@vsbe.com Subject: Re: [PATCH] 8250: add workaround for MPC8[356]xx UART break IRQ storm Date: Tue, 2 Mar 2010 13:21:49 -0800 Message-ID: References: <1267212301-26851-1-git-send-email-paul.gortmaker@windriver.com> <4B8D3C59.4080504@windriver.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: QUOTED-PRINTABLE Return-path: Received: from mout.perfora.net ([74.208.4.195]:49648 "EHLO mout.perfora.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751546Ab0CBVWN convert rfc822-to-8bit (ORCPT ); Tue, 2 Mar 2010 16:22:13 -0500 Received: by pzk39 with SMTP id 39so229183pzk.15 for ; Tue, 02 Mar 2010 13:22:09 -0800 (PST) In-Reply-To: <4B8D3C59.4080504@windriver.com> Sender: linux-serial-owner@vger.kernel.org List-Id: linux-serial@vger.kernel.org To: Paul Gortmaker Cc: linuxppc-dev@lists.ozlabs.org, linux-serial@vger.kernel.org On Tue, Mar 2, 2010 at 8:27 AM, Paul Gortmaker wrote: > On 10-03-01 06:03 PM, vb@vsbe.com wrote: >> sounds very much like this issue: >> >> http://linux.derkeiler.com/Mailing-Lists/Kernel/2010-02/msg09470.htm= l > > Thanks for the link. > >> >> (interrupt storm on the second port which is hit with breaks). >> >> It's not the uart driver problem per se, the below fixes it: > > Actually, it is a uart *hardware* problem -- see in this same > thread where Scott Wood described an errata, and when I > implemented his interpretation of what the fix should look > like, things just worked. =A0You might want to try out that patch > and see if it helps you, since from the link above, I see you > are also on a powerpc board. > > Paul. > yeah, I was not aware of the hardware bug you are describing, it's just the scenario I encountered is very similar: the serial interface is flooded with breaks, after a while the prot generates an IRQ storm. But the storm happens only after the port gets shut down (by getty in my case). In my case this behavior is due to a SW bug, you might be hitting the HW problem, I have not seen it yet, cheers, /vb >> >> *** linux/drivers/serial/serial_core.c#1 =A0 =A0 =A0 =A0Wed Feb 24 1= 7:46:22 2010 >> --- =A0linux/drivers/serial/serial_core.c#2 =A0 =A0 =A0 =A0Mon Mar =A0= 1 15:00:29 2010 >> *************** >> *** 622,632 **** >> =A0 =A0 =A0 =A0 =A0struct uart_port *port =3D state->port; >> >> =A0 =A0 =A0 =A0 =A0if (I_IXOFF(tty)) { >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (port->x_char) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0port->x_char =3D = 0; >> ! =A0 =A0 =A0 =A0 =A0 =A0 =A0 else >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0uart_send_xchar(t= ty, START_CHAR(tty)); >> =A0 =A0 =A0 =A0 =A0} >> >> =A0 =A0 =A0 =A0 =A0if (tty->termios->c_cflag& =A0CRTSCTS) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0uart_set_mctrl(port, TIOCM_RTS); >> --- 622,632 ---- >> =A0 =A0 =A0 =A0 =A0struct uart_port *port =3D state->port; >> >> =A0 =A0 =A0 =A0 =A0if (I_IXOFF(tty)) { >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (port->x_char) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0port->x_char =3D = 0; >> ! =A0 =A0 =A0 =A0 =A0 =A0 =A0 else if (!(tty->flags& =A0(1<< =A0TTY_= IO_ERROR))) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0uart_send_xchar(t= ty, START_CHAR(tty)); >> =A0 =A0 =A0 =A0 =A0} >> >> =A0 =A0 =A0 =A0 =A0if (tty->termios->c_cflag& =A0CRTSCTS) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0uart_set_mctrl(port, TIOCM_RTS); >> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^= ^^^^^^^^^^^^^^^^^^^^^^^^^^ >> >> I did not get to trying to submit it, but it sure gets rid o the sto= rm. >> >> cheers, >> /vb >> >> On Fri, Feb 26, 2010 at 11:25 AM, Paul Gortmaker >> =A0wrote: >>> Sending a break on the SOC UARTs found in some MPC83xx/85xx/86xx >>> chips seems to cause a short lived IRQ storm (/proc/interrupts >>> typically shows somewhere between 300 and 1500 events). =A0Unfortun= ately >>> this renders SysRQ over the serial console completely inoperable. >>> Testing with obvious things like ACKing the event doesn't seem to >>> change anything vs. a completely dumb approach of just ignoring >>> it and waiting for it to stop, so that is what is implemented here. >>> >>> Signed-off-by: Paul Gortmaker >>> --- >>> >>> This is a refresh of a patch I'd done earlier -- I've tried to make >>> the bug support as generic as possible to minimize having board >>> specific ifdef crap in 8250.c -- any suggestions on how to further >>> improve it are welcome. >>> >>> =A0 drivers/serial/8250.c =A0 =A0 =A0| =A0 =A06 ++++++ >>> =A0 drivers/serial/8250.h =A0 =A0 =A0| =A0 20 ++++++++++++++++++++ >>> =A0 drivers/serial/Kconfig =A0 =A0 | =A0 14 ++++++++++++++ >>> =A0 include/linux/serial_reg.h | =A0 =A02 ++ >>> =A0 4 files changed, 42 insertions(+), 0 deletions(-) >>> >>> diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c >>> index e9b15c3..850b0e9 100644 >>> --- a/drivers/serial/8250.c >>> +++ b/drivers/serial/8250.c >>> @@ -1531,6 +1531,11 @@ static void serial8250_handle_port(struct ua= rt_8250_port *up) >>> >>> =A0 =A0 =A0 =A0 status =3D serial_inp(up, UART_LSR); >>> >>> + =A0 =A0 =A0 if ((up->bugs& =A0UART_BUG_PPC)&& =A0(status =3D=3D U= ART_LSR_RFE_ERROR_BITS)) { >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 spin_unlock_irqrestore(&up->port.lock= , flags); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return; >>> + =A0 =A0 =A0 } >>> + >>> =A0 =A0 =A0 =A0 DEBUG_INTR("status =3D %x...", status); >>> >>> =A0 =A0 =A0 =A0 if (status& =A0(UART_LSR_DR | UART_LSR_BI)) >>> @@ -1948,6 +1953,7 @@ static int serial8250_startup(struct uart_por= t *port) >>> >>> =A0 =A0 =A0 =A0 up->capabilities =3D uart_config[up->port.type].fla= gs; >>> =A0 =A0 =A0 =A0 up->mcr =3D 0; >>> + =A0 =A0 =A0 up->bugs |=3D UART_KNOWN_BUGS; >>> >>> =A0 =A0 =A0 =A0 if (up->port.iotype !=3D up->cur_iotype) >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_io_from_upio(port); >>> diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h >>> index 6e19ea3..2074ce1 100644 >>> --- a/drivers/serial/8250.h >>> +++ b/drivers/serial/8250.h >>> @@ -49,6 +49,7 @@ struct serial8250_config { >>> =A0 #define UART_BUG_TXEN =A0(1<< =A01) =A0 =A0 =A0 =A0/* UART has = buggy TX IIR status */ >>> =A0 #define UART_BUG_NOMSR (1<< =A02) =A0 =A0 =A0 =A0/* UART has bu= ggy MSR status bits (Au1x00) */ >>> =A0 #define UART_BUG_THRE =A0(1<< =A03) =A0 =A0 =A0 =A0/* UART has = buggy THRE reassertion */ >>> +#define UART_BUG_PPC =A0 (1<< =A04) =A0 =A0 =A0 =A0/* UART has bug= gy PPC break IRQ storm */ >>> >>> =A0 #define PROBE_RSA =A0 =A0 =A0(1<< =A00) >>> =A0 #define PROBE_ANY =A0 =A0 =A0(~0) >>> @@ -78,3 +79,22 @@ struct serial8250_config { >>> =A0 #else >>> =A0 #define ALPHA_KLUDGE_MCR 0 >>> =A0 #endif >>> + >>> +/* >>> + * The following UART bugs are currently dynamically detected and = not >>> + * required to be contingent on any particular compile time option= s. >>> + */ >>> +#define HAS_BUG_QUOT =A0 0 =A0 =A0 =A0 /* assign UART_BUG_QUOT to = enable */ >>> +#define HAS_BUG_TXEN =A0 0 =A0 =A0 =A0 /* assign UART_BUG_TXEN to = enable */ >>> +#define HAS_BUG_NOMSR =A00 =A0 =A0 =A0 /* assign UART_BUG_NOMSR to= enable */ >>> +#define HAS_BUG_THRE =A0 0 =A0 =A0 =A0 /* assign UART_BUG_THRE to = enable */ >>> + >>> +#ifdef CONFIG_SERIAL_8250_PPC_BUG >>> +#define HAS_BUG_PPC =A0 =A0UART_BUG_PPC >>> +#else >>> +#define HAS_BUG_PPC =A0 =A00 >>> +#endif >>> + >>> +#define UART_KNOWN_BUGS (HAS_BUG_QUOT | HAS_BUG_TXEN | HAS_BUG_NOM= SR | \ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 HAS_BUG_THRE | HAS_BU= G_PPC) >>> + >>> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig >>> index 9ff47db..e01a411 100644 >>> --- a/drivers/serial/Kconfig >>> +++ b/drivers/serial/Kconfig >>> @@ -70,6 +70,20 @@ config SERIAL_8250_CONSOLE >>> >>> =A0 =A0 =A0 =A0 =A0 If unsure, say N. >>> >>> +config SERIAL_8250_PPC_BUG >>> + =A0 =A0 =A0 bool "Fix 8250/16550 to handle IRQ storm after receip= t of a break" >>> + =A0 =A0 =A0 depends on SERIAL_8250&& =A0PPC32 >>> + =A0 =A0 =A0 ---help--- >>> + =A0 =A0 =A0 =A0 If you say Y here, addional checks will be added = in the handling of >>> + =A0 =A0 =A0 =A0 interrupts on the serial ports which will prevent= ill effects of >>> + =A0 =A0 =A0 =A0 an interrupt storm triggered by a break on the se= rial line. Without >>> + =A0 =A0 =A0 =A0 this enabled, a Sysrq via the serial console can = be unusable on >>> + =A0 =A0 =A0 =A0 some systems. >>> + >>> + =A0 =A0 =A0 =A0 This is commonly observed on PPC32 MPC83xx/85xx/8= 6xx based boards. >>> + >>> + =A0 =A0 =A0 =A0 If unsure, say N. >>> + >>> =A0 config FIX_EARLYCON_MEM >>> =A0 =A0 =A0 =A0 bool >>> =A0 =A0 =A0 =A0 depends on X86 >>> diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.= h >>> index cf9327c..010174f 100644 >>> --- a/include/linux/serial_reg.h >>> +++ b/include/linux/serial_reg.h >>> @@ -111,6 +111,7 @@ >>> =A0 #define UART_MCR_DTR =A0 =A0 =A0 =A0 =A0 0x01 /* DTR complement= */ >>> >>> =A0 #define UART_LSR =A0 =A0 =A0 5 =A0 =A0 =A0 /* In: =A0Line Statu= s Register */ >>> +#define UART_LSR_RFE =A0 =A0 =A0 =A0 =A0 0x80 /* Rx FIFO Error (BE= , FE, or PE) */ >>> =A0 #define UART_LSR_TEMT =A0 =A0 =A0 =A0 =A00x40 /* Transmitter em= pty */ >>> =A0 #define UART_LSR_THRE =A0 =A0 =A0 =A0 =A00x20 /* Transmit-hold-= register empty */ >>> =A0 #define UART_LSR_BI =A0 =A0 =A0 =A0 =A0 =A00x10 /* Break interr= upt indicator */ >>> @@ -119,6 +120,7 @@ >>> =A0 #define UART_LSR_OE =A0 =A0 =A0 =A0 =A0 =A00x02 /* Overrun erro= r indicator */ >>> =A0 #define UART_LSR_DR =A0 =A0 =A0 =A0 =A0 =A00x01 /* Receiver dat= a ready */ >>> =A0 #define UART_LSR_BRK_ERROR_BITS =A0 =A0 =A0 =A00x1E /* BI, FE, = PE, OE bits */ >>> +#define UART_LSR_RFE_ERROR_BITS =A0 =A0 =A0 =A00xF1 /* RFE, TEMT, = THRE, BI, DR bits */ >>> >>> =A0 #define UART_MSR =A0 =A0 =A0 6 =A0 =A0 =A0 /* In: =A0Modem Stat= us Register */ >>> =A0 #define UART_MSR_DCD =A0 =A0 =A0 =A0 =A0 0x80 /* Data Carrier D= etect */ >>> -- >>> 1.6.5.2 >>> >>> _______________________________________________ >>> Linuxppc-dev mailing list >>> Linuxppc-dev@lists.ozlabs.org >>> https://lists.ozlabs.org/listinfo/linuxppc-dev >>> > > -- To unsubscribe from this list: send the line "unsubscribe linux-serial"= in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html