Commit ef017328 authored by Russell King's avatar Russell King

[SERIAL] Clean up handling of LSR in receive function.

It's pointless accessing the LSR value via a pointer all the time -
it prevents the compiler optimising it.  Also, ensure that we
recognise a break sent during a kernel printk correctly.
parent 1a060592
...@@ -958,7 +958,7 @@ static _INLINE_ void ...@@ -958,7 +958,7 @@ static _INLINE_ void
receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
{ {
struct tty_struct *tty = up->port.info->tty; struct tty_struct *tty = up->port.info->tty;
unsigned char ch; unsigned char ch, lsr = *status;
int max_count = 256; int max_count = 256;
do { do {
...@@ -972,13 +972,23 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) ...@@ -972,13 +972,23 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
*tty->flip.flag_buf_ptr = TTY_NORMAL; *tty->flip.flag_buf_ptr = TTY_NORMAL;
up->port.icount.rx++; up->port.icount.rx++;
if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | #ifdef CONFIG_SERIAL_8250_CONSOLE
UART_LSR_FE | UART_LSR_OE))) { /*
* Recover the break flag from console xmit
*/
if (up->port.line == up->port.cons->index) {
lsr |= up->lsr_break_flag;
up->lsr_break_flag = 0;
}
#endif
if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE |
UART_LSR_FE | UART_LSR_OE))) {
/* /*
* For statistics only * For statistics only
*/ */
if (*status & UART_LSR_BI) { if (lsr & UART_LSR_BI) {
*status &= ~(UART_LSR_FE | UART_LSR_PE); lsr &= ~(UART_LSR_FE | UART_LSR_PE);
up->port.icount.brk++; up->port.icount.brk++;
/* /*
* We do the SysRQ and SAK checking * We do the SysRQ and SAK checking
...@@ -988,41 +998,34 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) ...@@ -988,41 +998,34 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
*/ */
if (uart_handle_break(&up->port)) if (uart_handle_break(&up->port))
goto ignore_char; goto ignore_char;
} else if (*status & UART_LSR_PE) } else if (lsr & UART_LSR_PE)
up->port.icount.parity++; up->port.icount.parity++;
else if (*status & UART_LSR_FE) else if (lsr & UART_LSR_FE)
up->port.icount.frame++; up->port.icount.frame++;
if (*status & UART_LSR_OE) if (lsr & UART_LSR_OE)
up->port.icount.overrun++; up->port.icount.overrun++;
/* /*
* Mask off conditions which should be ingored. * Mask off conditions which should be ingored.
*/ */
*status &= up->port.read_status_mask; lsr &= up->port.read_status_mask;
#ifdef CONFIG_SERIAL_8250_CONSOLE if (lsr & UART_LSR_BI) {
if (up->port.line == up->port.cons->index) {
/* Recover the break flag from console xmit */
*status |= up->lsr_break_flag;
up->lsr_break_flag = 0;
}
#endif
if (*status & UART_LSR_BI) {
DEBUG_INTR("handling break...."); DEBUG_INTR("handling break....");
*tty->flip.flag_buf_ptr = TTY_BREAK; *tty->flip.flag_buf_ptr = TTY_BREAK;
} else if (*status & UART_LSR_PE) } else if (lsr & UART_LSR_PE)
*tty->flip.flag_buf_ptr = TTY_PARITY; *tty->flip.flag_buf_ptr = TTY_PARITY;
else if (*status & UART_LSR_FE) else if (lsr & UART_LSR_FE)
*tty->flip.flag_buf_ptr = TTY_FRAME; *tty->flip.flag_buf_ptr = TTY_FRAME;
} }
if (uart_handle_sysrq_char(&up->port, ch, regs)) if (uart_handle_sysrq_char(&up->port, ch, regs))
goto ignore_char; goto ignore_char;
if ((*status & up->port.ignore_status_mask) == 0) { if ((lsr & up->port.ignore_status_mask) == 0) {
tty->flip.flag_buf_ptr++; tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++; tty->flip.char_buf_ptr++;
tty->flip.count++; tty->flip.count++;
} }
if ((*status & UART_LSR_OE) && if ((lsr & UART_LSR_OE) &&
tty->flip.count < TTY_FLIPBUF_SIZE) { tty->flip.count < TTY_FLIPBUF_SIZE) {
/* /*
* Overrun is special, since it's reported * Overrun is special, since it's reported
...@@ -1035,9 +1038,10 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) ...@@ -1035,9 +1038,10 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
tty->flip.count++; tty->flip.count++;
} }
ignore_char: ignore_char:
*status = serial_inp(up, UART_LSR); lsr = serial_inp(up, UART_LSR);
} while ((*status & UART_LSR_DR) && (max_count-- > 0)); } while ((lsr & UART_LSR_DR) && (max_count-- > 0));
tty_flip_buffer_push(tty); tty_flip_buffer_push(tty);
*status = lsr;
} }
static _INLINE_ void transmit_chars(struct uart_8250_port *up) static _INLINE_ void transmit_chars(struct uart_8250_port *up)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment