diff options
Diffstat (limited to 'drivers/serial/sh-sci.c')
-rw-r--r-- | drivers/serial/sh-sci.c | 81 |
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); |