Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pch_uart: add sysrq support

When send break to the uart port, we always get 'frame error', but we
can not just reset receive fifo in such case, otherwise the sysrq cmd
will not be received correctly.

When we handle sysrq output via pch_console_write, the priv lock has
already been taken so no need to take the lock in pch_console_write.

Signed-off-by: Liang Li <liang.li@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Liang Li and committed by
Greg Kroah-Hartman
1f9db092 384e301e

+19 -8
+19 -8
drivers/tty/serial/pch_uart.c
··· 14 14 *along with this program; if not, write to the Free Software 15 15 *Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 16 16 */ 17 + #if defined(CONFIG_SERIAL_PCH_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) 18 + #define SUPPORT_SYSRQ 19 + #endif 17 20 #include <linux/kernel.h> 18 21 #include <linux/serial_reg.h> 19 22 #include <linux/slab.h> 20 23 #include <linux/module.h> 21 24 #include <linux/pci.h> 25 + #include <linux/console.h> 22 26 #include <linux/serial_core.h> 23 27 #include <linux/tty.h> 24 28 #include <linux/tty_flip.h> 25 29 #include <linux/interrupt.h> 26 30 #include <linux/io.h> 27 31 #include <linux/dmi.h> 28 - #include <linux/console.h> 29 32 #include <linux/nmi.h> 30 33 #include <linux/delay.h> 31 34 ··· 556 553 { 557 554 int i; 558 555 u8 rbr, lsr; 556 + struct uart_port *port = &priv->port; 559 557 560 558 lsr = ioread8(priv->membase + UART_LSR); 561 559 for (i = 0, lsr = ioread8(priv->membase + UART_LSR); 562 - i < rx_size && lsr & UART_LSR_DR; 560 + i < rx_size && lsr & (UART_LSR_DR | UART_LSR_BI); 563 561 lsr = ioread8(priv->membase + UART_LSR)) { 564 562 rbr = ioread8(priv->membase + PCH_UART_RBR); 563 + 564 + if (lsr & UART_LSR_BI) { 565 + port->icount.brk++; 566 + if (uart_handle_break(port)) 567 + continue; 568 + } 569 + if (port->sysrq) { 570 + if (uart_handle_sysrq_char(port, rbr)) 571 + continue; 572 + } 573 + 565 574 buf[i++] = rbr; 566 575 } 567 576 return i; ··· 1038 1023 1039 1024 static void pch_uart_err_ir(struct eg20t_port *priv, unsigned int lsr) 1040 1025 { 1041 - u8 fcr = ioread8(priv->membase + UART_FCR); 1042 1026 struct uart_port *port = &priv->port; 1043 1027 struct tty_struct *tty = tty_port_tty_get(&port->state->port); 1044 1028 char *error_msg[5] = {}; 1045 1029 int i = 0; 1046 - 1047 - /* Reset FIFO */ 1048 - fcr |= UART_FCR_CLEAR_RCVR; 1049 - iowrite8(fcr, priv->membase + UART_FCR); 1050 1030 1051 1031 if (lsr & PCH_UART_LSR_ERR) 1052 1032 error_msg[i++] = "Error data in FIFO\n"; ··· 1575 1565 1576 1566 local_irq_save(flags); 1577 1567 if (priv->port.sysrq) { 1578 - spin_lock(&priv->lock); 1568 + /* call to uart_handle_sysrq_char already took the priv lock */ 1569 + priv_locked = 0; 1579 1570 /* serial8250_handle_port() already took the port lock */ 1580 1571 port_locked = 0; 1581 1572 } else if (oops_in_progress) {