aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorLiang Li <liang.li@windriver.com>2013-01-19 04:52:11 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-01-20 19:03:21 -0500
commit1f9db0921f212ad8fdf4bacfdf23590e64272f90 (patch)
tree4d506202c55e2194a1559237c3e02ea5417a4ab0 /drivers/tty
parent384e301e3519599b000c1a2ecd938b533fc15d85 (diff)
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>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/pch_uart.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 10e1a95b0c92..1ddfc66b1084 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -14,18 +14,21 @@
14 *along with this program; if not, write to the Free Software 14 *along with this program; if not, write to the Free Software
15 *Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 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#include <linux/kernel.h> 20#include <linux/kernel.h>
18#include <linux/serial_reg.h> 21#include <linux/serial_reg.h>
19#include <linux/slab.h> 22#include <linux/slab.h>
20#include <linux/module.h> 23#include <linux/module.h>
21#include <linux/pci.h> 24#include <linux/pci.h>
25#include <linux/console.h>
22#include <linux/serial_core.h> 26#include <linux/serial_core.h>
23#include <linux/tty.h> 27#include <linux/tty.h>
24#include <linux/tty_flip.h> 28#include <linux/tty_flip.h>
25#include <linux/interrupt.h> 29#include <linux/interrupt.h>
26#include <linux/io.h> 30#include <linux/io.h>
27#include <linux/dmi.h> 31#include <linux/dmi.h>
28#include <linux/console.h>
29#include <linux/nmi.h> 32#include <linux/nmi.h>
30#include <linux/delay.h> 33#include <linux/delay.h>
31 34
@@ -553,12 +556,24 @@ static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf,
553{ 556{
554 int i; 557 int i;
555 u8 rbr, lsr; 558 u8 rbr, lsr;
559 struct uart_port *port = &priv->port;
556 560
557 lsr = ioread8(priv->membase + UART_LSR); 561 lsr = ioread8(priv->membase + UART_LSR);
558 for (i = 0, lsr = ioread8(priv->membase + UART_LSR); 562 for (i = 0, lsr = ioread8(priv->membase + UART_LSR);
559 i < rx_size && lsr & UART_LSR_DR; 563 i < rx_size && lsr & (UART_LSR_DR | UART_LSR_BI);
560 lsr = ioread8(priv->membase + UART_LSR)) { 564 lsr = ioread8(priv->membase + UART_LSR)) {
561 rbr = ioread8(priv->membase + PCH_UART_RBR); 565 rbr = ioread8(priv->membase + PCH_UART_RBR);
566
567 if (lsr & UART_LSR_BI) {
568 port->icount.brk++;
569 if (uart_handle_break(port))
570 continue;
571 }
572 if (port->sysrq) {
573 if (uart_handle_sysrq_char(port, rbr))
574 continue;
575 }
576
562 buf[i++] = rbr; 577 buf[i++] = rbr;
563 } 578 }
564 return i; 579 return i;
@@ -1023,16 +1038,11 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
1023 1038
1024static void pch_uart_err_ir(struct eg20t_port *priv, unsigned int lsr) 1039static void pch_uart_err_ir(struct eg20t_port *priv, unsigned int lsr)
1025{ 1040{
1026 u8 fcr = ioread8(priv->membase + UART_FCR);
1027 struct uart_port *port = &priv->port; 1041 struct uart_port *port = &priv->port;
1028 struct tty_struct *tty = tty_port_tty_get(&port->state->port); 1042 struct tty_struct *tty = tty_port_tty_get(&port->state->port);
1029 char *error_msg[5] = {}; 1043 char *error_msg[5] = {};
1030 int i = 0; 1044 int i = 0;
1031 1045
1032 /* Reset FIFO */
1033 fcr |= UART_FCR_CLEAR_RCVR;
1034 iowrite8(fcr, priv->membase + UART_FCR);
1035
1036 if (lsr & PCH_UART_LSR_ERR) 1046 if (lsr & PCH_UART_LSR_ERR)
1037 error_msg[i++] = "Error data in FIFO\n"; 1047 error_msg[i++] = "Error data in FIFO\n";
1038 1048
@@ -1565,7 +1575,8 @@ pch_console_write(struct console *co, const char *s, unsigned int count)
1565 1575
1566 local_irq_save(flags); 1576 local_irq_save(flags);
1567 if (priv->port.sysrq) { 1577 if (priv->port.sysrq) {
1568 spin_lock(&priv->lock); 1578 /* call to uart_handle_sysrq_char already took the priv lock */
1579 priv_locked = 0;
1569 /* serial8250_handle_port() already took the port lock */ 1580 /* serial8250_handle_port() already took the port lock */
1570 port_locked = 0; 1581 port_locked = 0;
1571 } else if (oops_in_progress) { 1582 } else if (oops_in_progress) {