Commit 05ab3014 authored by Russell King's avatar Russell King

[PATCH] Serial: Add uart_insert_char()

Add uart_insert_char(), which handles inserting characters into the
flip buffer.  This helper function handles the correct semantics
for handling overrun in addition to inserting normal characters.
Signed-off-by: default avatarRussell King <rmk@arm.linux.org.uk>
parent 88d7bd8c
...@@ -126,18 +126,8 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r ...@@ -126,18 +126,8 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r
flag = TTY_FRAME; flag = TTY_FRAME;
} }
if ((rxs & port->ignore_status_mask) == 0) { uart_insert_char(port, rxs, RXSTAT_OVERRUN, ch, flag);
tty_insert_flip_char(tty, ch, flag);
}
if ((rxs & RXSTAT_OVERRUN) &&
tty->flip.count < TTY_FLIPBUF_SIZE) {
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character.
*/
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
status = *CSR_UARTFLG; status = *CSR_UARTFLG;
} }
tty_flip_buffer_push(tty); tty_flip_buffer_push(tty);
......
...@@ -1122,18 +1122,9 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) ...@@ -1122,18 +1122,9 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
} }
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 ((lsr & up->port.ignore_status_mask) == 0) {
tty_insert_flip_char(tty, ch, flag); uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
}
if ((lsr & UART_LSR_OE) &&
tty->flip.count < TTY_FLIPBUF_SIZE) {
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character.
*/
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char: ignore_char:
lsr = serial_inp(up, UART_LSR); lsr = serial_inp(up, UART_LSR);
} while ((lsr & UART_LSR_DR) && (max_count-- > 0)); } while ((lsr & UART_LSR_DR) && (max_count-- > 0));
......
...@@ -198,18 +198,8 @@ pl010_rx_chars(struct uart_port *port) ...@@ -198,18 +198,8 @@ pl010_rx_chars(struct uart_port *port)
if (uart_handle_sysrq_char(port, ch, regs)) if (uart_handle_sysrq_char(port, ch, regs))
goto ignore_char; goto ignore_char;
if ((rsr & port->ignore_status_mask) == 0) { uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag);
tty_insert_flip_char(tty, ch, flag);
}
if ((rsr & UART01x_RSR_OE) &&
tty->flip.count < TTY_FLIPBUF_SIZE) {
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character
*/
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char: ignore_char:
status = UART_GET_FR(port); status = UART_GET_FR(port);
} }
......
...@@ -163,18 +163,8 @@ pl011_rx_chars(struct uart_amba_port *uap) ...@@ -163,18 +163,8 @@ pl011_rx_chars(struct uart_amba_port *uap)
if (uart_handle_sysrq_char(&uap->port, ch, regs)) if (uart_handle_sysrq_char(&uap->port, ch, regs))
goto ignore_char; goto ignore_char;
if ((rsr & uap->port.ignore_status_mask) == 0) { uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag);
tty_insert_flip_char(tty, ch, flag);
}
if ((rsr & UART01x_RSR_OE) &&
tty->flip.count < TTY_FLIPBUF_SIZE) {
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character
*/
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char: ignore_char:
status = readw(uap->port.membase + UART01x_FR); status = readw(uap->port.membase + UART01x_FR);
} }
......
...@@ -143,10 +143,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re ...@@ -143,10 +143,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re
* CHECK: does overrun affect the current character? * CHECK: does overrun affect the current character?
* ASSUMPTION: it does not. * ASSUMPTION: it does not.
*/ */
if ((ch & port->ignore_status_mask & ~RXSTAT_OVERRUN) == 0) uart_insert_char(port, ch, UARTDR_OVERR, ch, flg);
tty_insert_flip_char(tty, ch, flg);
if ((ch & ~port->ignore_status_mask & RXSTAT_OVERRUN) == 0)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
ignore_char: ignore_char:
status = clps_readl(SYSFLG(port)); status = clps_readl(SYSFLG(port));
......
...@@ -161,20 +161,12 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs) ...@@ -161,20 +161,12 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs)
else if (*status & UART_LSR_FE) else if (*status & UART_LSR_FE)
flag = TTY_FRAME; flag = 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) {
tty_insert_flip_char(tty, ch, flag); uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
}
if ((*status & UART_LSR_OE) &&
tty->flip.count < TTY_FLIPBUF_SIZE) {
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character.
*/
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char: ignore_char:
*status = serial_in(up, UART_LSR); *status = serial_in(up, UART_LSR);
} while ((*status & UART_LSR_DR) && (max_count-- > 0)); } while ((*status & UART_LSR_DR) && (max_count-- > 0));
......
...@@ -394,20 +394,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs) ...@@ -394,20 +394,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
if (uart_handle_sysrq_char(port, ch, regs)) if (uart_handle_sysrq_char(port, ch, regs))
goto ignore_char; goto ignore_char;
if ((uerstat & port->ignore_status_mask) == 0) { uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, flag);
tty_insert_flip_char(tty, ch, flag);
}
if ((uerstat & S3C2410_UERSTAT_OVERRUN) &&
tty->flip.count < TTY_FLIPBUF_SIZE) {
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character.
*/
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char: ignore_char:
continue; continue;
......
...@@ -237,10 +237,7 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) ...@@ -237,10 +237,7 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
if (uart_handle_sysrq_char(&sport->port, ch, regs)) if (uart_handle_sysrq_char(&sport->port, ch, regs))
goto ignore_char; goto ignore_char;
if ((status & port->ignore_status_mask & ~UTSR1_TO_SM(UTSR1_ROR)) == 0) uart_insert_char(&sport->port, status, UTSR1_TO_SM(UTSR1_ROR), ch, flg);
tty_insert_flip_char(tty, ch, flg);
if (status & ~port->ignore_status_mask & UTSR1_TO_SM(UTSR1_ROR))
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
ignore_char: ignore_char:
status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
......
...@@ -190,18 +190,7 @@ lh7a40xuart_rx_chars (struct uart_port* port) ...@@ -190,18 +190,7 @@ lh7a40xuart_rx_chars (struct uart_port* port)
if (uart_handle_sysrq_char (port, (unsigned char) data, regs)) if (uart_handle_sysrq_char (port, (unsigned char) data, regs))
continue; continue;
if ((data & port->ignore_status_mask) == 0) { uart_insert_char(port, data, RxOverrunError, data, flag);
tty_insert_flip_char(tty, data, flag);
}
if ((data & RxOverrunError)
&& tty->flip.count < TTY_FLIPBUF_SIZE) {
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character
*/
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
} }
tty_flip_buffer_push (tty); tty_flip_buffer_push (tty);
return; return;
......
...@@ -350,18 +350,9 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r ...@@ -350,18 +350,9 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
} }
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 ((disr & up->port.ignore_status_mask) == 0) {
tty_insert_flip_char(tty, ch, flag); uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag);
}
if ((disr & TXX9_SIDISR_UOER) &&
tty->flip.count < TTY_FLIPBUF_SIZE) {
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character.
*/
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char: ignore_char:
disr = sio_in(up, TXX9_SIDISR); disr = sio_in(up, TXX9_SIDISR);
} while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0)); } while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
......
...@@ -412,10 +412,8 @@ static inline void receive_chars(struct uart_port *port, uint8_t *status, ...@@ -412,10 +412,8 @@ static inline void receive_chars(struct uart_port *port, uint8_t *status,
if (uart_handle_sysrq_char(port, ch, regs)) if (uart_handle_sysrq_char(port, ch, regs))
goto ignore_char; goto ignore_char;
if ((lsr & port->ignore_status_mask) == 0)
tty_insert_flip_char(tty, ch, flag); uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
if ((lsr & UART_LSR_OE) && (tty->flip.count < TTY_FLIPBUF_SIZE))
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
ignore_char: ignore_char:
lsr = siu_read(port, UART_LSR); lsr = siu_read(port, UART_LSR);
......
...@@ -479,6 +479,25 @@ uart_handle_cts_change(struct uart_port *port, unsigned int status) ...@@ -479,6 +479,25 @@ uart_handle_cts_change(struct uart_port *port, unsigned int status)
} }
} }
#include <linux/tty_flip.h>
static inline void
uart_insert_char(struct uart_port *port, unsigned int status,
unsigned int overrun, unsigned int ch, unsigned int flag)
{
struct tty_struct *tty = port->info->tty;
if ((status & port->ignore_status_mask & ~overrun) == 0)
tty_insert_flip_char(tty, ch, flag);
/*
* Overrun is special. Since it's reported immediately,
* it doesn't affect the current character.
*/
if (status & ~port->ignore_status_mask & overrun)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
/* /*
* UART_ENABLE_MS - determine if port should enable modem status irqs * UART_ENABLE_MS - determine if port should enable modem status irqs
*/ */
......
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