diff options
Diffstat (limited to 'drivers/serial')
33 files changed, 210 insertions, 508 deletions
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index b5cf39468d1..221999bcf8f 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -94,15 +94,6 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r status = *CSR_UARTFLG; while (!(status & 0x10) && max_count--) { - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - 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; flag = TTY_NORMAL; port->icount.rx++; diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 67e9afa000c..4dd5c3f9816 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -294,7 +294,7 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg { struct tty_struct *tty = info->tty; m68328_uart *uart = &uart_addr[info->line]; - unsigned char ch; + unsigned char ch, flag; /* * This do { } while() loop will get ALL chars out of Rx FIFO @@ -332,26 +332,24 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg /* * Make sure that we do not overflow the buffer */ - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + if (tty_request_buffer_room(tty, 1) == 0) { schedule_work(&tty->flip.work); return; } + flag = TTY_NORMAL; + if(rx & URX_PARITY_ERROR) { - *tty->flip.flag_buf_ptr++ = TTY_PARITY; + flag = TTY_PARITY; status_handle(info, rx); } else if(rx & URX_OVRUN) { - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; + flag = TTY_OVERRUN; status_handle(info, rx); } else if(rx & URX_FRAME_ERROR) { - *tty->flip.flag_buf_ptr++ = TTY_FRAME; + flag = TTY_FRAME; status_handle(info, rx); - } else { - *tty->flip.flag_buf_ptr++ = 0; /* XXX */ } - *tty->flip.char_buf_ptr++ = ch; - tty->flip.count++; - + tty_insert_flip_char(tty, ch, flag); #ifndef CONFIG_XCOPILOT_BUGS } while((rx = uart->urx.w) & URX_DATA_READY); #endif diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 170c9d2a749..60f5a5dc17f 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -394,7 +394,7 @@ static void rs_360_start(struct tty_struct *tty) static _INLINE_ void receive_chars(ser_info_t *info) { struct tty_struct *tty = info->tty; - unsigned char ch, *cp; + unsigned char ch, flag, *cp; /*int ignored = 0;*/ int i; ushort status; @@ -438,24 +438,15 @@ static _INLINE_ void receive_chars(ser_info_t *info) cp = (char *)bdp->buf; status = bdp->status; - /* Check to see if there is room in the tty buffer for - * the characters in our BD buffer. If not, we exit - * now, leaving the BD with the characters. We'll pick - * them up again on the next receive interrupt (which could - * be a timeout). - */ - if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) - break; - while (i-- > 0) { ch = *cp++; - *tty->flip.char_buf_ptr = ch; icount->rx++; #ifdef SERIAL_DEBUG_INTR printk("DR%02x:%02x...", ch, status); #endif - *tty->flip.flag_buf_ptr = 0; + flag = TTY_NORMAL; + if (status & (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV)) { /* @@ -490,30 +481,18 @@ static _INLINE_ void receive_chars(ser_info_t *info) if (info->flags & ASYNC_SAK) do_SAK(tty); } else if (status & BD_SC_PR) - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; else if (status & BD_SC_FR) - *tty->flip.flag_buf_ptr = TTY_FRAME; - if (status & BD_SC_OV) { - /* - * Overrun is special, since it's - * reported immediately, and doesn't - * affect the current character - */ - 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; - } - } + flag = TTY_FRAME; } - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - break; - - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + tty_insert_flip_char(tty, ch, flag); + if (status & BD_SC_OV) + /* + * Overrun is special, since it's + * reported immediately, and doesn't + * affect the current character + */ + tty_insert_flip_char(tty, 0, TTY_OVERRUN); } /* This BD is ready to be used again. Clear status. @@ -541,12 +520,7 @@ static _INLINE_ void receive_break(ser_info_t *info) /* Check to see if there is room in the tty buffer for * the break. If not, we exit now, losing the break. FIXME */ - if ((tty->flip.count + 1) >= TTY_FLIPBUF_SIZE) - return; - *(tty->flip.flag_buf_ptr++) = TTY_BREAK; - *(tty->flip.char_buf_ptr++) = 0; - tty->flip.count++; - + tty_insert_flip_char(tty, 0, TTY_BREAK); schedule_work(&tty->flip.work); } diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index e8454611cb6..fb610c3634a 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -41,6 +41,7 @@ #include <linux/serial.h> #include <linux/serial_8250.h> #include <linux/nmi.h> +#include <linux/mutex.h> #include <asm/io.h> #include <asm/irq.h> @@ -1142,19 +1143,6 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) 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)) { - if (tty->low_latency) { - spin_unlock(&up->port.lock); - tty_flip_buffer_push(tty); - spin_lock(&up->port.lock); - } - /* - * If this failed then we will throw away the - * bytes but must do so to clear interrupts - */ - } ch = serial_inp(up, UART_RX); flag = TTY_NORMAL; up->port.icount.rx++; @@ -2480,7 +2468,7 @@ static struct platform_device *serial8250_isa_devs; * 16x50 serial ports to be configured at run-time, to support PCMCIA * modems and PCI multiport cards. */ -static DECLARE_MUTEX(serial_sem); +static DEFINE_MUTEX(serial_mutex); static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port) { @@ -2535,7 +2523,7 @@ int serial8250_register_port(struct uart_port *port) if (port->uartclk == 0) return -EINVAL; - down(&serial_sem); + mutex_lock(&serial_mutex); uart = serial8250_find_match_or_unused(port); if (uart) { @@ -2557,7 +2545,7 @@ int serial8250_register_port(struct uart_port *port) if (ret == 0) ret = uart->port.line; } - up(&serial_sem); + mutex_unlock(&serial_mutex); return ret; } @@ -2574,7 +2562,7 @@ void serial8250_unregister_port(int line) { struct uart_8250_port *uart = &serial8250_ports[line]; - down(&serial_sem); + mutex_lock(&serial_mutex); uart_remove_one_port(&serial8250_reg, &uart->port); if (serial8250_isa_devs) { uart->port.flags &= ~UPF_BOOT_AUTOCONF; @@ -2584,7 +2572,7 @@ void serial8250_unregister_port(int line) } else { uart->port.dev = NULL; } - up(&serial_sem); + mutex_unlock(&serial_mutex); } EXPORT_SYMBOL(serial8250_unregister_port); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index a256a020b15..843717275d4 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -894,7 +894,7 @@ config SERIAL_VR41XX_CONSOLE config SERIAL_JSM tristate "Digi International NEO PCI Support" - depends on PCI + depends on PCI && BROKEN select SERIAL_CORE help This is a driver for Digi International's Neo series diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 48f6e872314..3490022e9fd 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -154,15 +154,6 @@ pl010_rx_chars(struct uart_port *port) status = UART_GET_FR(port); while (UART_RX_DATA(status) && max_count--) { - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - 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; diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 12967055616..034a029e356 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -120,15 +120,6 @@ pl011_rx_chars(struct uart_amba_port *uap) status = readw(uap->port.membase + UART01x_FR); while ((status & UART01x_FR_RXFE) == 0 && max_count--) { - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - 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) | UART_DUMMY_DR_RX; flag = TTY_NORMAL; uap->port.icount.rx++; diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c index a274ebf256a..ceb5d7f37bb 100644 --- a/drivers/serial/au1x00_uart.c +++ b/drivers/serial/au1x00_uart.c @@ -241,18 +241,12 @@ static _INLINE_ void receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) { struct tty_struct *tty = up->port.info->tty; - unsigned char ch; + unsigned char ch, flag; int max_count = 256; do { - 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 - } 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++; if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | @@ -292,30 +286,23 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) #endif if (*status & UART_LSR_BI) { DEBUG_INTR("handling break...."); - *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++; - } - if ((*status & UART_LSR_OE) && - tty->flip.count < TTY_FLIPBUF_SIZE) { + if ((*status & up->port.ignore_status_mask) == 0) + tty_insert_flip_char(tty, ch, flag); + if (*status & UART_LSR_OE) /* * Overrun is special, since it's reported * 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_inp(up, UART_LSR); diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index 87ef368384f..8ef999481f9 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -104,8 +104,6 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re while (!(status & SYSFLG_URXFE)) { ch = clps_readl(UARTDR(port)); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto ignore_char; port->icount.rx++; flg = TTY_NORMAL; diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 08c42c00018..be12623d854 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -442,6 +442,7 @@ static char *serial_version = "$Revision: 1.25 $"; #include <linux/init.h> #include <asm/uaccess.h> #include <linux/kernel.h> +#include <linux/mutex.h> #include <asm/io.h> #include <asm/irq.h> @@ -1315,11 +1316,7 @@ static const struct control_pins e100_modem_pins[NR_PORTS] = * memory if large numbers of serial ports are open. */ static unsigned char *tmp_buf; -#ifdef DECLARE_MUTEX -static DECLARE_MUTEX(tmp_buf_sem); -#else -static struct semaphore tmp_buf_sem = MUTEX; -#endif +static DEFINE_MUTEX(tmp_buf_mutex); /* Calculate the chartime depending on baudrate, numbor of bits etc. */ static void update_char_time(struct e100_serial * info) @@ -3661,7 +3658,7 @@ rs_raw_write(struct tty_struct * tty, int from_user, * design. */ if (from_user) { - down(&tmp_buf_sem); + mutex_lock(&tmp_buf_mutex); while (1) { int c1; c = CIRC_SPACE_TO_END(info->xmit.head, @@ -3692,7 +3689,7 @@ rs_raw_write(struct tty_struct * tty, int from_user, count -= c; ret += c; } - up(&tmp_buf_sem); + mutex_unlock(&tmp_buf_mutex); } else { cli(); while (count) { diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index 4d8516d1bb7..a64ba26a94e 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -216,8 +216,6 @@ static inline void dz_receive_chars(struct dz_port *dport) if (!tty) break; - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - break; icount->rx++; diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index eb31125c6a3..144a7a352b2 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c @@ -729,19 +729,20 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port) unsigned short int status; struct uart_icount *icount; unsigned long offset; + unsigned char flag; trace(icom_port, "RCV_COMPLETE", 0); rcv_buff = icom_port->next_rcv; status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags); while (status & SA_FL_RCV_DONE) { + int first = -1; trace(icom_port, "FID_STATUS", status); count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength); + count = tty_buffer_request_room(tty, count); trace(icom_port, "RCV_COUNT", count); - if (count > (TTY_FLIPBUF_SIZE - tty->flip.count)) - count = TTY_FLIPBUF_SIZE - tty->flip.count; trace(icom_port, "REAL_COUNT", count); @@ -749,15 +750,10 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port) cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) - icom_port->recv_buf_pci; - memcpy(tty->flip.char_buf_ptr,(unsigned char *) - ((unsigned long)icom_port->recv_buf + offset), count); - + /* Block copy all but the last byte as this may have status */ if (count > 0) { - tty->flip.count += count - 1; - tty->flip.char_buf_ptr += count - 1; - - memset(tty->flip.flag_buf_ptr, 0, count); - tty->flip.flag_buf_ptr += count - 1; + first = icom_port->recv_buf[offset]; + tty_insert_flip_string(tty, icom_port->recv_buf + offset, count - 1); } icount = &icom_port->uart_port.icount; @@ -765,12 +761,14 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port) /* Break detect logic */ if ((status & SA_FLAGS_FRAME_ERROR) - && (tty->flip.char_buf_ptr[0] == 0x00)) { + && first == 0) { status &= ~SA_FLAGS_FRAME_ERROR; status |= SA_FLAGS_BREAK_DET; trace(icom_port, "BREAK_DET", 0); } + flag = TTY_NORMAL; + if (status & (SA_FLAGS_BREAK_DET | SA_FLAGS_PARITY_ERROR | SA_FLAGS_FRAME_ERROR | SA_FLAGS_OVERRUN)) { @@ -797,33 +795,26 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port) status &= icom_port->read_status_mask; if (status & SA_FLAGS_BREAK_DET) { - *tty->flip.flag_buf_ptr = TTY_BREAK; + flag = TTY_BREAK; } else if (status & SA_FLAGS_PARITY_ERROR) { trace(icom_port, "PARITY_ERROR", 0); - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; } else if (status & SA_FLAGS_FRAME_ERROR) - *tty->flip.flag_buf_ptr = TTY_FRAME; - - if (status & SA_FLAGS_OVERRUN) { - /* - * Overrun is special, since it's - * reported immediately, and doesn't - * affect the current character - */ - 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; - } - } + flag = TTY_FRAME; + } - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - ignore_char: - icom_port->statStg->rcv[rcv_buff].flags = 0; + tty_insert_flip_char(tty, *(icom_port->recv_buf + offset + count - 1), flag); + + if (status & SA_FLAGS_OVERRUN) + /* + * 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: + icom_port->statStg->rcv[rcv_buff].flags = 0; icom_port->statStg->rcv[rcv_buff].leLength = 0; icom_port->statStg->rcv[rcv_buff].WorkingLength = (unsigned short int) cpu_to_le16(RCV_BUFF_SZ); diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 83c4c121658..5c098be9346 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -256,9 +256,6 @@ static irqreturn_t imx_rxint(int irq, void *dev_id, struct pt_regs *regs) error_return: tty_insert_flip_char(tty, rx, flg); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto out; - ignore_char: rx = URXD0((u32)sport->port.membase); } while(rx & URXD_CHARRDY); diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 771676abee6..1d85533d46d 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -2327,19 +2327,13 @@ static void receive_chars(struct uart_port *the_port) spin_lock_irqsave(&the_port->lock, pflags); tty = info->tty; - if (request_count > TTY_FLIPBUF_SIZE - tty->flip.count) - request_count = TTY_FLIPBUF_SIZE - tty->flip.count; + request_count = tty_buffer_request_room(tty, IOC4_MAX_CHARS - 2); if (request_count > 0) { icount = &the_port->icount; read_count = do_read(the_port, ch, request_count); if (read_count > 0) { - flip = 1; - memcpy(tty->flip.char_buf_ptr, ch, read_count); - memset(tty->flip.flag_buf_ptr, TTY_NORMAL, read_count); - tty->flip.char_buf_ptr += read_count; - tty->flip.flag_buf_ptr += read_count; - tty->flip.count += read_count; + tty_insert_flip_string(tty, ch, read_count); icount->rx += read_count; } } diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index ef132349f31..66f117d1506 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -259,13 +259,7 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */ while (1) { - unsigned char ch, r1; - - if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { - tty->flip.work.func((void *)tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - return; /* XXX Ignores SysRq when we need it most. Fix. */ - } + unsigned char ch, r1, flag; r1 = read_zsreg(channel, R1); if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) { @@ -303,8 +297,7 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, } /* A real serial line, record the character and status. */ - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; + flag = TTY_NORMAL; up->port.icount.rx++; if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) { if (r1 & BRK_ABRT) { @@ -321,28 +314,21 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, up->port.icount.overrun++; r1 &= up->port.read_status_mask; if (r1 & BRK_ABRT) - *tty->flip.flag_buf_ptr = TTY_BREAK; + flag = TTY_BREAK; else if (r1 & PAR_ERR) - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; else if (r1 & CRC_ERR) - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_FRAME; } if (uart_handle_sysrq_char(&up->port, ch, regs)) goto next_char; if (up->port.ignore_status_mask == 0xff || - (r1 & up->port.ignore_status_mask) == 0) { - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - } - if ((r1 & Rx_OVR) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - *tty->flip.flag_buf_ptr = TTY_OVERRUN; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - } + (r1 & up->port.ignore_status_mask) == 0) + tty_insert_flip_char(tty, ch, flag); + + if (r1 & Rx_OVR) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); next_char: ch = readb(&channel->control); ZSDELAY(); diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index b0ecc7537ce..b48066a64a7 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -331,17 +331,12 @@ static _INLINE_ void receive_chars(struct uart_sio_port *up, int *status, { struct tty_struct *tty = up->port.info->tty; unsigned char ch; + unsigned char flag; int max_count = 256; do { - 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 - } ch = sio_in(up, SIORXB); - *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 | @@ -380,30 +375,24 @@ static _INLINE_ void receive_chars(struct uart_sio_port *up, int *status, if (*status & UART_LSR_BI) { DEBUG_INTR("handling break...."); - *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++; - } - if ((*status & UART_LSR_OE) && - tty->flip.count < TTY_FLIPBUF_SIZE) { + if ((*status & up->port.ignore_status_mask) == 0) + tty_insert_flip_char(tty, ch, flag); + + if (*status & UART_LSR_OE) { /* * Overrun is special, since it's reported * 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); diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index 47f7404cb04..d957a3a9edf 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -313,7 +313,7 @@ static inline void receive_chars(struct mcf_serial *info) { volatile unsigned char *uartp; struct tty_struct *tty = info->tty; - unsigned char status, ch; + unsigned char status, ch, flag; if (!tty) return; @@ -321,10 +321,6 @@ static inline void receive_chars(struct mcf_serial *info) uartp = info->addr; while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) { - - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - break; - ch = uartp[MCFUART_URB]; info->stats.rx++; @@ -335,29 +331,24 @@ static inline void receive_chars(struct mcf_serial *info) } #endif - tty->flip.count++; + flag = TTY_NORMAL; if (status & MCFUART_USR_RXERR) { uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR; if (status & MCFUART_USR_RXBREAK) { info->stats.rxbreak++; - *tty->flip.flag_buf_ptr++ = TTY_BREAK; + flag = TTY_BREAK; } else if (status & MCFUART_USR_RXPARITY) { info->stats.rxparity++; - *tty->flip.flag_buf_ptr++ = TTY_PARITY; + flag = TTY_PARITY; } else if (status & MCFUART_USR_RXOVERRUN) { info->stats.rxoverrun++; - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; + flag = TTY_OVERRUN; } else if (status & MCFUART_USR_RXFRAMING) { info->stats.rxframing++; - *tty->flip.flag_buf_ptr++ = TTY_FRAME; - } else { - /* This should never happen... */ - *tty->flip.flag_buf_ptr++ = 0; + flag = TTY_FRAME; } - } else { - *tty->flip.flag_buf_ptr++ = 0; } - *tty->flip.char_buf_ptr++ = ch; + tty_insert_flip_char(tty, ch, flag); } schedule_work(&tty->flip.work); @@ -1525,7 +1516,7 @@ static void mcfrs_irqinit(struct mcf_serial *info) icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 + MCFINTC_ICR0 + MCFINT_UART0 + info->line); - *icrp = 0x33; /* UART0 with level 6, priority 3 */ + *icrp = 0x30 + info->line; /* level 6, line based priority */ imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 + MCFINTC_IMRL); diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 1288d6203e9..61dd17d7bac 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -405,17 +405,13 @@ static inline int mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs) { struct tty_struct *tty = port->info->tty; - unsigned char ch; + unsigned char ch, flag; unsigned short status; /* While we can read, do so ! */ while ( (status = in_be16(&PSC(port)->mpc52xx_psc_status)) & MPC52xx_PSC_SR_RXRDY) { - /* If we are full, just stop reading */ - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - break; - /* Get the char */ ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8); @@ -428,45 +424,35 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs) #endif /* Store it */ - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = 0; + + flag = TTY_NORMAL; port->icount.rx++; if ( status & (MPC52xx_PSC_SR_PE | MPC52xx_PSC_SR_FE | - MPC52xx_PSC_SR_RB | - MPC52xx_PSC_SR_OE) ) { + MPC52xx_PSC_SR_RB) ) { if (status & MPC52xx_PSC_SR_RB) { - *tty->flip.flag_buf_ptr = TTY_BREAK; + flag = TTY_BREAK; uart_handle_break(port); } else if (status & MPC52xx_PSC_SR_PE) - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; else if (status & MPC52xx_PSC_SR_FE) - *tty->flip.flag_buf_ptr = TTY_FRAME; - if (status & MPC52xx_PSC_SR_OE) { - /* - * Overrun is special, since it's - * reported immediately, and doesn't - * affect the current character - */ - if (tty->flip.count < (TTY_FLIPBUF_SIZE-1)) { - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - } - *tty->flip.flag_buf_ptr = TTY_OVERRUN; - } + flag = TTY_FRAME; /* Clear error condition */ out_8(&PSC(port)->command,MPC52xx_PSC_RST_ERR_STAT); } - - tty->flip.char_buf_ptr++; - tty->flip.flag_buf_ptr++; - tty->flip.count++; - + tty_insert_flip_char(tty, ch, flag); + if (status & MPC52xx_PSC_SR_OE) { + /* + * 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); diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index 8f83e4007ec..0ca83ac31d0 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -769,12 +769,12 @@ mpsc_rx_intr(struct mpsc_port_info *pi, struct pt_regs *regs) bytes_in = be16_to_cpu(rxre->bytecnt); /* Following use of tty struct directly is deprecated */ - if (unlikely((tty->flip.count + bytes_in) >= TTY_FLIPBUF_SIZE)){ + if (unlikely(tty_buffer_request_room(tty, bytes_in) < bytes_in)) { if (tty->low_latency) tty_flip_buffer_push(tty); /* - * If this failed then we will throw awa the bytes - * but mst do so to clear interrupts. + * If this failed then we will throw away the bytes + * but must do so to clear interrupts. */ } diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 7633132a10a..4e49168c317 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -223,11 +223,6 @@ static void mux_read(struct uart_port *port) if (MUX_EOFIFO(data)) break; - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - continue; - - *tty->flip.char_buf_ptr = data & 0xffu; - *tty->flip.flag_buf_ptr = TTY_NORMAL; port->icount.rx++; if (MUX_BREAK(data)) { @@ -239,9 +234,7 @@ static void mux_read(struct uart_port *port) if (uart_handle_sysrq_char(port, data & 0xffu, NULL)) continue; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + tty_insert_flip_char(tty, data & 0xFF, TTY_NORMAL); } if (start_count != port->icount.rx) { diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index ea24129eb6b..5f52883e64d 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -60,6 +60,7 @@ #include <linux/pmu.h> #include <linux/bitops.h> #include <linux/sysrq.h> +#include <linux/mutex.h> #include <asm/sections.h> #include <asm/io.h> #include <asm/irq.h> @@ -96,7 +97,7 @@ MODULE_LICENSE("GPL"); */ static struct uart_pmac_port pmz_ports[MAX_ZS_PORTS]; static int pmz_ports_count; -static DECLARE_MUTEX(pmz_irq_sem); +static DEFINE_MUTEX(pmz_irq_mutex); static struct uart_driver pmz_uart_reg = { .owner = THIS_MODULE, @@ -210,10 +211,9 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, struct pt_regs *regs) { struct tty_struct *tty = NULL; - unsigned char ch, r1, drop, error; + unsigned char ch, r1, drop, error, flag; int loops = 0; - retry: /* The interrupt can be enabled when the port isn't open, typically * that happens when using one port is open and the other closed (stale * interrupt) or when one port is used as a console. @@ -246,20 +246,6 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, error = 0; drop = 0; - if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { - /* Have to drop the lock here */ - pmz_debug("pmz: flip overflow\n"); - spin_unlock(&uap->port.lock); - tty->flip.work.func((void *)tty); - spin_lock(&uap->port.lock); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - drop = 1; - if (ZS_IS_ASLEEP(uap)) - return NULL; - if (!ZS_IS_OPEN(uap)) - goto retry; - } - r1 = read_zsreg(uap, R1); ch = read_zsdata(uap); @@ -295,8 +281,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, if (drop) goto next_char; - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; + flag = TTY_NORMAL; uap->port.icount.rx++; if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) { @@ -316,26 +301,19 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, uap->port.icount.overrun++; r1 &= uap->port.read_status_mask; if (r1 & BRK_ABRT) - *tty->flip.flag_buf_ptr = TTY_BREAK; + flag = TTY_BREAK; else if (r1 & PAR_ERR) - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; else if (r1 & CRC_ERR) - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_FRAME; } if (uap->port.ignore_status_mask == 0xff || (r1 & uap->port.ignore_status_mask) == 0) { - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - } - if ((r1 & Rx_OVR) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - *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, ch, flag); } + if (r1 & Rx_OVR) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); next_char: /* We can get stuck in an infinite loop getting char 0 when the * line is in a wrong HW state, we break that here. @@ -945,7 +923,7 @@ static int pmz_startup(struct uart_port *port) if (uap->node == NULL) return -ENODEV; - down(&pmz_irq_sem); + mutex_lock(&pmz_irq_mutex); uap->flags |= PMACZILOG_FLAG_IS_OPEN; @@ -963,11 +941,11 @@ static int pmz_startup(struct uart_port *port) dev_err(&uap->dev->ofdev.dev, "Unable to register zs interrupt handler.\n"); pmz_set_scc_power(uap, 0); - up(&pmz_irq_sem); + mutex_unlock(&pmz_irq_mutex); return -ENXIO; } - up(&pmz_irq_sem); + mutex_unlock(&pmz_irq_mutex); /* Right now, we deal with delay by blocking here, I'll be * smarter later on @@ -1004,7 +982,7 @@ static void pmz_shutdown(struct uart_port *port) if (uap->node == NULL) return; - down(&pmz_irq_sem); + mutex_lock(&pmz_irq_mutex); /* Release interrupt handler */ free_irq(uap->port.irq, uap); @@ -1025,7 +1003,7 @@ static void pmz_shutdown(struct uart_port *port) if (ZS_IS_CONS(uap) || ZS_IS_ASLEEP(uap)) { spin_unlock_irqrestore(&port->lock, flags); - up(&pmz_irq_sem); + mutex_unlock(&pmz_irq_mutex); return; } @@ -1042,7 +1020,7 @@ static void pmz_shutdown(struct uart_port *port) spin_unlock_irqrestore(&port->lock, flags); - up(&pmz_irq_sem); + mutex_unlock(&pmz_irq_mutex); pmz_debug("pmz: shutdown() done.\n"); } @@ -1614,7 +1592,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state) state = pmz_uart_reg.state + uap->port.line; - down(&pmz_irq_sem); + mutex_lock(&pmz_irq_mutex); down(&state->sem); spin_lock_irqsave(&uap->port.lock, flags); @@ -1647,7 +1625,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state) pmz_set_scc_power(uap, 0); up(&state->sem); - up(&pmz_irq_sem); + mutex_unlock(&pmz_irq_mutex); pmz_debug("suspend, switching complete\n"); @@ -1674,7 +1652,7 @@ static int pmz_resume(struct macio_dev *mdev) state = pmz_uart_reg.state + uap->port.line; - down(&pmz_irq_sem); + mutex_lock(&pmz_irq_mutex); down(&state->sem); spin_lock_irqsave(&uap->port.lock, flags); @@ -1708,7 +1686,7 @@ static int pmz_resume(struct macio_dev *mdev) bail: up(&state->sem); - up(&pmz_irq_sem); + mutex_unlock(&pmz_irq_mutex); /* Right now, we deal with delay by blocking here, I'll be * smarter later on diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index cc998b99a19..10535f00301 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -107,14 +107,6 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs) int max_count = 256; do { - if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { - 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_in(up, UART_RX); flag = TTY_NORMAL; up->port.icount.rx++; diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index fe83ce6fef5..eb4883efb7c 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -323,16 +323,6 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs) if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0) break; - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - 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 - */ - } - uerstat = rd_regl(port, S3C2410_UERSTAT); ch = rd_regb(port, S3C2410_URXH); diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 25a086458ab..1bd93168f50 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -201,8 +201,6 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) while (status & UTSR1_TO_SM(UTSR1_RNE)) { ch = UART_GET_CHAR(sport); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto ignore_char; sport->port.icount.rx++; flg = TTY_NORMAL; diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 9589509fc5b..2ca620900bc 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -33,6 +33,7 @@ #include <linux/device.h> #include <linux/serial.h> /* for serial_state and serial_icounter_struct */ #include <linux/delay.h> +#include <linux/mutex.h> #include <asm/irq.h> #include <asm/uaccess.h> @@ -47,7 +48,7 @@ /* * This is used to lock changes in serial line configuration. */ -static DECLARE_MUTEX(port_sem); +static DEFINE_MUTEX(port_mutex); #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) @@ -1472,7 +1473,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) { struct uart_state *state; - down(&port_sem); + mutex_lock(&port_mutex); state = drv->state + line; if (down_interruptible(&state->sem)) { state = ERR_PTR(-ERESTARTSYS); @@ -1509,7 +1510,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) } out: - up(&port_sem); + mutex_unlock(&port_mutex); return state; } @@ -2219,7 +2220,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) state = drv->state + port->line; - down(&port_sem); + mutex_lock(&port_mutex); if (state->port) { ret = -EINVAL; goto out; @@ -2255,7 +2256,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) register_console(port->cons); out: - up(&port_sem); + mutex_unlock(&port_mutex); return ret; } @@ -2279,7 +2280,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) printk(KERN_ALERT "Removing wrong port: %p != %p\n", state->port, port); - down(&port_sem); + mutex_lock(&port_mutex); /* * Remove the devices from devfs @@ -2288,7 +2289,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) uart_unconfigure_port(drv, state); state->port = NULL; - up(&port_sem); + mutex_unlock(&port_mutex); return 0; } diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index d01dbe5da3b..d4a1f0e798c 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -148,15 +148,6 @@ lh7a40xuart_rx_chars (struct uart_port* port) unsigned int data, flag;/* Received data and status */ while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) { - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - 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); flag = TTY_NORMAL; ++port->icount.rx; diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 995d9dd9ddd..ee98a867bc6 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -52,6 +52,7 @@ #include <linux/tty_flip.h> #include <linux/serial_core.h> #include <linux/serial.h> +#include <linux/mutex.h> #include <asm/io.h> #include <asm/irq.h> @@ -303,17 +304,6 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r 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)) { - if (tty->low_latency) { - spin_unlock(&up->port.lock); - tty_flip_buffer_push(tty); - spin_lock(&up->port.lock); - } - /* If this failed then we will throw away the - bytes but must do so to clear interrupts */ - } ch = sio_in(up, TXX9_SIRFIFO); flag = TTY_NORMAL; up->port.icount.rx++; @@ -1029,7 +1019,7 @@ static void serial_txx9_resume_port(int line) uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port); } -static DECLARE_MUTEX(serial_txx9_sem); +static DEFINE_MUTEX(serial_txx9_mutex); /** * serial_txx9_register_port - register a serial port @@ -1048,7 +1038,7 @@ static int __devinit serial_txx9_register_port(struct uart_port *port) struct uart_txx9_port *uart; int ret = -ENOSPC; - down(&serial_txx9_sem); + mutex_lock(&serial_txx9_mutex); for (i = 0; i < UART_NR; i++) { uart = &serial_txx9_ports[i]; if (uart->port.type == PORT_UNKNOWN) @@ -1069,7 +1059,7 @@ static int __devinit serial_txx9_register_port(struct uart_port *port) if (ret == 0) ret = uart->port.line; } - up(&serial_txx9_sem); + mutex_unlock(&serial_txx9_mutex); return ret; } @@ -1084,7 +1074,7 @@ static void __devexit serial_txx9_unregister_port(int line) { struct uart_txx9_port *uart = &serial_txx9_ports[line]; - down(&serial_txx9_sem); + mutex_lock(&serial_txx9_mutex); uart_remove_one_port(&serial_txx9_reg, &uart->port); uart->port.flags = 0; uart->port.type = PORT_UNKNOWN; @@ -1093,7 +1083,7 @@ static void __devexit serial_txx9_unregister_port(int line) uart->port.membase = 0; uart->port.dev = NULL; uart_add_one_port(&serial_txx9_reg, &uart->port); - up(&serial_txx9_sem); + mutex_unlock(&serial_txx9_mutex); } /* diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 430754ebac8..a9e07075962 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -482,6 +482,7 @@ static inline void sci_receive_chars(struct uart_port *port, struct tty_struct *tty = port->info->tty; int i, count, copied = 0; unsigned short status; + unsigned char flag; status = sci_in(port, SCxSR); if (!(status & SCxSR_RDxF(port))) @@ -499,8 +500,7 @@ static inline void sci_receive_chars(struct uart_port *port, #endif /* Don't copy more bytes than there is room for in the buffer */ - if (tty->flip.count + count > TTY_FLIPBUF_SIZE) - count = TTY_FLIPBUF_SIZE - tty->flip.count; + count = tty_buffer_request_room(tty, count); /* If for any reason we can't copy more data, we're done! */ if (count == 0) @@ -512,8 +512,7 @@ static inline void sci_receive_chars(struct uart_port *port, || uart_handle_sysrq_char(port, c, regs)) { count = 0; } else { - tty->flip.char_buf_ptr[0] = c; - tty->flip.flag_buf_ptr[0] = TTY_NORMAL; + tty_insert_flip_char(tty, c, TTY_NORMAL); } } else { for (i=0; i<count; i++) { @@ -542,26 +541,21 @@ static inline void sci_receive_chars(struct uart_port *port, } /* Store data and status */ - tty->flip.char_buf_ptr[i] = c; if (status&SCxSR_FER(port)) { - tty->flip.flag_buf_ptr[i] = TTY_FRAME; + flag = TTY_FRAME; pr_debug("sci: frame error\n"); } else if (status&SCxSR_PER(port)) { - tty->flip.flag_buf_ptr[i] = TTY_PARITY; + flag = TTY_PARITY; pr_debug("sci: parity error\n"); - } else { - tty->flip.flag_buf_ptr[i] = TTY_NORMAL; - } + } else + flag = TTY_NORMAL; + tty_insert_flip_char(tty, c, flag); } } sci_in(port, SCxSR); /* dummy read */ sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); - /* Update the kernel buffer end */ - tty->flip.count += count; - tty->flip.char_buf_ptr += count; - tty->flip.flag_buf_ptr += count; copied += count; port->icount.rx += count; } @@ -608,48 +602,45 @@ static inline int sci_handle_errors(struct uart_port *port) unsigned short status = sci_in(port, SCxSR); struct tty_struct *tty = port->info->tty; - if (status&SCxSR_ORER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) { + if (status&SCxSR_ORER(port)) { /* overrun error */ - copied++; - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; + if(tty_insert_flip_char(tty, 0, TTY_OVERRUN)) + copied++; pr_debug("sci: overrun error\n"); } - if (status&SCxSR_FER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) { + if (status&SCxSR_FER(port)) { if (sci_rxd_in(port) == 0) { /* Notify of BREAK */ struct sci_port * sci_port = (struct sci_port *)port; - if(!sci_port->break_flag) { - sci_port->break_flag = 1; - sci_schedule_break_timer((struct sci_port *)port); + if(!sci_port->break_flag) { + sci_port->break_flag = 1; + sci_schedule_break_timer((struct sci_port *)port); /* Do sysrq handling. */ - if(uart_handle_break(port)) { + if(uart_handle_break(port)) return 0; - } pr_debug("sci: BREAK detected\n"); - copied++; - *tty->flip.flag_buf_ptr++ = TTY_BREAK; + if(tty_insert_flip_char(tty, 0, TTY_BREAK)) + copied++; } } else { /* frame error */ - copied++; - *tty->flip.flag_buf_ptr++ = TTY_FRAME; + if(tty_insert_flip_char(tty, 0, TTY_FRAME)) + copied++; pr_debug("sci: frame error\n"); } } - if (status&SCxSR_PER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) { + if (status&SCxSR_PER(port)) { + if(tty_insert_flip_char(tty, 0, TTY_PARITY)) + copied++; /* parity error */ - copied++; - *tty->flip.flag_buf_ptr++ = TTY_PARITY; pr_debug("sci: parity error\n"); } - if (copied) { - tty->flip.count += copied; + if (copied) tty_flip_buffer_push(tty); - } return copied; } @@ -661,15 +652,14 @@ static inline int sci_handle_breaks(struct uart_port *port) struct tty_struct *tty = port->info->tty; struct sci_port *s = &sci_ports[port->line]; - if (!s->break_flag && status & SCxSR_BRK(port) && - tty->flip.count < TTY_FLIPBUF_SIZE) { + if (!s->break_flag && status & SCxSR_BRK(port)) #if defined(CONFIG_CPU_SH3) /* Debounce break */ s->break_flag = 1; #endif /* Notify of BREAK */ - copied++; - *tty->flip.flag_buf_ptr++ = TTY_BREAK; + if(tty_insert_flip_char(tty, 0, TTY_BREAK)) + copied++; pr_debug("sci: BREAK detected\n"); } @@ -677,19 +667,15 @@ static inline int sci_handle_breaks(struct uart_port *port) /* XXX: Handle SCIF overrun error */ if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) { sci_out(port, SCLSR, 0); - if(tty->flip.count<TTY_FLIPBUF_SIZE) { + if(tty_insert_flip_char(tty, 0, TTY_OVERRUN)) { copied++; - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; pr_debug("sci: overrun error\n"); } } #endif - if (copied) { - tty->flip.count += copied; + if (copied) tty_flip_buffer_push(tty); - } - return copied; } @@ -732,12 +718,9 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr, struct pt_regs *regs) struct tty_struct *tty = port->info->tty; sci_out(port, SCLSR, 0); - if(tty->flip.count<TTY_FLIPBUF_SIZE) { - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; - tty->flip.count++; - tty_flip_buffer_push(tty); - pr_debug("scif: overrun error\n"); - } + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + tty_flip_buffer_push(tty); + pr_debug("scif: overrun error\n"); } #endif sci_rx_interrupt(irq, ptr, regs); diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 313f9df24a2..5468e5a767e 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -519,11 +519,7 @@ sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs, /* record the character to pass up to the tty layer */ if (tty) { - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; - tty->flip.char_buf_ptr++; - tty->flip.count++; - if (tty->flip.count == TTY_FLIPBUF_SIZE) + if(tty_insert_flip_char(tty, ch, TTY_NORMAL) == 0) break; } port->sc_port.icount.rx++; diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index ba9381fd3f2..7e773ff76c6 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -159,21 +159,14 @@ receive_chars(struct uart_sunsab_port *up, saw_console_brk = 1; for (i = 0; i < count; i++) { - unsigned char ch = buf[i]; + unsigned char ch = buf[i], flag; if (tty == NULL) { uart_handle_sysrq_char(&up->port, ch, regs); continue; } - if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { - tty->flip.work.func((void *)tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - return tty; // if TTY_DONT_FLIP is set - } - - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; + flag = TTY_NORMAL; up->port.icount.rx++; if (unlikely(stat->sreg.isr0 & (SAB82532_ISR0_PERR | @@ -209,34 +202,21 @@ receive_chars(struct uart_sunsab_port *up, stat->sreg.isr1 &= ((up->port.read_status_mask >> 8) & 0xff); if (stat->sreg.isr1 & SAB82532_ISR1_BRK) { - *tty->flip.flag_buf_ptr = TTY_BREAK; + flag = TTY_BREAK; } else if (stat->sreg.isr0 & SAB82532_ISR0_PERR) - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; else if (stat->sreg.isr0 & SAB82532_ISR0_FERR) - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_FRAME; } if (uart_handle_sysrq_char(&up->port, ch, regs)) continue; if ((stat->sreg.isr0 & (up->port.ignore_status_mask & 0xff)) == 0 && - (stat->sreg.isr1 & ((up->port.ignore_status_mask >> 8) & 0xff)) == 0){ - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - } - if ((stat->sreg.isr0 & SAB82532_ISR0_RFO) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * 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++; - } + (stat->sreg.isr1 & ((up->port.ignore_status_mask >> 8) & 0xff)) == 0) + tty_insert_flip_char(tty, ch, flag); + if (stat->sreg.isr0 & SAB82532_ISR0_RFO) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); } if (saw_console_brk) diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index f0738533f39..9a3665b34d9 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -323,19 +323,13 @@ static _INLINE_ struct tty_struct * receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs *regs) { struct tty_struct *tty = up->port.info->tty; - unsigned char ch; + unsigned char ch, flag; int max_count = 256; int saw_console_brk = 0; do { - if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { - tty->flip.work.func((void *)tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - return tty; // if TTY_DONT_FLIP is set - } 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++; if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | @@ -377,31 +371,23 @@ receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs } 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++; - } - if ((*status & UART_LSR_OE) && - tty->flip.count < TTY_FLIPBUF_SIZE) { + if ((*status & up->port.ignore_status_mask) == 0) + tty_insert_flip_char(tty, ch, flag); + if (*status & UART_LSR_OE) /* * Overrun is special, since it's reported * 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_inp(up, UART_LSR); } while ((*status & UART_LSR_DR) && (max_count-- > 0)); diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 7653d6cf05a..3c72484adea 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -319,7 +319,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up, struct pt_regs *regs) { struct tty_struct *tty; - unsigned char ch, r1; + unsigned char ch, r1, flag; tty = NULL; if (up->port.info != NULL && /* Unopened serial console */ @@ -362,19 +362,8 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up, continue; } - if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { - tty->flip.work.func((void *)tty); - /* - * The 8250 bails out of the loop here, - * but we need to read everything, or die. - */ - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - continue; - } - /* A real serial line, record the character and status. */ - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; + flag = TTY_NORMAL; up->port.icount.rx++; if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) { if (r1 & BRK_ABRT) { @@ -391,28 +380,21 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up, up->port.icount.overrun++; r1 &= up->port.read_status_mask; if (r1 & BRK_ABRT) - *tty->flip.flag_buf_ptr = TTY_BREAK; + flag = TTY_BREAK; else if (r1 & PAR_ERR) - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; else if (r1 & CRC_ERR) - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_FRAME; } if (uart_handle_sysrq_char(&up->port, ch, regs)) continue; if (up->port.ignore_status_mask == 0xff || (r1 & up->port.ignore_status_mask) == 0) { - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - } - if ((r1 & Rx_OVR) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - *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, ch, flag); } + if (r1 & Rx_OVR) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); } return tty; diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index 865d4dea65d..d61494d185c 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -1,7 +1,7 @@ /* * Driver for NEC VR4100 series Serial Interface Unit. * - * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> + * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * Based on drivers/serial/8250.c, by Russell King. * @@ -371,11 +371,6 @@ static inline void receive_chars(struct uart_port *port, uint8_t *status, lsr = *status; do { - if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { - if (tty->low_latency) - tty_flip_buffer_push(tty); - } - ch = siu_read(port, UART_RX); port->icount.rx++; flag = TTY_NORMAL; |