aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2006-01-09 23:54:13 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-10 11:01:59 -0500
commit33f0f88f1c51ae5c2d593d26960c760ea154c2e2 (patch)
treef53a38cf49406863f079d74d0e8f91b276f7c1a9 /drivers/serial
parent6ed80991a2dce4afc113be35089c564d62fa1f11 (diff)
[PATCH] TTY layer buffering revamp
The API and code have been through various bits of initial review by serial driver people but they definitely need to live somewhere for a while so the unconverted drivers can get knocked into shape, existing drivers that have been updated can be better tuned and bugs whacked out. This replaces the tty flip buffers with kmalloc objects in rings. In the normal situation for an IRQ driven serial port at typical speeds the behaviour is pretty much the same, two buffers end up allocated and the kernel cycles between them as before. When there are delays or at high speed we now behave far better as the buffer pool can grow a bit rather than lose characters. This also means that we can operate at higher speeds reliably. For drivers that receive characters in blocks (DMA based, USB and especially virtualisation) the layer allows a lot of driver specific code that works around the tty layer with private secondary queues to be removed. The IBM folks need this sort of layer, the smart serial port people do, the virtualisers do (because a virtualised tty typically operates at infinite speed rather than emulating 9600 baud). Finally many drivers had invalid and unsafe attempts to avoid buffer overflows by directly invoking tty methods extracted out of the innards of work queue structs. These are no longer needed and all go away. That fixes various random hangs with serial ports on overflow. The other change in here is to optimise the receive_room path that is used by some callers. It turns out that only one ldisc uses receive room except asa constant and it updates it far far less than the value is read. We thus make it a variable not a function call. I expect the code to contain bugs due to the size alone but I'll be watching and squashing them and feeding out new patches as it goes. Because the buffers now dynamically expand you should only run out of buffering when the kernel runs out of memory for real. That means a lot of the horrible hacks high performance drivers used to do just aren't needed any more. Description: tty_insert_flip_char is an old API and continues to work as before, as does tty_flip_buffer_push() [this is why many drivers dont need modification]. It does now also return the number of chars inserted There are also tty_buffer_request_room(tty, len) which asks for a buffer block of the length requested and returns the space found. This improves efficiency with hardware that knows how much to transfer. and tty_insert_flip_string_flags(tty, str, flags, len) to insert a string of characters and flags For a smart interface the usual code is len = tty_request_buffer_room(tty, amount_hardware_says); tty_insert_flip_string(tty, buffer_from_card, len); More description! At the moment tty buffers are attached directly to the tty. This is causing a lot of the problems related to tty layer locking, also problems at high speed and also with bursty data (such as occurs in virtualised environments) I'm working on ripping out the flip buffers and replacing them with a pool of dynamically allocated buffers. This allows both for old style "byte I/O" devices and also helps virtualisation and smart devices where large blocks of data suddenely materialise and need storing. So far so good. Lots of drivers reference tty->flip.*. Several of them also call directly and unsafely into function pointers it provides. This will all break. Most drivers can use tty_insert_flip_char which can be kept as an API but others need more. At the moment I've added the following interfaces, if people think more will be needed now is a good time to say int tty_buffer_request_room(tty, size) Try and ensure at least size bytes are available, returns actual room (may be zero). At the moment it just uses the flipbuf space but that will change. Repeated calls without characters being added are not cumulative. (ie if you call it with 1, 1, 1, and then 4 you'll have four characters of space. The other functions will also try and grow buffers in future but this will be a more efficient way when you know block sizes. int tty_insert_flip_char(tty, ch, flag) As before insert a character if there is room. Now returns 1 for success, 0 for failure. int tty_insert_flip_string(tty, str, len) Insert a block of non error characters. Returns the number inserted. int tty_prepare_flip_string(tty, strptr, len) Adjust the buffer to allow len characters to be added. Returns a buffer pointer in strptr and the length available. This allows for hardware that needs to use functions like insl or mencpy_fromio. Signed-off-by: Alan Cox <alan@redhat.com> Cc: Paul Fulghum <paulkf@microgate.com> Signed-off-by: Hirokazu Takata <takata@linux-m32r.org> Signed-off-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: Jeff Dike <jdike@addtoit.com> Signed-off-by: John Hawkes <hawkes@sgi.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
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.c13
-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/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.c23
-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.c39
-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_lh7a40x.c9
-rw-r--r--drivers/serial/serial_txx9.c11
-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.c5
30 files changed, 171 insertions, 470 deletions
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index b5cf39468d18..221999bcf8fe 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
94 94
95 status = *CSR_UARTFLG; 95 status = *CSR_UARTFLG;
96 while (!(status & 0x10) && max_count--) { 96 while (!(status & 0x10) && max_count--) {
97 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
98 if (tty->low_latency)
99 tty_flip_buffer_push(tty);
100 /*
101 * If this failed then we will throw away the
102 * bytes but must do so to clear interrupts
103 */
104 }
105
106 ch = *CSR_UARTDR; 97 ch = *CSR_UARTDR;
107 flag = TTY_NORMAL; 98 flag = TTY_NORMAL;
108 port->icount.rx++; 99 port->icount.rx++;
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 67e9afa000c1..4dd5c3f98167 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
294{ 294{
295 struct tty_struct *tty = info->tty; 295 struct tty_struct *tty = info->tty;
296 m68328_uart *uart = &uart_addr[info->line]; 296 m68328_uart *uart = &uart_addr[info->line];
297 unsigned char ch; 297 unsigned char ch, flag;
298 298
299 /* 299 /*
300 * This do { } while() loop will get ALL chars out of Rx FIFO 300 * 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
332 /* 332 /*
333 * Make sure that we do not overflow the buffer 333 * Make sure that we do not overflow the buffer
334 */ 334 */
335 if (tty->flip.count >= TTY_FLIPBUF_SIZE) { 335 if (tty_request_buffer_room(tty, 1) == 0) {
336 schedule_work(&tty->flip.work); 336 schedule_work(&tty->flip.work);
337 return; 337 return;
338 } 338 }
339 339
340 flag = TTY_NORMAL;
341
340 if(rx & URX_PARITY_ERROR) { 342 if(rx & URX_PARITY_ERROR) {
341 *tty->flip.flag_buf_ptr++ = TTY_PARITY; 343 flag = TTY_PARITY;
342 status_handle(info, rx); 344 status_handle(info, rx);
343 } else if(rx & URX_OVRUN) { 345 } else if(rx & URX_OVRUN) {
344 *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; 346 flag = TTY_OVERRUN;
345 status_handle(info, rx); 347 status_handle(info, rx);
346 } else if(rx & URX_FRAME_ERROR) { 348 } else if(rx & URX_FRAME_ERROR) {
347 *tty->flip.flag_buf_ptr++ = TTY_FRAME; 349 flag = TTY_FRAME;
348 status_handle(info, rx); 350 status_handle(info, rx);
349 } else {
350 *tty->flip.flag_buf_ptr++ = 0; /* XXX */
351 } 351 }
352 *tty->flip.char_buf_ptr++ = ch; 352 tty_insert_flip_char(tty, ch, flag);
353 tty->flip.count++;
354
355#ifndef CONFIG_XCOPILOT_BUGS 353#ifndef CONFIG_XCOPILOT_BUGS
356 } while((rx = uart->urx.w) & URX_DATA_READY); 354 } while((rx = uart->urx.w) & URX_DATA_READY);
357#endif 355#endif
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 170c9d2a749c..60f5a5dc17f1 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -394,7 +394,7 @@ static void rs_360_start(struct tty_struct *tty)
394static _INLINE_ void receive_chars(ser_info_t *info) 394static _INLINE_ void receive_chars(ser_info_t *info)
395{ 395{
396 struct tty_struct *tty = info->tty; 396 struct tty_struct *tty = info->tty;
397 unsigned char ch, *cp; 397 unsigned char ch, flag, *cp;
398 /*int ignored = 0;*/ 398 /*int ignored = 0;*/
399 int i; 399 int i;
400 ushort status; 400 ushort status;
@@ -438,24 +438,15 @@ static _INLINE_ void receive_chars(ser_info_t *info)
438 cp = (char *)bdp->buf; 438 cp = (char *)bdp->buf;
439 status = bdp->status; 439 status = bdp->status;
440 440
441 /* Check to see if there is room in the tty buffer for
442 * the characters in our BD buffer. If not, we exit
443 * now, leaving the BD with the characters. We'll pick
444 * them up again on the next receive interrupt (which could
445 * be a timeout).
446 */
447 if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE)
448 break;
449
450 while (i-- > 0) { 441 while (i-- > 0) {
451 ch = *cp++; 442 ch = *cp++;
452 *tty->flip.char_buf_ptr = ch;
453 icount->rx++; 443 icount->rx++;
454 444
455#ifdef SERIAL_DEBUG_INTR 445#ifdef SERIAL_DEBUG_INTR
456 printk("DR%02x:%02x...", ch, status); 446 printk("DR%02x:%02x...", ch, status);
457#endif 447#endif
458 *tty->flip.flag_buf_ptr = 0; 448 flag = TTY_NORMAL;
449
459 if (status & (BD_SC_BR | BD_SC_FR | 450 if (status & (BD_SC_BR | BD_SC_FR |
460 BD_SC_PR | BD_SC_OV)) { 451 BD_SC_PR | BD_SC_OV)) {
461 /* 452 /*
@@ -490,30 +481,18 @@ static _INLINE_ void receive_chars(ser_info_t *info)
490 if (info->flags & ASYNC_SAK) 481 if (info->flags & ASYNC_SAK)
491 do_SAK(tty); 482 do_SAK(tty);
492 } else if (status & BD_SC_PR) 483 } else if (status & BD_SC_PR)
493 *tty->flip.flag_buf_ptr = TTY_PARITY; 484 flag = TTY_PARITY;
494 else if (status & BD_SC_FR) 485 else if (status & BD_SC_FR)
495 *tty->flip.flag_buf_ptr = TTY_FRAME; 486 flag = TTY_FRAME;
496 if (status & BD_SC_OV) {
497 /*
498 * Overrun is special, since it's
499 * reported immediately, and doesn't
500 * affect the current character
501 */
502 if (tty->flip.count < TTY_FLIPBUF_SIZE) {
503 tty->flip.count++;
504 tty->flip.flag_buf_ptr++;
505 tty->flip.char_buf_ptr++;
506 *tty->flip.flag_buf_ptr =
507 TTY_OVERRUN;
508 }
509 }
510 } 487 }
511 if (tty->flip.count >= TTY_FLIPBUF_SIZE) 488 tty_insert_flip_char(tty, ch, flag);
512 break; 489 if (status & BD_SC_OV)
513 490 /*
514 tty->flip.flag_buf_ptr++; 491 * Overrun is special, since it's
515 tty->flip.char_buf_ptr++; 492 * reported immediately, and doesn't
516 tty->flip.count++; 493 * affect the current character
494 */
495 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
517 } 496 }
518 497
519 /* This BD is ready to be used again. Clear status. 498 /* This BD is ready to be used again. Clear status.
@@ -541,12 +520,7 @@ static _INLINE_ void receive_break(ser_info_t *info)
541 /* Check to see if there is room in the tty buffer for 520 /* Check to see if there is room in the tty buffer for
542 * the break. If not, we exit now, losing the break. FIXME 521 * the break. If not, we exit now, losing the break. FIXME
543 */ 522 */
544 if ((tty->flip.count + 1) >= TTY_FLIPBUF_SIZE) 523 tty_insert_flip_char(tty, 0, TTY_BREAK);
545 return;
546 *(tty->flip.flag_buf_ptr++) = TTY_BREAK;
547 *(tty->flip.char_buf_ptr++) = 0;
548 tty->flip.count++;
549
550 schedule_work(&tty->flip.work); 524 schedule_work(&tty->flip.work);
551} 525}
552 526
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index e8454611cb65..54e5cc0dd5f8 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1142,19 +1142,6 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
1142 char flag; 1142 char flag;
1143 1143
1144 do { 1144 do {
1145 /* The following is not allowed by the tty layer and
1146 unsafe. It should be fixed ASAP */
1147 if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
1148 if (tty->low_latency) {
1149 spin_unlock(&up->port.lock);
1150 tty_flip_buffer_push(tty);
1151 spin_lock(&up->port.lock);
1152 }
1153 /*
1154 * If this failed then we will throw away the
1155 * bytes but must do so to clear interrupts
1156 */
1157 }
1158 ch = serial_inp(up, UART_RX); 1145 ch = serial_inp(up, UART_RX);
1159 flag = TTY_NORMAL; 1146 flag = TTY_NORMAL;
1160 up->port.icount.rx++; 1147 up->port.icount.rx++;
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 48f6e872314b..3490022e9fdc 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -154,15 +154,6 @@ pl010_rx_chars(struct uart_port *port)
154 154
155 status = UART_GET_FR(port); 155 status = UART_GET_FR(port);
156 while (UART_RX_DATA(status) && max_count--) { 156 while (UART_RX_DATA(status) && max_count--) {
157 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
158 if (tty->low_latency)
159 tty_flip_buffer_push(tty);
160 /*
161 * If this failed then we will throw away the
162 * bytes but must do so to clear interrupts.
163 */
164 }
165
166 ch = UART_GET_CHAR(port); 157 ch = UART_GET_CHAR(port);
167 flag = TTY_NORMAL; 158 flag = TTY_NORMAL;
168 159
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 129670556162..034a029e356e 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)
120 120
121 status = readw(uap->port.membase + UART01x_FR); 121 status = readw(uap->port.membase + UART01x_FR);
122 while ((status & UART01x_FR_RXFE) == 0 && max_count--) { 122 while ((status & UART01x_FR_RXFE) == 0 && max_count--) {
123 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
124 if (tty->low_latency)
125 tty_flip_buffer_push(tty);
126 /*
127 * If this failed then we will throw away the
128 * bytes but must do so to clear interrupts
129 */
130 }
131
132 ch = readw(uap->port.membase + UART01x_DR) | UART_DUMMY_DR_RX; 123 ch = readw(uap->port.membase + UART01x_DR) | UART_DUMMY_DR_RX;
133 flag = TTY_NORMAL; 124 flag = TTY_NORMAL;
134 uap->port.icount.rx++; 125 uap->port.icount.rx++;
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
index a274ebf256a1..ceb5d7f37bbd 100644
--- a/drivers/serial/au1x00_uart.c
+++ b/drivers/serial/au1x00_uart.c
@@ -241,18 +241,12 @@ static _INLINE_ void
241receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) 241receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
242{ 242{
243 struct tty_struct *tty = up->port.info->tty; 243 struct tty_struct *tty = up->port.info->tty;
244 unsigned char ch; 244 unsigned char ch, flag;
245 int max_count = 256; 245 int max_count = 256;
246 246
247 do { 247 do {
248 if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
249 tty->flip.work.func((void *)tty);
250 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
251 return; // if TTY_DONT_FLIP is set
252 }
253 ch = serial_inp(up, UART_RX); 248 ch = serial_inp(up, UART_RX);
254 *tty->flip.char_buf_ptr = ch; 249 flag = TTY_NORMAL;
255 *tty->flip.flag_buf_ptr = TTY_NORMAL;
256 up->port.icount.rx++; 250 up->port.icount.rx++;
257 251
258 if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | 252 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)
292#endif 286#endif
293 if (*status & UART_LSR_BI) { 287 if (*status & UART_LSR_BI) {
294 DEBUG_INTR("handling break...."); 288 DEBUG_INTR("handling break....");
295 *tty->flip.flag_buf_ptr = TTY_BREAK; 289 flag = TTY_BREAK;
296 } else if (*status & UART_LSR_PE) 290 } else if (*status & UART_LSR_PE)
297 *tty->flip.flag_buf_ptr = TTY_PARITY; 291 flag = TTY_PARITY;
298 else if (*status & UART_LSR_FE) 292 else if (*status & UART_LSR_FE)
299 *tty->flip.flag_buf_ptr = TTY_FRAME; 293 flag = TTY_FRAME;
300 } 294 }
301 if (uart_handle_sysrq_char(&up->port, ch, regs)) 295 if (uart_handle_sysrq_char(&up->port, ch, regs))
302 goto ignore_char; 296 goto ignore_char;
303 if ((*status & up->port.ignore_status_mask) == 0) { 297 if ((*status & up->port.ignore_status_mask) == 0)
304 tty->flip.flag_buf_ptr++; 298 tty_insert_flip_char(tty, ch, flag);
305 tty->flip.char_buf_ptr++; 299 if (*status & UART_LSR_OE)
306 tty->flip.count++;
307 }
308 if ((*status & UART_LSR_OE) &&
309 tty->flip.count < TTY_FLIPBUF_SIZE) {
310 /* 300 /*
311 * Overrun is special, since it's reported 301 * Overrun is special, since it's reported
312 * immediately, and doesn't affect the current 302 * immediately, and doesn't affect the current
313 * character. 303 * character.
314 */ 304 */
315 *tty->flip.flag_buf_ptr = TTY_OVERRUN; 305 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
316 tty->flip.flag_buf_ptr++;
317 tty->flip.char_buf_ptr++;
318 tty->flip.count++;
319 } 306 }
320 ignore_char: 307 ignore_char:
321 *status = serial_inp(up, UART_LSR); 308 *status = serial_inp(up, UART_LSR);
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index 87ef368384fb..8ef999481f93 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
104 while (!(status & SYSFLG_URXFE)) { 104 while (!(status & SYSFLG_URXFE)) {
105 ch = clps_readl(UARTDR(port)); 105 ch = clps_readl(UARTDR(port));
106 106
107 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
108 goto ignore_char;
109 port->icount.rx++; 107 port->icount.rx++;
110 108
111 flg = TTY_NORMAL; 109 flg = TTY_NORMAL;
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index 4d8516d1bb71..a64ba26a94e8 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)
216 216
217 if (!tty) 217 if (!tty)
218 break; 218 break;
219 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
220 break;
221 219
222 icount->rx++; 220 icount->rx++;
223 221
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index eb31125c6a30..144a7a352b28 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)
729 unsigned short int status; 729 unsigned short int status;
730 struct uart_icount *icount; 730 struct uart_icount *icount;
731 unsigned long offset; 731 unsigned long offset;
732 unsigned char flag;
732 733
733 trace(icom_port, "RCV_COMPLETE", 0); 734 trace(icom_port, "RCV_COMPLETE", 0);
734 rcv_buff = icom_port->next_rcv; 735 rcv_buff = icom_port->next_rcv;
735 736
736 status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags); 737 status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
737 while (status & SA_FL_RCV_DONE) { 738 while (status & SA_FL_RCV_DONE) {
739 int first = -1;
738 740
739 trace(icom_port, "FID_STATUS", status); 741 trace(icom_port, "FID_STATUS", status);
740 count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength); 742 count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength);
741 743
744 count = tty_buffer_request_room(tty, count);
742 trace(icom_port, "RCV_COUNT", count); 745 trace(icom_port, "RCV_COUNT", count);
743 if (count > (TTY_FLIPBUF_SIZE - tty->flip.count))
744 count = TTY_FLIPBUF_SIZE - tty->flip.count;
745 746
746 trace(icom_port, "REAL_COUNT", count); 747 trace(icom_port, "REAL_COUNT", count);
747 748
@@ -749,15 +750,10 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
749 cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) - 750 cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) -
750 icom_port->recv_buf_pci; 751 icom_port->recv_buf_pci;
751 752
752 memcpy(tty->flip.char_buf_ptr,(unsigned char *) 753 /* Block copy all but the last byte as this may have status */
753 ((unsigned long)icom_port->recv_buf + offset), count);
754
755 if (count > 0) { 754 if (count > 0) {
756 tty->flip.count += count - 1; 755 first = icom_port->recv_buf[offset];
757 tty->flip.char_buf_ptr += count - 1; 756 tty_insert_flip_string(tty, icom_port->recv_buf + offset, count - 1);
758
759 memset(tty->flip.flag_buf_ptr, 0, count);
760 tty->flip.flag_buf_ptr += count - 1;
761 } 757 }
762 758
763 icount = &icom_port->uart_port.icount; 759 icount = &icom_port->uart_port.icount;
@@ -765,12 +761,14 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
765 761
766 /* Break detect logic */ 762 /* Break detect logic */
767 if ((status & SA_FLAGS_FRAME_ERROR) 763 if ((status & SA_FLAGS_FRAME_ERROR)
768 && (tty->flip.char_buf_ptr[0] == 0x00)) { 764 && first == 0) {
769 status &= ~SA_FLAGS_FRAME_ERROR; 765 status &= ~SA_FLAGS_FRAME_ERROR;
770 status |= SA_FLAGS_BREAK_DET; 766 status |= SA_FLAGS_BREAK_DET;
771 trace(icom_port, "BREAK_DET", 0); 767 trace(icom_port, "BREAK_DET", 0);
772 } 768 }
773 769
770 flag = TTY_NORMAL;
771
774 if (status & 772 if (status &
775 (SA_FLAGS_BREAK_DET | SA_FLAGS_PARITY_ERROR | 773 (SA_FLAGS_BREAK_DET | SA_FLAGS_PARITY_ERROR |
776 SA_FLAGS_FRAME_ERROR | SA_FLAGS_OVERRUN)) { 774 SA_FLAGS_FRAME_ERROR | SA_FLAGS_OVERRUN)) {
@@ -797,33 +795,26 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
797 status &= icom_port->read_status_mask; 795 status &= icom_port->read_status_mask;
798 796
799 if (status & SA_FLAGS_BREAK_DET) { 797 if (status & SA_FLAGS_BREAK_DET) {
800 *tty->flip.flag_buf_ptr = TTY_BREAK; 798 flag = TTY_BREAK;
801 } else if (status & SA_FLAGS_PARITY_ERROR) { 799 } else if (status & SA_FLAGS_PARITY_ERROR) {
802 trace(icom_port, "PARITY_ERROR", 0); 800 trace(icom_port, "PARITY_ERROR", 0);
803 *tty->flip.flag_buf_ptr = TTY_PARITY; 801 flag = TTY_PARITY;
804 } else if (status & SA_FLAGS_FRAME_ERROR) 802 } else if (status & SA_FLAGS_FRAME_ERROR)
805 *tty->flip.flag_buf_ptr = TTY_FRAME; 803 flag = TTY_FRAME;
806 804
807 if (status & SA_FLAGS_OVERRUN) {
808 /*
809 * Overrun is special, since it's
810 * reported immediately, and doesn't
811 * affect the current character
812 */
813 if (tty->flip.count < TTY_FLIPBUF_SIZE) {
814 tty->flip.count++;
815 tty->flip.flag_buf_ptr++;
816 tty->flip.char_buf_ptr++;
817 *tty->flip.flag_buf_ptr = TTY_OVERRUN;
818 }
819 }
820 } 805 }
821 806
822 tty->flip.flag_buf_ptr++; 807 tty_insert_flip_char(tty, *(icom_port->recv_buf + offset + count - 1), flag);
823 tty->flip.char_buf_ptr++; 808
824 tty->flip.count++; 809 if (status & SA_FLAGS_OVERRUN)
825 ignore_char: 810 /*
826 icom_port->statStg->rcv[rcv_buff].flags = 0; 811 * Overrun is special, since it's
812 * reported immediately, and doesn't
813 * affect the current character
814 */
815 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
816ignore_char:
817 icom_port->statStg->rcv[rcv_buff].flags = 0;
827 icom_port->statStg->rcv[rcv_buff].leLength = 0; 818 icom_port->statStg->rcv[rcv_buff].leLength = 0;
828 icom_port->statStg->rcv[rcv_buff].WorkingLength = 819 icom_port->statStg->rcv[rcv_buff].WorkingLength =
829 (unsigned short int) cpu_to_le16(RCV_BUFF_SZ); 820 (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 83c4c1216587..5c098be9346b 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)
256 error_return: 256 error_return:
257 tty_insert_flip_char(tty, rx, flg); 257 tty_insert_flip_char(tty, rx, flg);
258 258
259 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
260 goto out;
261
262 ignore_char: 259 ignore_char:
263 rx = URXD0((u32)sport->port.membase); 260 rx = URXD0((u32)sport->port.membase);
264 } while(rx & URXD_CHARRDY); 261 } while(rx & URXD_CHARRDY);
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index 771676abee60..1d85533d46d2 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)
2327 spin_lock_irqsave(&the_port->lock, pflags); 2327 spin_lock_irqsave(&the_port->lock, pflags);
2328 tty = info->tty; 2328 tty = info->tty;
2329 2329
2330 if (request_count > TTY_FLIPBUF_SIZE - tty->flip.count) 2330 request_count = tty_buffer_request_room(tty, IOC4_MAX_CHARS - 2);
2331 request_count = TTY_FLIPBUF_SIZE - tty->flip.count;
2332 2331
2333 if (request_count > 0) { 2332 if (request_count > 0) {
2334 icount = &the_port->icount; 2333 icount = &the_port->icount;
2335 read_count = do_read(the_port, ch, request_count); 2334 read_count = do_read(the_port, ch, request_count);
2336 if (read_count > 0) { 2335 if (read_count > 0) {
2337 flip = 1; 2336 tty_insert_flip_string(tty, ch, read_count);
2338 memcpy(tty->flip.char_buf_ptr, ch, read_count);
2339 memset(tty->flip.flag_buf_ptr, TTY_NORMAL, read_count);
2340 tty->flip.char_buf_ptr += read_count;
2341 tty->flip.flag_buf_ptr += read_count;
2342 tty->flip.count += read_count;
2343 icount->rx += read_count; 2337 icount->rx += read_count;
2344 } 2338 }
2345 } 2339 }
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index ef132349f310..66f117d15065 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,
259 struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */ 259 struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */
260 260
261 while (1) { 261 while (1) {
262 unsigned char ch, r1; 262 unsigned char ch, r1, flag;
263
264 if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
265 tty->flip.work.func((void *)tty);
266 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
267 return; /* XXX Ignores SysRq when we need it most. Fix. */
268 }
269 263
270 r1 = read_zsreg(channel, R1); 264 r1 = read_zsreg(channel, R1);
271 if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) { 265 if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
@@ -303,8 +297,7 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
303 } 297 }
304 298
305 /* A real serial line, record the character and status. */ 299 /* A real serial line, record the character and status. */
306 *tty->flip.char_buf_ptr = ch; 300 flag = TTY_NORMAL;
307 *tty->flip.flag_buf_ptr = TTY_NORMAL;
308 up->port.icount.rx++; 301 up->port.icount.rx++;
309 if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) { 302 if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
310 if (r1 & BRK_ABRT) { 303 if (r1 & BRK_ABRT) {
@@ -321,28 +314,21 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
321 up->port.icount.overrun++; 314 up->port.icount.overrun++;
322 r1 &= up->port.read_status_mask; 315 r1 &= up->port.read_status_mask;
323 if (r1 & BRK_ABRT) 316 if (r1 & BRK_ABRT)
324 *tty->flip.flag_buf_ptr = TTY_BREAK; 317 flag = TTY_BREAK;
325 else if (r1 & PAR_ERR) 318 else if (r1 & PAR_ERR)
326 *tty->flip.flag_buf_ptr = TTY_PARITY; 319 flag = TTY_PARITY;
327 else if (r1 & CRC_ERR) 320 else if (r1 & CRC_ERR)
328 *tty->flip.flag_buf_ptr = TTY_FRAME; 321 flag = TTY_FRAME;
329 } 322 }
330 if (uart_handle_sysrq_char(&up->port, ch, regs)) 323 if (uart_handle_sysrq_char(&up->port, ch, regs))
331 goto next_char; 324 goto next_char;
332 325
333 if (up->port.ignore_status_mask == 0xff || 326 if (up->port.ignore_status_mask == 0xff ||
334 (r1 & up->port.ignore_status_mask) == 0) { 327 (r1 & up->port.ignore_status_mask) == 0)
335 tty->flip.flag_buf_ptr++; 328 tty_insert_flip_char(tty, ch, flag);
336 tty->flip.char_buf_ptr++; 329
337 tty->flip.count++; 330 if (r1 & Rx_OVR)
338 } 331 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
339 if ((r1 & Rx_OVR) &&
340 tty->flip.count < TTY_FLIPBUF_SIZE) {
341 *tty->flip.flag_buf_ptr = TTY_OVERRUN;
342 tty->flip.flag_buf_ptr++;
343 tty->flip.char_buf_ptr++;
344 tty->flip.count++;
345 }
346 next_char: 332 next_char:
347 ch = readb(&channel->control); 333 ch = readb(&channel->control);
348 ZSDELAY(); 334 ZSDELAY();
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index b0ecc7537ce5..b48066a64a7d 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,
331{ 331{
332 struct tty_struct *tty = up->port.info->tty; 332 struct tty_struct *tty = up->port.info->tty;
333 unsigned char ch; 333 unsigned char ch;
334 unsigned char flag;
334 int max_count = 256; 335 int max_count = 256;
335 336
336 do { 337 do {
337 if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
338 tty->flip.work.func((void *)tty);
339 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
340 return; // if TTY_DONT_FLIP is set
341 }
342 ch = sio_in(up, SIORXB); 338 ch = sio_in(up, SIORXB);
343 *tty->flip.char_buf_ptr = ch; 339 flag = TTY_NORMAL;
344 *tty->flip.flag_buf_ptr = TTY_NORMAL;
345 up->port.icount.rx++; 340 up->port.icount.rx++;
346 341
347 if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | 342 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,
380 375
381 if (*status & UART_LSR_BI) { 376 if (*status & UART_LSR_BI) {
382 DEBUG_INTR("handling break...."); 377 DEBUG_INTR("handling break....");
383 *tty->flip.flag_buf_ptr = TTY_BREAK; 378 flag = TTY_BREAK;
384 } else if (*status & UART_LSR_PE) 379 } else if (*status & UART_LSR_PE)
385 *tty->flip.flag_buf_ptr = TTY_PARITY; 380 flag = TTY_PARITY;
386 else if (*status & UART_LSR_FE) 381 else if (*status & UART_LSR_FE)
387 *tty->flip.flag_buf_ptr = TTY_FRAME; 382 flag = TTY_FRAME;
388 } 383 }
389 if (uart_handle_sysrq_char(&up->port, ch, regs)) 384 if (uart_handle_sysrq_char(&up->port, ch, regs))
390 goto ignore_char; 385 goto ignore_char;
391 if ((*status & up->port.ignore_status_mask) == 0) { 386 if ((*status & up->port.ignore_status_mask) == 0)
392 tty->flip.flag_buf_ptr++; 387 tty_insert_flip_char(tty, ch, flag);
393 tty->flip.char_buf_ptr++; 388
394 tty->flip.count++; 389 if (*status & UART_LSR_OE) {
395 }
396 if ((*status & UART_LSR_OE) &&
397 tty->flip.count < TTY_FLIPBUF_SIZE) {
398 /* 390 /*
399 * Overrun is special, since it's reported 391 * Overrun is special, since it's reported
400 * immediately, and doesn't affect the current 392 * immediately, and doesn't affect the current
401 * character. 393 * character.
402 */ 394 */
403 *tty->flip.flag_buf_ptr = TTY_OVERRUN; 395 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
404 tty->flip.flag_buf_ptr++;
405 tty->flip.char_buf_ptr++;
406 tty->flip.count++;
407 } 396 }
408 ignore_char: 397 ignore_char:
409 *status = serial_in(up, UART_LSR); 398 *status = serial_in(up, UART_LSR);
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 47f7404cb045..f2a51e61eec7 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -313,7 +313,7 @@ static inline void receive_chars(struct mcf_serial *info)
313{ 313{
314 volatile unsigned char *uartp; 314 volatile unsigned char *uartp;
315 struct tty_struct *tty = info->tty; 315 struct tty_struct *tty = info->tty;
316 unsigned char status, ch; 316 unsigned char status, ch, flag;
317 317
318 if (!tty) 318 if (!tty)
319 return; 319 return;
@@ -321,10 +321,6 @@ static inline void receive_chars(struct mcf_serial *info)
321 uartp = info->addr; 321 uartp = info->addr;
322 322
323 while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) { 323 while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) {
324
325 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
326 break;
327
328 ch = uartp[MCFUART_URB]; 324 ch = uartp[MCFUART_URB];
329 info->stats.rx++; 325 info->stats.rx++;
330 326
@@ -335,29 +331,24 @@ static inline void receive_chars(struct mcf_serial *info)
335 } 331 }
336#endif 332#endif
337 333
338 tty->flip.count++; 334 flag = TTY_NORMAL;
339 if (status & MCFUART_USR_RXERR) { 335 if (status & MCFUART_USR_RXERR) {
340 uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR; 336 uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR;
341 if (status & MCFUART_USR_RXBREAK) { 337 if (status & MCFUART_USR_RXBREAK) {
342 info->stats.rxbreak++; 338 info->stats.rxbreak++;
343 *tty->flip.flag_buf_ptr++ = TTY_BREAK; 339 flag = TTY_BREAK;
344 } else if (status & MCFUART_USR_RXPARITY) { 340 } else if (status & MCFUART_USR_RXPARITY) {
345 info->stats.rxparity++; 341 info->stats.rxparity++;
346 *tty->flip.flag_buf_ptr++ = TTY_PARITY; 342 flag = TTY_PARITY;
347 } else if (status & MCFUART_USR_RXOVERRUN) { 343 } else if (status & MCFUART_USR_RXOVERRUN) {
348 info->stats.rxoverrun++; 344 info->stats.rxoverrun++;
349 *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; 345 flag = TTY_OVERRUN;
350 } else if (status & MCFUART_USR_RXFRAMING) { 346 } else if (status & MCFUART_USR_RXFRAMING) {
351 info->stats.rxframing++; 347 info->stats.rxframing++;
352 *tty->flip.flag_buf_ptr++ = TTY_FRAME; 348 flag = TTY_FRAME;
353 } else {
354 /* This should never happen... */
355 *tty->flip.flag_buf_ptr++ = 0;
356 } 349 }
357 } else {
358 *tty->flip.flag_buf_ptr++ = 0;
359 } 350 }
360 *tty->flip.char_buf_ptr++ = ch; 351 tty_insert_flip_char(tty, ch, flag);
361 } 352 }
362 353
363 schedule_work(&tty->flip.work); 354 schedule_work(&tty->flip.work);
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 1288d6203e94..61dd17d7bace 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -405,17 +405,13 @@ static inline int
405mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs) 405mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs)
406{ 406{
407 struct tty_struct *tty = port->info->tty; 407 struct tty_struct *tty = port->info->tty;
408 unsigned char ch; 408 unsigned char ch, flag;
409 unsigned short status; 409 unsigned short status;
410 410
411 /* While we can read, do so ! */ 411 /* While we can read, do so ! */
412 while ( (status = in_be16(&PSC(port)->mpc52xx_psc_status)) & 412 while ( (status = in_be16(&PSC(port)->mpc52xx_psc_status)) &
413 MPC52xx_PSC_SR_RXRDY) { 413 MPC52xx_PSC_SR_RXRDY) {
414 414
415 /* If we are full, just stop reading */
416 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
417 break;
418
419 /* Get the char */ 415 /* Get the char */
420 ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8); 416 ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8);
421 417
@@ -428,45 +424,35 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs)
428#endif 424#endif
429 425
430 /* Store it */ 426 /* Store it */
431 *tty->flip.char_buf_ptr = ch; 427
432 *tty->flip.flag_buf_ptr = 0; 428 flag = TTY_NORMAL;
433 port->icount.rx++; 429 port->icount.rx++;
434 430
435 if ( status & (MPC52xx_PSC_SR_PE | 431 if ( status & (MPC52xx_PSC_SR_PE |
436 MPC52xx_PSC_SR_FE | 432 MPC52xx_PSC_SR_FE |
437 MPC52xx_PSC_SR_RB | 433 MPC52xx_PSC_SR_RB) ) {
438 MPC52xx_PSC_SR_OE) ) {
439 434
440 if (status & MPC52xx_PSC_SR_RB) { 435 if (status & MPC52xx_PSC_SR_RB) {
441 *tty->flip.flag_buf_ptr = TTY_BREAK; 436 flag = TTY_BREAK;
442 uart_handle_break(port); 437 uart_handle_break(port);
443 } else if (status & MPC52xx_PSC_SR_PE) 438 } else if (status & MPC52xx_PSC_SR_PE)
444 *tty->flip.flag_buf_ptr = TTY_PARITY; 439 flag = TTY_PARITY;
445 else if (status & MPC52xx_PSC_SR_FE) 440 else if (status & MPC52xx_PSC_SR_FE)
446 *tty->flip.flag_buf_ptr = TTY_FRAME; 441 flag = TTY_FRAME;
447 if (status & MPC52xx_PSC_SR_OE) {
448 /*
449 * Overrun is special, since it's
450 * reported immediately, and doesn't
451 * affect the current character
452 */
453 if (tty->flip.count < (TTY_FLIPBUF_SIZE-1)) {
454 tty->flip.flag_buf_ptr++;
455 tty->flip.char_buf_ptr++;
456 tty->flip.count++;
457 }
458 *tty->flip.flag_buf_ptr = TTY_OVERRUN;
459 }
460 442
461 /* Clear error condition */ 443 /* Clear error condition */
462 out_8(&PSC(port)->command,MPC52xx_PSC_RST_ERR_STAT); 444 out_8(&PSC(port)->command,MPC52xx_PSC_RST_ERR_STAT);
463 445
464 } 446 }
465 447 tty_insert_flip_char(tty, ch, flag);
466 tty->flip.char_buf_ptr++; 448 if (status & MPC52xx_PSC_SR_OE) {
467 tty->flip.flag_buf_ptr++; 449 /*
468 tty->flip.count++; 450 * Overrun is special, since it's
469 451 * reported immediately, and doesn't
452 * affect the current character
453 */
454 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
455 }
470 } 456 }
471 457
472 tty_flip_buffer_push(tty); 458 tty_flip_buffer_push(tty);
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index 8f83e4007ecd..0ca83ac31d07 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)
769 bytes_in = be16_to_cpu(rxre->bytecnt); 769 bytes_in = be16_to_cpu(rxre->bytecnt);
770 770
771 /* Following use of tty struct directly is deprecated */ 771 /* Following use of tty struct directly is deprecated */
772 if (unlikely((tty->flip.count + bytes_in) >= TTY_FLIPBUF_SIZE)){ 772 if (unlikely(tty_buffer_request_room(tty, bytes_in) < bytes_in)) {
773 if (tty->low_latency) 773 if (tty->low_latency)
774 tty_flip_buffer_push(tty); 774 tty_flip_buffer_push(tty);
775 /* 775 /*
776 * If this failed then we will throw awa the bytes 776 * If this failed then we will throw away the bytes
777 * but mst do so to clear interrupts. 777 * but must do so to clear interrupts.
778 */ 778 */
779 } 779 }
780 780
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index 7633132a10aa..4e49168c3176 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -223,11 +223,6 @@ static void mux_read(struct uart_port *port)
223 if (MUX_EOFIFO(data)) 223 if (MUX_EOFIFO(data))
224 break; 224 break;
225 225
226 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
227 continue;
228
229 *tty->flip.char_buf_ptr = data & 0xffu;
230 *tty->flip.flag_buf_ptr = TTY_NORMAL;
231 port->icount.rx++; 226 port->icount.rx++;
232 227
233 if (MUX_BREAK(data)) { 228 if (MUX_BREAK(data)) {
@@ -239,9 +234,7 @@ static void mux_read(struct uart_port *port)
239 if (uart_handle_sysrq_char(port, data & 0xffu, NULL)) 234 if (uart_handle_sysrq_char(port, data & 0xffu, NULL))
240 continue; 235 continue;
241 236
242 tty->flip.flag_buf_ptr++; 237 tty_insert_flip_char(tty, data & 0xFF, TTY_NORMAL);
243 tty->flip.char_buf_ptr++;
244 tty->flip.count++;
245 } 238 }
246 239
247 if (start_count != port->icount.rx) { 240 if (start_count != port->icount.rx) {
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index ea24129eb6b9..f330d6c0e0df 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -210,10 +210,9 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
210 struct pt_regs *regs) 210 struct pt_regs *regs)
211{ 211{
212 struct tty_struct *tty = NULL; 212 struct tty_struct *tty = NULL;
213 unsigned char ch, r1, drop, error; 213 unsigned char ch, r1, drop, error, flag;
214 int loops = 0; 214 int loops = 0;
215 215
216 retry:
217 /* The interrupt can be enabled when the port isn't open, typically 216 /* The interrupt can be enabled when the port isn't open, typically
218 * that happens when using one port is open and the other closed (stale 217 * that happens when using one port is open and the other closed (stale
219 * interrupt) or when one port is used as a console. 218 * interrupt) or when one port is used as a console.
@@ -246,20 +245,6 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
246 error = 0; 245 error = 0;
247 drop = 0; 246 drop = 0;
248 247
249 if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
250 /* Have to drop the lock here */
251 pmz_debug("pmz: flip overflow\n");
252 spin_unlock(&uap->port.lock);
253 tty->flip.work.func((void *)tty);
254 spin_lock(&uap->port.lock);
255 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
256 drop = 1;
257 if (ZS_IS_ASLEEP(uap))
258 return NULL;
259 if (!ZS_IS_OPEN(uap))
260 goto retry;
261 }
262
263 r1 = read_zsreg(uap, R1); 248 r1 = read_zsreg(uap, R1);
264 ch = read_zsdata(uap); 249 ch = read_zsdata(uap);
265 250
@@ -295,8 +280,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
295 if (drop) 280 if (drop)
296 goto next_char; 281 goto next_char;
297 282
298 *tty->flip.char_buf_ptr = ch; 283 flag = TTY_NORMAL;
299 *tty->flip.flag_buf_ptr = TTY_NORMAL;
300 uap->port.icount.rx++; 284 uap->port.icount.rx++;
301 285
302 if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) { 286 if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) {
@@ -316,26 +300,19 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
316 uap->port.icount.overrun++; 300 uap->port.icount.overrun++;
317 r1 &= uap->port.read_status_mask; 301 r1 &= uap->port.read_status_mask;
318 if (r1 & BRK_ABRT) 302 if (r1 & BRK_ABRT)
319 *tty->flip.flag_buf_ptr = TTY_BREAK; 303 flag = TTY_BREAK;
320 else if (r1 & PAR_ERR) 304 else if (r1 & PAR_ERR)
321 *tty->flip.flag_buf_ptr = TTY_PARITY; 305 flag = TTY_PARITY;
322 else if (r1 & CRC_ERR) 306 else if (r1 & CRC_ERR)
323 *tty->flip.flag_buf_ptr = TTY_FRAME; 307 flag = TTY_FRAME;
324 } 308 }
325 309
326 if (uap->port.ignore_status_mask == 0xff || 310 if (uap->port.ignore_status_mask == 0xff ||
327 (r1 & uap->port.ignore_status_mask) == 0) { 311 (r1 & uap->port.ignore_status_mask) == 0) {
328 tty->flip.flag_buf_ptr++; 312 tty_insert_flip_char(tty, ch, flag);
329 tty->flip.char_buf_ptr++;
330 tty->flip.count++;
331 }
332 if ((r1 & Rx_OVR) &&
333 tty->flip.count < TTY_FLIPBUF_SIZE) {
334 *tty->flip.flag_buf_ptr = TTY_OVERRUN;
335 tty->flip.flag_buf_ptr++;
336 tty->flip.char_buf_ptr++;
337 tty->flip.count++;
338 } 313 }
314 if (r1 & Rx_OVR)
315 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
339 next_char: 316 next_char:
340 /* We can get stuck in an infinite loop getting char 0 when the 317 /* We can get stuck in an infinite loop getting char 0 when the
341 * line is in a wrong HW state, we break that here. 318 * line is in a wrong HW state, we break that here.
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index cc998b99a19f..10535f00301f 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)
107 int max_count = 256; 107 int max_count = 256;
108 108
109 do { 109 do {
110 if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
111 if (tty->low_latency)
112 tty_flip_buffer_push(tty);
113 /*
114 * If this failed then we will throw away the
115 * bytes but must do so to clear interrupts
116 */
117 }
118 ch = serial_in(up, UART_RX); 110 ch = serial_in(up, UART_RX);
119 flag = TTY_NORMAL; 111 flag = TTY_NORMAL;
120 up->port.icount.rx++; 112 up->port.icount.rx++;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index fe83ce6fef52..eb4883efb7c6 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)
323 if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0) 323 if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
324 break; 324 break;
325 325
326 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
327 if (tty->low_latency)
328 tty_flip_buffer_push(tty);
329
330 /*
331 * If this failed then we will throw away the
332 * bytes but must do so to clear interrupts
333 */
334 }
335
336 uerstat = rd_regl(port, S3C2410_UERSTAT); 326 uerstat = rd_regl(port, S3C2410_UERSTAT);
337 ch = rd_regb(port, S3C2410_URXH); 327 ch = rd_regb(port, S3C2410_URXH);
338 328
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 25a086458ab9..1bd93168f504 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)
201 while (status & UTSR1_TO_SM(UTSR1_RNE)) { 201 while (status & UTSR1_TO_SM(UTSR1_RNE)) {
202 ch = UART_GET_CHAR(sport); 202 ch = UART_GET_CHAR(sport);
203 203
204 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
205 goto ignore_char;
206 sport->port.icount.rx++; 204 sport->port.icount.rx++;
207 205
208 flg = TTY_NORMAL; 206 flg = TTY_NORMAL;
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index d01dbe5da3b9..d4a1f0e798c1 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -148,15 +148,6 @@ lh7a40xuart_rx_chars (struct uart_port* port)
148 unsigned int data, flag;/* Received data and status */ 148 unsigned int data, flag;/* Received data and status */
149 149
150 while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) { 150 while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
151 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
152 if (tty->low_latency)
153 tty_flip_buffer_push(tty);
154 /*
155 * If this failed then we will throw away the
156 * bytes but must do so to clear interrupts
157 */
158 }
159
160 data = UR (port, UART_R_DATA); 151 data = UR (port, UART_R_DATA);
161 flag = TTY_NORMAL; 152 flag = TTY_NORMAL;
162 ++port->icount.rx; 153 ++port->icount.rx;
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index 995d9dd9ddd5..fdd1f1915a42 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -303,17 +303,6 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
303 char flag; 303 char flag;
304 304
305 do { 305 do {
306 /* The following is not allowed by the tty layer and
307 unsafe. It should be fixed ASAP */
308 if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
309 if (tty->low_latency) {
310 spin_unlock(&up->port.lock);
311 tty_flip_buffer_push(tty);
312 spin_lock(&up->port.lock);
313 }
314 /* If this failed then we will throw away the
315 bytes but must do so to clear interrupts */
316 }
317 ch = sio_in(up, TXX9_SIRFIFO); 306 ch = sio_in(up, TXX9_SIRFIFO);
318 flag = TTY_NORMAL; 307 flag = TTY_NORMAL;
319 up->port.icount.rx++; 308 up->port.icount.rx++;
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 430754ebac8a..a9e070759628 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,
482 struct tty_struct *tty = port->info->tty; 482 struct tty_struct *tty = port->info->tty;
483 int i, count, copied = 0; 483 int i, count, copied = 0;
484 unsigned short status; 484 unsigned short status;
485 unsigned char flag;
485 486
486 status = sci_in(port, SCxSR); 487 status = sci_in(port, SCxSR);
487 if (!(status & SCxSR_RDxF(port))) 488 if (!(status & SCxSR_RDxF(port)))
@@ -499,8 +500,7 @@ static inline void sci_receive_chars(struct uart_port *port,
499#endif 500#endif
500 501
501 /* Don't copy more bytes than there is room for in the buffer */ 502 /* Don't copy more bytes than there is room for in the buffer */
502 if (tty->flip.count + count > TTY_FLIPBUF_SIZE) 503 count = tty_buffer_request_room(tty, count);
503 count = TTY_FLIPBUF_SIZE - tty->flip.count;
504 504
505 /* If for any reason we can't copy more data, we're done! */ 505 /* If for any reason we can't copy more data, we're done! */
506 if (count == 0) 506 if (count == 0)
@@ -512,8 +512,7 @@ static inline void sci_receive_chars(struct uart_port *port,
512 || uart_handle_sysrq_char(port, c, regs)) { 512 || uart_handle_sysrq_char(port, c, regs)) {
513 count = 0; 513 count = 0;
514 } else { 514 } else {
515 tty->flip.char_buf_ptr[0] = c; 515 tty_insert_flip_char(tty, c, TTY_NORMAL);
516 tty->flip.flag_buf_ptr[0] = TTY_NORMAL;
517 } 516 }
518 } else { 517 } else {
519 for (i=0; i<count; i++) { 518 for (i=0; i<count; i++) {
@@ -542,26 +541,21 @@ static inline void sci_receive_chars(struct uart_port *port,
542 } 541 }
543 542
544 /* Store data and status */ 543 /* Store data and status */
545 tty->flip.char_buf_ptr[i] = c;
546 if (status&SCxSR_FER(port)) { 544 if (status&SCxSR_FER(port)) {
547 tty->flip.flag_buf_ptr[i] = TTY_FRAME; 545 flag = TTY_FRAME;
548 pr_debug("sci: frame error\n"); 546 pr_debug("sci: frame error\n");
549 } else if (status&SCxSR_PER(port)) { 547 } else if (status&SCxSR_PER(port)) {
550 tty->flip.flag_buf_ptr[i] = TTY_PARITY; 548 flag = TTY_PARITY;
551 pr_debug("sci: parity error\n"); 549 pr_debug("sci: parity error\n");
552 } else { 550 } else
553 tty->flip.flag_buf_ptr[i] = TTY_NORMAL; 551 flag = TTY_NORMAL;
554 } 552 tty_insert_flip_char(tty, c, flag);
555 } 553 }
556 } 554 }
557 555
558 sci_in(port, SCxSR); /* dummy read */ 556 sci_in(port, SCxSR); /* dummy read */
559 sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); 557 sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
560 558
561 /* Update the kernel buffer end */
562 tty->flip.count += count;
563 tty->flip.char_buf_ptr += count;
564 tty->flip.flag_buf_ptr += count;
565 copied += count; 559 copied += count;
566 port->icount.rx += count; 560 port->icount.rx += count;
567 } 561 }
@@ -608,48 +602,45 @@ static inline int sci_handle_errors(struct uart_port *port)
608 unsigned short status = sci_in(port, SCxSR); 602 unsigned short status = sci_in(port, SCxSR);
609 struct tty_struct *tty = port->info->tty; 603 struct tty_struct *tty = port->info->tty;
610 604
611 if (status&SCxSR_ORER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) { 605 if (status&SCxSR_ORER(port)) {
612 /* overrun error */ 606 /* overrun error */
613 copied++; 607 if(tty_insert_flip_char(tty, 0, TTY_OVERRUN))
614 *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; 608 copied++;
615 pr_debug("sci: overrun error\n"); 609 pr_debug("sci: overrun error\n");
616 } 610 }
617 611
618 if (status&SCxSR_FER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) { 612 if (status&SCxSR_FER(port)) {
619 if (sci_rxd_in(port) == 0) { 613 if (sci_rxd_in(port) == 0) {
620 /* Notify of BREAK */ 614 /* Notify of BREAK */
621 struct sci_port * sci_port = (struct sci_port *)port; 615 struct sci_port * sci_port = (struct sci_port *)port;
622 if(!sci_port->break_flag) { 616 if(!sci_port->break_flag) {
623 sci_port->break_flag = 1; 617 sci_port->break_flag = 1;
624 sci_schedule_break_timer((struct sci_port *)port); 618 sci_schedule_break_timer((struct sci_port *)port);
625 /* Do sysrq handling. */ 619 /* Do sysrq handling. */
626 if(uart_handle_break(port)) { 620 if(uart_handle_break(port))
627 return 0; 621 return 0;
628 }
629 pr_debug("sci: BREAK detected\n"); 622 pr_debug("sci: BREAK detected\n");
630 copied++; 623 if(tty_insert_flip_char(tty, 0, TTY_BREAK))
631 *tty->flip.flag_buf_ptr++ = TTY_BREAK; 624 copied++;
632 } 625 }
633 } 626 }
634 else { 627 else {
635 /* frame error */ 628 /* frame error */
636 copied++; 629 if(tty_insert_flip_char(tty, 0, TTY_FRAME))
637 *tty->flip.flag_buf_ptr++ = TTY_FRAME; 630 copied++;
638 pr_debug("sci: frame error\n"); 631 pr_debug("sci: frame error\n");
639 } 632 }
640 } 633 }
641 634
642 if (status&SCxSR_PER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) { 635 if (status&SCxSR_PER(port)) {
636 if(tty_insert_flip_char(tty, 0, TTY_PARITY))
637 copied++;
643 /* parity error */ 638 /* parity error */
644 copied++;
645 *tty->flip.flag_buf_ptr++ = TTY_PARITY;
646 pr_debug("sci: parity error\n"); 639 pr_debug("sci: parity error\n");
647 } 640 }
648 641
649 if (copied) { 642 if (copied)
650 tty->flip.count += copied;
651 tty_flip_buffer_push(tty); 643 tty_flip_buffer_push(tty);
652 }
653 644
654 return copied; 645 return copied;
655} 646}
@@ -661,15 +652,14 @@ static inline int sci_handle_breaks(struct uart_port *port)
661 struct tty_struct *tty = port->info->tty; 652 struct tty_struct *tty = port->info->tty;
662 struct sci_port *s = &sci_ports[port->line]; 653 struct sci_port *s = &sci_ports[port->line];
663 654
664 if (!s->break_flag && status & SCxSR_BRK(port) && 655 if (!s->break_flag && status & SCxSR_BRK(port))
665 tty->flip.count < TTY_FLIPBUF_SIZE) {
666#if defined(CONFIG_CPU_SH3) 656#if defined(CONFIG_CPU_SH3)
667 /* Debounce break */ 657 /* Debounce break */
668 s->break_flag = 1; 658 s->break_flag = 1;
669#endif 659#endif
670 /* Notify of BREAK */ 660 /* Notify of BREAK */
671 copied++; 661 if(tty_insert_flip_char(tty, 0, TTY_BREAK))
672 *tty->flip.flag_buf_ptr++ = TTY_BREAK; 662 copied++;
673 pr_debug("sci: BREAK detected\n"); 663 pr_debug("sci: BREAK detected\n");
674 } 664 }
675 665
@@ -677,19 +667,15 @@ static inline int sci_handle_breaks(struct uart_port *port)
677 /* XXX: Handle SCIF overrun error */ 667 /* XXX: Handle SCIF overrun error */
678 if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) { 668 if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {
679 sci_out(port, SCLSR, 0); 669 sci_out(port, SCLSR, 0);
680 if(tty->flip.count<TTY_FLIPBUF_SIZE) { 670 if(tty_insert_flip_char(tty, 0, TTY_OVERRUN)) {
681 copied++; 671 copied++;
682 *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
683 pr_debug("sci: overrun error\n"); 672 pr_debug("sci: overrun error\n");
684 } 673 }
685 } 674 }
686#endif 675#endif
687 676
688 if (copied) { 677 if (copied)
689 tty->flip.count += copied;
690 tty_flip_buffer_push(tty); 678 tty_flip_buffer_push(tty);
691 }
692
693 return copied; 679 return copied;
694} 680}
695 681
@@ -732,12 +718,9 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr, struct pt_regs *regs)
732 struct tty_struct *tty = port->info->tty; 718 struct tty_struct *tty = port->info->tty;
733 719
734 sci_out(port, SCLSR, 0); 720 sci_out(port, SCLSR, 0);
735 if(tty->flip.count<TTY_FLIPBUF_SIZE) { 721 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
736 *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; 722 tty_flip_buffer_push(tty);
737 tty->flip.count++; 723 pr_debug("scif: overrun error\n");
738 tty_flip_buffer_push(tty);
739 pr_debug("scif: overrun error\n");
740 }
741 } 724 }
742#endif 725#endif
743 sci_rx_interrupt(irq, ptr, regs); 726 sci_rx_interrupt(irq, ptr, regs);
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 313f9df24a2d..5468e5a767e2 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,
519 519
520 /* record the character to pass up to the tty layer */ 520 /* record the character to pass up to the tty layer */
521 if (tty) { 521 if (tty) {
522 *tty->flip.char_buf_ptr = ch; 522 if(tty_insert_flip_char(tty, ch, TTY_NORMAL) == 0)
523 *tty->flip.flag_buf_ptr = TTY_NORMAL;
524 tty->flip.char_buf_ptr++;
525 tty->flip.count++;
526 if (tty->flip.count == TTY_FLIPBUF_SIZE)
527 break; 523 break;
528 } 524 }
529 port->sc_port.icount.rx++; 525 port->sc_port.icount.rx++;
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index ba9381fd3f2d..7e773ff76c61 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -159,21 +159,14 @@ receive_chars(struct uart_sunsab_port *up,
159 saw_console_brk = 1; 159 saw_console_brk = 1;
160 160
161 for (i = 0; i < count; i++) { 161 for (i = 0; i < count; i++) {
162 unsigned char ch = buf[i]; 162 unsigned char ch = buf[i], flag;
163 163
164 if (tty == NULL) { 164 if (tty == NULL) {
165 uart_handle_sysrq_char(&up->port, ch, regs); 165 uart_handle_sysrq_char(&up->port, ch, regs);
166 continue; 166 continue;
167 } 167 }
168 168
169 if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { 169 flag = TTY_NORMAL;
170 tty->flip.work.func((void *)tty);
171 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
172 return tty; // if TTY_DONT_FLIP is set
173 }
174
175 *tty->flip.char_buf_ptr = ch;
176 *tty->flip.flag_buf_ptr = TTY_NORMAL;
177 up->port.icount.rx++; 170 up->port.icount.rx++;
178 171
179 if (unlikely(stat->sreg.isr0 & (SAB82532_ISR0_PERR | 172 if (unlikely(stat->sreg.isr0 & (SAB82532_ISR0_PERR |
@@ -209,34 +202,21 @@ receive_chars(struct uart_sunsab_port *up,
209 stat->sreg.isr1 &= ((up->port.read_status_mask >> 8) & 0xff); 202 stat->sreg.isr1 &= ((up->port.read_status_mask >> 8) & 0xff);
210 203
211 if (stat->sreg.isr1 & SAB82532_ISR1_BRK) { 204 if (stat->sreg.isr1 & SAB82532_ISR1_BRK) {
212 *tty->flip.flag_buf_ptr = TTY_BREAK; 205 flag = TTY_BREAK;
213 } else if (stat->sreg.isr0 & SAB82532_ISR0_PERR) 206 } else if (stat->sreg.isr0 & SAB82532_ISR0_PERR)
214 *tty->flip.flag_buf_ptr = TTY_PARITY; 207 flag = TTY_PARITY;
215 else if (stat->sreg.isr0 & SAB82532_ISR0_FERR) 208 else if (stat->sreg.isr0 & SAB82532_ISR0_FERR)
216 *tty->flip.flag_buf_ptr = TTY_FRAME; 209 flag = TTY_FRAME;
217 } 210 }
218 211
219 if (uart_handle_sysrq_char(&up->port, ch, regs)) 212 if (uart_handle_sysrq_char(&up->port, ch, regs))
220 continue; 213 continue;
221 214
222 if ((stat->sreg.isr0 & (up->port.ignore_status_mask & 0xff)) == 0 && 215 if ((stat->sreg.isr0 & (up->port.ignore_status_mask & 0xff)) == 0 &&
223 (stat->sreg.isr1 & ((up->port.ignore_status_mask >> 8) & 0xff)) == 0){ 216 (stat->sreg.isr1 & ((up->port.ignore_status_mask >> 8) & 0xff)) == 0)
224 tty->flip.flag_buf_ptr++; 217 tty_insert_flip_char(tty, ch, flag);
225 tty->flip.char_buf_ptr++; 218 if (stat->sreg.isr0 & SAB82532_ISR0_RFO)
226 tty->flip.count++; 219 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
227 }
228 if ((stat->sreg.isr0 & SAB82532_ISR0_RFO) &&
229 tty->flip.count < TTY_FLIPBUF_SIZE) {
230 /*
231 * Overrun is special, since it's reported
232 * immediately, and doesn't affect the current
233 * character.
234 */
235 *tty->flip.flag_buf_ptr = TTY_OVERRUN;
236 tty->flip.flag_buf_ptr++;
237 tty->flip.char_buf_ptr++;
238 tty->flip.count++;
239 }
240 } 220 }
241 221
242 if (saw_console_brk) 222 if (saw_console_brk)
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index f0738533f39a..9a3665b34d97 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -323,19 +323,13 @@ static _INLINE_ struct tty_struct *
323receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs *regs) 323receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs *regs)
324{ 324{
325 struct tty_struct *tty = up->port.info->tty; 325 struct tty_struct *tty = up->port.info->tty;
326 unsigned char ch; 326 unsigned char ch, flag;
327 int max_count = 256; 327 int max_count = 256;
328 int saw_console_brk = 0; 328 int saw_console_brk = 0;
329 329
330 do { 330 do {
331 if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
332 tty->flip.work.func((void *)tty);
333 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
334 return tty; // if TTY_DONT_FLIP is set
335 }
336 ch = serial_inp(up, UART_RX); 331 ch = serial_inp(up, UART_RX);
337 *tty->flip.char_buf_ptr = ch; 332 flag = TTY_NORMAL;
338 *tty->flip.flag_buf_ptr = TTY_NORMAL;
339 up->port.icount.rx++; 333 up->port.icount.rx++;
340 334
341 if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | 335 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
377 } 371 }
378 372
379 if (*status & UART_LSR_BI) { 373 if (*status & UART_LSR_BI) {
380 *tty->flip.flag_buf_ptr = TTY_BREAK; 374 flag = TTY_BREAK;
381 } else if (*status & UART_LSR_PE) 375 } else if (*status & UART_LSR_PE)
382 *tty->flip.flag_buf_ptr = TTY_PARITY; 376 flag = TTY_PARITY;
383 else if (*status & UART_LSR_FE) 377 else if (*status & UART_LSR_FE)
384 *tty->flip.flag_buf_ptr = TTY_FRAME; 378 flag = TTY_FRAME;
385 } 379 }
386 if (uart_handle_sysrq_char(&up->port, ch, regs)) 380 if (uart_handle_sysrq_char(&up->port, ch, regs))
387 goto ignore_char; 381 goto ignore_char;
388 if ((*status & up->port.ignore_status_mask) == 0) { 382 if ((*status & up->port.ignore_status_mask) == 0)
389 tty->flip.flag_buf_ptr++; 383 tty_insert_flip_char(tty, ch, flag);
390 tty->flip.char_buf_ptr++; 384 if (*status & UART_LSR_OE)
391 tty->flip.count++;
392 }
393 if ((*status & UART_LSR_OE) &&
394 tty->flip.count < TTY_FLIPBUF_SIZE) {
395 /* 385 /*
396 * Overrun is special, since it's reported 386 * Overrun is special, since it's reported
397 * immediately, and doesn't affect the current 387 * immediately, and doesn't affect the current
398 * character. 388 * character.
399 */ 389 */
400 *tty->flip.flag_buf_ptr = TTY_OVERRUN; 390 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
401 tty->flip.flag_buf_ptr++;
402 tty->flip.char_buf_ptr++;
403 tty->flip.count++;
404 }
405 ignore_char: 391 ignore_char:
406 *status = serial_inp(up, UART_LSR); 392 *status = serial_inp(up, UART_LSR);
407 } while ((*status & UART_LSR_DR) && (max_count-- > 0)); 393 } while ((*status & UART_LSR_DR) && (max_count-- > 0));
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 7653d6cf05af..3c72484adea7 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -319,7 +319,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
319 struct pt_regs *regs) 319 struct pt_regs *regs)
320{ 320{
321 struct tty_struct *tty; 321 struct tty_struct *tty;
322 unsigned char ch, r1; 322 unsigned char ch, r1, flag;
323 323
324 tty = NULL; 324 tty = NULL;
325 if (up->port.info != NULL && /* Unopened serial console */ 325 if (up->port.info != NULL && /* Unopened serial console */
@@ -362,19 +362,8 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
362 continue; 362 continue;
363 } 363 }
364 364
365 if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
366 tty->flip.work.func((void *)tty);
367 /*
368 * The 8250 bails out of the loop here,
369 * but we need to read everything, or die.
370 */
371 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
372 continue;
373 }
374
375 /* A real serial line, record the character and status. */ 365 /* A real serial line, record the character and status. */
376 *tty->flip.char_buf_ptr = ch; 366 flag = TTY_NORMAL;
377 *tty->flip.flag_buf_ptr = TTY_NORMAL;
378 up->port.icount.rx++; 367 up->port.icount.rx++;
379 if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) { 368 if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
380 if (r1 & BRK_ABRT) { 369 if (r1 & BRK_ABRT) {
@@ -391,28 +380,21 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
391 up->port.icount.overrun++; 380 up->port.icount.overrun++;
392 r1 &= up->port.read_status_mask; 381 r1 &= up->port.read_status_mask;
393 if (r1 & BRK_ABRT) 382 if (r1 & BRK_ABRT)
394 *tty->flip.flag_buf_ptr = TTY_BREAK; 383 flag = TTY_BREAK;
395 else if (r1 & PAR_ERR) 384 else if (r1 & PAR_ERR)
396 *tty->flip.flag_buf_ptr = TTY_PARITY; 385 flag = TTY_PARITY;
397 else if (r1 & CRC_ERR) 386 else if (r1 & CRC_ERR)
398 *tty->flip.flag_buf_ptr = TTY_FRAME; 387 flag = TTY_FRAME;
399 } 388 }
400 if (uart_handle_sysrq_char(&up->port, ch, regs)) 389 if (uart_handle_sysrq_char(&up->port, ch, regs))
401 continue; 390 continue;
402 391
403 if (up->port.ignore_status_mask == 0xff || 392 if (up->port.ignore_status_mask == 0xff ||
404 (r1 & up->port.ignore_status_mask) == 0) { 393 (r1 & up->port.ignore_status_mask) == 0) {
405 tty->flip.flag_buf_ptr++; 394 tty_insert_flip_char(tty, ch, flag);
406 tty->flip.char_buf_ptr++;
407 tty->flip.count++;
408 }
409 if ((r1 & Rx_OVR) &&
410 tty->flip.count < TTY_FLIPBUF_SIZE) {
411 *tty->flip.flag_buf_ptr = TTY_OVERRUN;
412 tty->flip.flag_buf_ptr++;
413 tty->flip.char_buf_ptr++;
414 tty->flip.count++;
415 } 395 }
396 if (r1 & Rx_OVR)
397 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
416 } 398 }
417 399
418 return tty; 400 return tty;
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index 865d4dea65df..0a28deeb098d 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -371,11 +371,6 @@ static inline void receive_chars(struct uart_port *port, uint8_t *status,
371 lsr = *status; 371 lsr = *status;
372 372
373 do { 373 do {
374 if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
375 if (tty->low_latency)
376 tty_flip_buffer_push(tty);
377 }
378
379 ch = siu_read(port, UART_RX); 374 ch = siu_read(port, UART_RX);
380 port->icount.rx++; 375 port->icount.rx++;
381 flag = TTY_NORMAL; 376 flag = TTY_NORMAL;