Commit 271b0636 authored by Russell King's avatar Russell King

[SERIAL] serial driver fixes

Patch from Alan Cox, expanded to cover ARM drivers by Russell King.

- define SUPPORT_SYSRQ early
- ensure consistent include ordering
- use proper helper functions for flip buffer handling
- remove deadlock on overrun
parent 28eb41dd
......@@ -13,12 +13,14 @@
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/device.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/hardware/dec21285.h>
#include <asm/hardware.h>
......@@ -90,22 +92,21 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r
{
struct uart_port *port = dev_id;
struct tty_struct *tty = port->info->tty;
unsigned int status, ch, rxs, max_count = 256;
unsigned int status, ch, flag, rxs, max_count = 256;
status = *CSR_UARTFLG;
while (!(status & 0x10) && max_count--) {
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty->flip.work.func((void *)tty);
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
printk(KERN_WARNING "TTY_DONT_FLIP set\n");
goto out;
}
if (tty->low_latency)
tty_flip_buffer_push(tty);
/*
* If this failed then we will throw away the
* bytes but must do so to clear interrupts
*/
}
ch = *CSR_UARTDR;
*tty->flip.char_buf_ptr = ch;
*tty->flip.flag_buf_ptr = TTY_NORMAL;
flag = TTY_NORMAL;
port->icount.rx++;
rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ;
......@@ -120,15 +121,13 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r
rxs &= port->read_status_mask;
if (rxs & RXSTAT_PARITY)
*tty->flip.flag_buf_ptr = TTY_PARITY;
flag = TTY_PARITY;
else if (rxs & RXSTAT_FRAME)
*tty->flip.flag_buf_ptr = TTY_FRAME;
flag = TTY_FRAME;
}
if ((rxs & port->ignore_status_mask) == 0) {
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
tty->flip.count++;
tty_insert_flip_char(tty, ch, flag);
}
if ((rxs & RXSTAT_OVERRUN) &&
tty->flip.count < TTY_FLIPBUF_SIZE) {
......@@ -137,9 +136,7 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r
* immediately, and doesn't affect the current
* character.
*/
*tty->flip.char_buf_ptr++ = 0;
*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
tty->flip.count++;
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
status = *CSR_UARTFLG;
}
......
......@@ -20,28 +20,29 @@
* membase is an 'ioremapped' cookie.
*/
#include <linux/config.h>
#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_reg.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
#include <linux/circ_buf.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/irq.h>
#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial_core.h>
#include "8250.h"
/*
......@@ -979,16 +980,19 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
struct tty_struct *tty = up->port.info->tty;
unsigned char ch, lsr = *status;
int max_count = 256;
char flag;
do {
/* The following is not allowed by the tty layer and
unsafe. It should be fixed ASAP */
if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
tty->flip.work.func((void *)tty);
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
return; // if TTY_DONT_FLIP is set
if(tty->low_latency)
tty_flip_buffer_push(tty);
/* If this failed then we will throw away the
bytes but must do so to clear interrupts */
}
ch = serial_inp(up, UART_RX);
*tty->flip.char_buf_ptr = ch;
*tty->flip.flag_buf_ptr = TTY_NORMAL;
flag = TTY_NORMAL;
up->port.icount.rx++;
#ifdef CONFIG_SERIAL_8250_CONSOLE
......@@ -1031,18 +1035,16 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
if (lsr & UART_LSR_BI) {
DEBUG_INTR("handling break....");
*tty->flip.flag_buf_ptr = TTY_BREAK;
flag = TTY_BREAK;
} else if (lsr & UART_LSR_PE)
*tty->flip.flag_buf_ptr = TTY_PARITY;
flag = TTY_PARITY;
else if (lsr & UART_LSR_FE)
*tty->flip.flag_buf_ptr = TTY_FRAME;
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
goto ignore_char;
if ((lsr & up->port.ignore_status_mask) == 0) {
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
tty->flip.count++;
tty_insert_flip_char(tty, ch, flag);
}
if ((lsr & UART_LSR_OE) &&
tty->flip.count < TTY_FLIPBUF_SIZE) {
......@@ -1051,10 +1053,7 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
* immediately, and doesn't affect the current
* character.
*/
*tty->flip.flag_buf_ptr = TTY_OVERRUN;
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
tty->flip.count++;
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char:
lsr = serial_inp(up, UART_LSR);
......
......@@ -32,25 +32,25 @@
* and hooked into this driver.
*/
#include <linux/config.h>
#if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware/amba.h>
#if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial_core.h>
#include <asm/hardware/amba_serial.h>
#define UART_NR 2
......@@ -149,22 +149,22 @@ pl010_rx_chars(struct uart_port *port)
#endif
{
struct tty_struct *tty = port->info->tty;
unsigned int status, ch, rsr, max_count = 256;
unsigned int status, ch, flag, rsr, max_count = 256;
status = UART_GET_FR(port);
while (UART_RX_DATA(status) && max_count--) {
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty->flip.work.func((void *)tty);
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
printk(KERN_WARNING "TTY_DONT_FLIP set\n");
return;
}
if (tty->low_latency)
tty_flip_buffer_push(tty);
/*
* If this failed then we will throw away the
* bytes but must do so to clear interrupts.
*/
}
ch = UART_GET_CHAR(port);
flag = TTY_NORMAL;
*tty->flip.char_buf_ptr = ch;
*tty->flip.flag_buf_ptr = TTY_NORMAL;
port->icount.rx++;
/*
......@@ -188,20 +188,18 @@ pl010_rx_chars(struct uart_port *port)
rsr &= port->read_status_mask;
if (rsr & UART01x_RSR_BE)
*tty->flip.flag_buf_ptr = TTY_BREAK;
flag = TTY_BREAK;
else if (rsr & UART01x_RSR_PE)
*tty->flip.flag_buf_ptr = TTY_PARITY;
flag = TTY_PARITY;
else if (rsr & UART01x_RSR_FE)
*tty->flip.flag_buf_ptr = TTY_FRAME;
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(port, ch, regs))
goto ignore_char;
if ((rsr & port->ignore_status_mask) == 0) {
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
tty->flip.count++;
tty_insert_flip_char(tty, ch, flag);
}
if ((rsr & UART01x_RSR_OE) &&
tty->flip.count < TTY_FLIPBUF_SIZE) {
......@@ -210,9 +208,7 @@ pl010_rx_chars(struct uart_port *port)
* immediately, and doesn't affect the current
* character
*/
*tty->flip.char_buf_ptr++ = 0;
*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
tty->flip.count++;
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char:
status = UART_GET_FR(port);
......
......@@ -32,26 +32,26 @@
* and hooked into this driver.
*/
#include <linux/config.h>
#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/clock.h>
#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial_core.h>
#include <asm/hardware/amba_serial.h>
#define UART_NR 14
......@@ -115,22 +115,21 @@ pl011_rx_chars(struct uart_amba_port *uap)
#endif
{
struct tty_struct *tty = uap->port.info->tty;
unsigned int status, ch, rsr, max_count = 256;
unsigned int status, ch, flag, rsr, max_count = 256;
status = readw(uap->port.membase + UART01x_FR);
while ((status & UART01x_FR_RXFE) == 0 && max_count--) {
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty->flip.work.func((void *)tty);
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
printk(KERN_WARNING "TTY_DONT_FLIP set\n");
return;
}
if (tty->low_latency)
tty_flip_buffer_push(tty);
/*
* If this failed then we will throw away the
* bytes but must do so to clear interrupts
*/
}
ch = readw(uap->port.membase + UART01x_DR);
*tty->flip.char_buf_ptr = ch;
*tty->flip.flag_buf_ptr = TTY_NORMAL;
flag = TTY_NORMAL;
uap->port.icount.rx++;
/*
......@@ -154,20 +153,18 @@ pl011_rx_chars(struct uart_amba_port *uap)
rsr &= uap->port.read_status_mask;
if (rsr & UART01x_RSR_BE)
*tty->flip.flag_buf_ptr = TTY_BREAK;
flag = TTY_BREAK;
else if (rsr & UART01x_RSR_PE)
*tty->flip.flag_buf_ptr = TTY_PARITY;
flag = TTY_PARITY;
else if (rsr & UART01x_RSR_FE)
*tty->flip.flag_buf_ptr = TTY_FRAME;
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&uap->port, ch, regs))
goto ignore_char;
if ((rsr & uap->port.ignore_status_mask) == 0) {
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
tty->flip.count++;
tty_insert_flip_char(tty, ch, flag);
}
if ((rsr & UART01x_RSR_OE) &&
tty->flip.count < TTY_FLIPBUF_SIZE) {
......@@ -176,9 +173,7 @@ pl011_rx_chars(struct uart_amba_port *uap)
* immediately, and doesn't affect the current
* character
*/
*tty->flip.char_buf_ptr++ = 0;
*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
tty->flip.count++;
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char:
status = readw(uap->port.membase + UART01x_FR);
......
......@@ -26,26 +26,26 @@
*
*/
#include <linux/config.h>
#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial_core.h>
#include <asm/hardware/clps7111.h>
#define UART_NR 2
......@@ -123,9 +123,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re
goto ignore_char;
error_return:
*tty->flip.flag_buf_ptr++ = flg;
*tty->flip.char_buf_ptr++ = ch;
tty->flip.count++;
tty_insert_flip_char(tty, ch, flg);
ignore_char:
status = clps_readl(SYSFLG(port));
}
......@@ -158,11 +156,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re
* CHECK: does overrun affect the current character?
* ASSUMPTION: it does not.
*/
*tty->flip.flag_buf_ptr++ = flg;
*tty->flip.char_buf_ptr++ = ch;
tty->flip.count++;
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
goto ignore_char;
tty_insert_flip_char(tty, ch, flg);
ch = 0;
flg = TTY_OVERRUN;
}
......
......@@ -28,12 +28,13 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/serial.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <asm/bootinfo.h>
#include <asm/dec/interrupts.h>
......@@ -186,7 +187,7 @@ static inline void dz_receive_chars(struct dz_port *dport)
struct uart_icount *icount;
int ignore = 0;
unsigned short status, tmp;
unsigned char ch;
unsigned char ch, flag;
/* this code is going to be a problem...
the call to tty_flip_buffer is going to need
......@@ -201,6 +202,7 @@ static inline void dz_receive_chars(struct dz_port *dport)
ch = UCHAR(status); /* grab the char */
flag = TTY_NORMAL;
#if 0
if (info->is_console) {
......@@ -217,8 +219,6 @@ static inline void dz_receive_chars(struct dz_port *dport)
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
break;
*tty->flip.char_buf_ptr = ch;
*tty->flip.flag_buf_ptr = 0;
icount->rx++;
/* keep track of the statistics */
......@@ -243,12 +243,12 @@ static inline void dz_receive_chars(struct dz_port *dport)
tmp = status & dport->port.read_status_mask;
if (tmp & DZ_PERR) {
*tty->flip.flag_buf_ptr = TTY_PARITY;
flag = TTY_PARITY;
#ifdef DEBUG_DZ
debug_console("PERR\n", 5);
#endif
} else if (tmp & DZ_FERR) {
*tty->flip.flag_buf_ptr = TTY_FRAME;
flag = TTY_FRAME;
#ifdef DEBUG_DZ
debug_console("FERR\n", 5);
#endif
......@@ -257,17 +257,12 @@ static inline void dz_receive_chars(struct dz_port *dport)
#ifdef DEBUG_DZ
debug_console("OERR\n", 5);
#endif
if (tty->flip.count < TTY_FLIPBUF_SIZE) {
tty->flip.count++;
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
*tty->flip.flag_buf_ptr = TTY_OVERRUN;
}
tty_insert_flip_char(tty, ch, flag);
ch = 0;
flag = TTY_OVERRUN;
}
}
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
tty->flip.count++;
tty_insert_flip_char(tty, ch, flag);
ignore_char:
} while (status & DZ_DVAL);
......
......@@ -24,14 +24,21 @@
*
*/
#include <linux/config.h>
#if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <asm/io.h>
#include <asm/irq.h>
......@@ -39,12 +46,6 @@
#include <asm/arch/serial.h>
#include <asm/mach-types.h>
#if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial_core.h>
/* We've been assigned a range on the "Low-density serial ports" major */
#define SERIAL_IMX_MAJOR 204
#define MINOR_START 41
......@@ -237,9 +238,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id, struct pt_regs *regs)
goto handle_error;
error_return:
*tty->flip.flag_buf_ptr++ = flg;
*tty->flip.char_buf_ptr++ = (unsigned char)rx;
tty->flip.count++;
tty_insert_flip_char(tty, rx, flg);
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
goto out;
......
......@@ -25,8 +25,12 @@
*/
#include <linux/config.h>
#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
......@@ -36,18 +40,15 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/pxa-regs.h>
#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial_core.h>
struct uart_pxa_port {
struct uart_port port;
......@@ -102,25 +103,20 @@ static inline void
receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs)
{
struct tty_struct *tty = up->port.info->tty;
unsigned char ch;
unsigned int ch, flag;
int max_count = 256;
do {
if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
if (tty->low_latency)
tty_flip_buffer_push(tty);
/*
* FIXME: Deadlock can happen here if we're a
* low-latency port. We're holding the per-port
* spinlock, and we call flush_to_ldisc->
* n_tty_receive_buf->n_tty_receive_char->
* opost->uart_put_char.
* If this failed then we will throw away the
* bytes but must do so to clear interrupts
*/
tty->flip.work.func((void *)tty);
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
return; // if TTY_DONT_FLIP is set
}
ch = serial_in(up, UART_RX);
*tty->flip.char_buf_ptr = ch;
*tty->flip.flag_buf_ptr = TTY_NORMAL;
flag = TTY_NORMAL;
up->port.icount.rx++;
if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
......@@ -159,18 +155,16 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs)
}
#endif
if (*status & UART_LSR_BI) {
*tty->flip.flag_buf_ptr = TTY_BREAK;
flag = TTY_BREAK;
} else if (*status & UART_LSR_PE)
*tty->flip.flag_buf_ptr = TTY_PARITY;
flag = TTY_PARITY;
else if (*status & UART_LSR_FE)
*tty->flip.flag_buf_ptr = TTY_FRAME;
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
goto ignore_char;
if ((*status & up->port.ignore_status_mask) == 0) {
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
tty->flip.count++;
tty_insert_flip_char(tty, ch, flag);
}
if ((*status & UART_LSR_OE) &&
tty->flip.count < TTY_FLIPBUF_SIZE) {
......@@ -179,10 +173,7 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs)
* immediately, and doesn't affect the current
* character.
*/
*tty->flip.flag_buf_ptr = TTY_OVERRUN;
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
tty->flip.count++;
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char:
*status = serial_in(up, UART_LSR);
......
......@@ -12,11 +12,12 @@
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
......@@ -111,7 +112,7 @@ serial_s3c2410_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
{
struct uart_port *port = dev_id;
struct tty_struct *tty = port->info->tty;
unsigned int ufcon, ch, rxs, ufstat;
unsigned int ufcon, ch, flag, rxs, ufstat;
int max_count = 256;
while (max_count-- > 0) {
......@@ -122,17 +123,16 @@ serial_s3c2410_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
break;
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty->flip.work.func((void *)tty);
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
printk(KERN_WARNING "TTY_DONT_FLIP set\n");
goto out;
}
if (tty->low_latency)
tty_flip_buffer_push(tty);
/*
* If this failed then we will throw away the
* bytes but must do so to clear interrupts
*/
}
ch = rd_regb(port, S3C2410_URXH);
*tty->flip.char_buf_ptr = ch;
*tty->flip.flag_buf_ptr = TTY_NORMAL;
flag = TTY_NORMAL;
port->icount.rx++;
rxs = rd_regb(port, S3C2410_UERSTAT) | RXSTAT_DUMMY_READ;
......@@ -146,15 +146,13 @@ serial_s3c2410_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
rxs &= port->read_status_mask;
if (rxs & S3C2410_UERSTAT_PARITY)
*tty->flip.flag_buf_ptr = TTY_PARITY;
flag = TTY_PARITY;
else if (rxs & ( S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_OVERRUN))
*tty->flip.flag_buf_ptr = TTY_FRAME;
flag = TTY_FRAME;
}
if ((rxs & port->ignore_status_mask) == 0) {
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
tty->flip.count++;
tty_insert_flip_char(tty, ch, flag);
}
if ((rxs & S3C2410_UERSTAT_OVERRUN) &&
......@@ -164,9 +162,7 @@ serial_s3c2410_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
* immediately, and doesn't affect the current
* character.
*/
*tty->flip.char_buf_ptr++ = 0;
*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
tty->flip.count++;
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
}
tty_flip_buffer_push(tty);
......
......@@ -25,26 +25,27 @@
*
*/
#include <linux/config.h>
#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/mach/serial_sa1100.h>
#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial_core.h>
/* We've been assigned a range on the "Low-density serial ports" major */
#define SERIAL_SA1100_MAJOR 204
#define MINOR_START 5
......@@ -220,9 +221,7 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
goto ignore_char;
error_return:
*tty->flip.flag_buf_ptr++ = flg;
*tty->flip.char_buf_ptr++ = ch;
tty->flip.count++;
tty_insert_flip_char(tty, ch, flg);
ignore_char:
status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
UTSR0_TO_SM(UART_GET_UTSR0(sport));
......@@ -257,11 +256,7 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
* overrun does *not* affect the character
* we read from the FIFO
*/
*tty->flip.flag_buf_ptr++ = flg;
*tty->flip.char_buf_ptr++ = ch;
tty->flip.count++;
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
goto ignore_char;
tty_insert_flip_char(tty, ch, flg);
ch = 0;
flg = TTY_OVERRUN;
}
......
......@@ -28,23 +28,24 @@
*/
#include <linux/config.h>
#if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <asm/io.h>
#include <asm/irq.h>
#if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial_core.h>
#define DEV_MAJOR 204
#define DEV_MINOR 16
#define DEV_NR 3
......@@ -145,21 +146,20 @@ lh7a40xuart_rx_chars (struct uart_port* port)
{
struct tty_struct* tty = port->info->tty;
int cbRxMax = 256; /* (Gross) limit on receive */
unsigned int data; /* Received data and status */
unsigned int data, flag;/* Received data and status */
while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty->flip.work.func((void*)tty);
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
printk(KERN_WARNING "TTY_DONT_FLIP set\n");
return;
}
if (tty->low_latency)
tty_flip_buffer_push(tty);
/*
* If this failed then we will throw away the
* bytes but must do so to clear interrupts
*/
}
data = UR (port, UART_R_DATA);
*tty->flip.char_buf_ptr = (unsigned char) data;
*tty->flip.flag_buf_ptr = TTY_NORMAL;
flag = TTY_NORMAL;
++port->icount.rx;
if (data & RxError) { /* Quick check, short-circuit */
......@@ -180,20 +180,18 @@ lh7a40xuart_rx_chars (struct uart_port* port)
data &= port->read_status_mask | 0xff;
if (data & RxBreak)
*tty->flip.flag_buf_ptr = TTY_BREAK;
flag = TTY_BREAK;
else if (data & RxParityError)
*tty->flip.flag_buf_ptr = TTY_PARITY;
flag = TTY_PARITY;
else if (data & RxFramingError)
*tty->flip.flag_buf_ptr = TTY_FRAME;
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char (port, (unsigned char) data, regs))
continue;
if ((data & port->ignore_status_mask) == 0) {
++tty->flip.flag_buf_ptr;
++tty->flip.char_buf_ptr;
++tty->flip.count;
tty_insert_flip_char(tty, data, flag);
}
if ((data & RxOverrunError)
&& tty->flip.count < TTY_FLIPBUF_SIZE) {
......@@ -202,9 +200,7 @@ lh7a40xuart_rx_chars (struct uart_port* port)
* immediately, and doesn't affect the current
* character
*/
*tty->flip.char_buf_ptr++ = 0;
*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
++tty->flip.count;
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
}
tty_flip_buffer_push (tty);
......
......@@ -27,23 +27,25 @@
*
*/
#include <linux/config.h>
#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/sizes.h>
#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial_core.h>
#include <asm/arch/excalibur.h>
#define UART00_TYPE (volatile unsigned int*)
#include <asm/arch/uart00.h>
......@@ -132,9 +134,8 @@ uart00_rx_chars(struct uart_port *port, struct pt_regs *regs)
goto ignore_char;
error_return:
*tty->flip.flag_buf_ptr++ = flg;
*tty->flip.char_buf_ptr++ = ch;
tty->flip.count++;
tty_insert_flip_char(tty, ch, flg);
ignore_char:
status = UART_GET_RSR(port);
}
......@@ -174,11 +175,7 @@ uart00_rx_chars(struct uart_port *port, struct pt_regs *regs)
* CHECK: does overrun affect the current character?
* ASSUMPTION: it does not.
*/
*tty->flip.flag_buf_ptr++ = flg;
*tty->flip.char_buf_ptr++ = ch;
tty->flip.count++;
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
goto ignore_char;
tty_insert_flip_char(tty, ch, flg);
ch = 0;
flg = TTY_OVERRUN;
}
......
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