aboutsummaryrefslogtreecommitdiff
path: root/drivers/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/21285.c9
-rw-r--r--drivers/serial/68328serial.c18
-rw-r--r--drivers/serial/68360serial.c54
-rw-r--r--drivers/serial/8250.c24
-rw-r--r--drivers/serial/Kconfig2
-rw-r--r--drivers/serial/amba-pl010.c9
-rw-r--r--drivers/serial/amba-pl011.c9
-rw-r--r--drivers/serial/au1x00_uart.c31
-rw-r--r--drivers/serial/clps711x.c2
-rw-r--r--drivers/serial/crisv10.c11
-rw-r--r--drivers/serial/dz.c2
-rw-r--r--drivers/serial/icom.c57
-rw-r--r--drivers/serial/imx.c3
-rw-r--r--drivers/serial/ioc4_serial.c10
-rw-r--r--drivers/serial/ip22zilog.c34
-rw-r--r--drivers/serial/m32r_sio.c31
-rw-r--r--drivers/serial/mcfserial.c25
-rw-r--r--drivers/serial/mpc52xx_uart.c46
-rw-r--r--drivers/serial/mpsc.c6
-rw-r--r--drivers/serial/mux.c9
-rw-r--r--drivers/serial/pmac_zilog.c62
-rw-r--r--drivers/serial/pxa.c8
-rw-r--r--drivers/serial/s3c2410.c10
-rw-r--r--drivers/serial/sa1100.c2
-rw-r--r--drivers/serial/serial_core.c15
-rw-r--r--drivers/serial/serial_lh7a40x.c9
-rw-r--r--drivers/serial/serial_txx9.c22
-rw-r--r--drivers/serial/sh-sci.c81
-rw-r--r--drivers/serial/sn_console.c6
-rw-r--r--drivers/serial/sunsab.c38
-rw-r--r--drivers/serial/sunsu.c32
-rw-r--r--drivers/serial/sunzilog.c34
-rw-r--r--drivers/serial/vr41xx_siu.c7
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;