aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/sh-sci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial/sh-sci.c')
-rw-r--r--drivers/serial/sh-sci.c81
1 files changed, 32 insertions, 49 deletions
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);