diff options
author | V. Ananda Krishnan <mansarov@us.ibm.com> | 2006-02-03 06:04:30 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-03 11:32:07 -0500 |
commit | 0a577ce34f703c885f807e2abc77dff02c7857af (patch) | |
tree | a2bfd15ca0ffe4ecc65c769008c9bfa8e0b107c9 /drivers/serial | |
parent | 7d95c8f27d9be65bf160f1edaf653d33dfceb58c (diff) |
[PATCH] jsm: update for tty buffering revamp
Signed-off-by: V. Ananda Krishnan <mansarov@us.ibm.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
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/Kconfig | 28 | ||||
-rw-r--r-- | drivers/serial/jsm/jsm_tty.c | 208 |
2 files changed, 79 insertions, 157 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 0d38f0f2ae29..ee4265d7a8c9 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -892,20 +892,20 @@ config SERIAL_VR41XX_CONSOLE | |||
892 | a console on a serial port, say Y. Otherwise, say N. | 892 | a console on a serial port, say Y. Otherwise, say N. |
893 | 893 | ||
894 | config SERIAL_JSM | 894 | config SERIAL_JSM |
895 | tristate "Digi International NEO PCI Support" | 895 | tristate "Digi International NEO PCI Support" |
896 | depends on PCI && BROKEN | 896 | depends on PCI |
897 | select SERIAL_CORE | 897 | select SERIAL_CORE |
898 | help | 898 | help |
899 | This is a driver for Digi International's Neo series | 899 | This is a driver for Digi International's Neo series |
900 | of cards which provide multiple serial ports. You would need | 900 | of cards which provide multiple serial ports. You would need |
901 | something like this to connect more than two modems to your Linux | 901 | something like this to connect more than two modems to your Linux |
902 | box, for instance in order to become a dial-in server. This driver | 902 | box, for instance in order to become a dial-in server. This driver |
903 | supports PCI boards only. | 903 | supports PCI boards only. |
904 | If you have a card like this, say Y here and read the file | 904 | If you have a card like this, say Y here and read the file |
905 | <file:Documentation/jsm.txt>. | 905 | <file:Documentation/jsm.txt>. |
906 | 906 | ||
907 | To compile this driver as a module, choose M here: the | 907 | To compile this driver as a module, choose M here: the |
908 | module will be called jsm. | 908 | module will be called jsm. |
909 | 909 | ||
910 | config SERIAL_SGI_IOC4 | 910 | config SERIAL_SGI_IOC4 |
911 | tristate "SGI IOC4 controller serial support" | 911 | tristate "SGI IOC4 controller serial support" |
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 6fa0d62d6f68..07bf28ca3302 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
@@ -20,8 +20,10 @@ | |||
20 | * | 20 | * |
21 | * Contact Information: | 21 | * Contact Information: |
22 | * Scott H Kilau <Scott_Kilau@digi.com> | 22 | * Scott H Kilau <Scott_Kilau@digi.com> |
23 | * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com> | 23 | * Ananda Venkatarman <mansarov@us.ibm.com> |
24 | * | 24 | * Modifications: |
25 | * 01/19/06: changed jsm_input routine to use the dynamically allocated | ||
26 | * tty_buffer changes. Contributors: Scott Kilau and Ananda V. | ||
25 | ***********************************************************************/ | 27 | ***********************************************************************/ |
26 | #include <linux/tty.h> | 28 | #include <linux/tty.h> |
27 | #include <linux/tty_flip.h> | 29 | #include <linux/tty_flip.h> |
@@ -497,16 +499,16 @@ void jsm_input(struct jsm_channel *ch) | |||
497 | { | 499 | { |
498 | struct jsm_board *bd; | 500 | struct jsm_board *bd; |
499 | struct tty_struct *tp; | 501 | struct tty_struct *tp; |
502 | struct tty_ldisc *ld; | ||
500 | u32 rmask; | 503 | u32 rmask; |
501 | u16 head; | 504 | u16 head; |
502 | u16 tail; | 505 | u16 tail; |
503 | int data_len; | 506 | int data_len; |
504 | unsigned long lock_flags; | 507 | unsigned long lock_flags; |
505 | int flip_len; | 508 | int flip_len = 0; |
506 | int len = 0; | 509 | int len = 0; |
507 | int n = 0; | 510 | int n = 0; |
508 | char *buf = NULL; | 511 | char *buf = NULL; |
509 | char *buf2 = NULL; | ||
510 | int s = 0; | 512 | int s = 0; |
511 | int i = 0; | 513 | int i = 0; |
512 | 514 | ||
@@ -574,56 +576,50 @@ void jsm_input(struct jsm_channel *ch) | |||
574 | 576 | ||
575 | /* | 577 | /* |
576 | * If the rxbuf is empty and we are not throttled, put as much | 578 | * If the rxbuf is empty and we are not throttled, put as much |
577 | * as we can directly into the linux TTY flip buffer. | 579 | * as we can directly into the linux TTY buffer. |
578 | * The jsm_rawreadok case takes advantage of carnal knowledge that | ||
579 | * the char_buf and the flag_buf are next to each other and | ||
580 | * are each of (2 * TTY_FLIPBUF_SIZE) size. | ||
581 | * | 580 | * |
582 | * NOTE: if(!tty->real_raw), the call to ldisc.receive_buf | ||
583 | *actually still uses the flag buffer, so you can't | ||
584 | *use it for input data | ||
585 | */ | 581 | */ |
586 | if (jsm_rawreadok) { | 582 | flip_len = TTY_FLIPBUF_SIZE; |
587 | if (tp->real_raw) | ||
588 | flip_len = MYFLIPLEN; | ||
589 | else | ||
590 | flip_len = 2 * TTY_FLIPBUF_SIZE; | ||
591 | } else | ||
592 | flip_len = TTY_FLIPBUF_SIZE - tp->flip.count; | ||
593 | 583 | ||
594 | len = min(data_len, flip_len); | 584 | len = min(data_len, flip_len); |
595 | len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt); | 585 | len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt); |
586 | ld = tty_ldisc_ref(tp); | ||
596 | 587 | ||
597 | if (len <= 0) { | 588 | /* |
598 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | 589 | * If the DONT_FLIP flag is on, don't flush our buffer, and act |
599 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n"); | 590 | * like the ld doesn't have any space to put the data right now. |
600 | return; | 591 | */ |
601 | } | 592 | if (test_bit(TTY_DONT_FLIP, &tp->flags)) |
593 | len = 0; | ||
602 | 594 | ||
603 | /* | 595 | /* |
604 | * If we're bypassing flip buffers on rx, we can blast it | 596 | * If we were unable to get a reference to the ld, |
605 | * right into the beginning of the buffer. | 597 | * don't flush our buffer, and act like the ld doesn't |
598 | * have any space to put the data right now. | ||
606 | */ | 599 | */ |
607 | if (jsm_rawreadok) { | 600 | if (!ld) { |
608 | if (tp->real_raw) { | 601 | len = 0; |
609 | if (ch->ch_flags & CH_FLIPBUF_IN_USE) { | ||
610 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, | ||
611 | "JSM - FLIPBUF in use. delaying input\n"); | ||
612 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
613 | return; | ||
614 | } | ||
615 | ch->ch_flags |= CH_FLIPBUF_IN_USE; | ||
616 | buf = ch->ch_bd->flipbuf; | ||
617 | buf2 = NULL; | ||
618 | } else { | ||
619 | buf = tp->flip.char_buf; | ||
620 | buf2 = tp->flip.flag_buf; | ||
621 | } | ||
622 | } else { | 602 | } else { |
623 | buf = tp->flip.char_buf_ptr; | 603 | /* |
624 | buf2 = tp->flip.flag_buf_ptr; | 604 | * If ld doesn't have a pointer to a receive_buf function, |
605 | * flush the data, then act like the ld doesn't have any | ||
606 | * space to put the data right now. | ||
607 | */ | ||
608 | if (!ld->receive_buf) { | ||
609 | ch->ch_r_head = ch->ch_r_tail; | ||
610 | len = 0; | ||
611 | } | ||
625 | } | 612 | } |
626 | 613 | ||
614 | if (len <= 0) { | ||
615 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
616 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n"); | ||
617 | if (ld) | ||
618 | tty_ldisc_deref(ld); | ||
619 | return; | ||
620 | } | ||
621 | |||
622 | len = tty_buffer_request_room(tp, len); | ||
627 | n = len; | 623 | n = len; |
628 | 624 | ||
629 | /* | 625 | /* |
@@ -638,121 +634,47 @@ void jsm_input(struct jsm_channel *ch) | |||
638 | if (s <= 0) | 634 | if (s <= 0) |
639 | break; | 635 | break; |
640 | 636 | ||
641 | memcpy(buf, ch->ch_rqueue + tail, s); | 637 | /* |
642 | 638 | * If conditions are such that ld needs to see all | |
643 | /* buf2 is only set when port isn't raw */ | 639 | * UART errors, we will have to walk each character |
644 | if (buf2) | 640 | * and error byte and send them to the buffer one at |
645 | memcpy(buf2, ch->ch_equeue + tail, s); | 641 | * a time. |
646 | 642 | */ | |
647 | tail += s; | ||
648 | buf += s; | ||
649 | if (buf2) | ||
650 | buf2 += s; | ||
651 | n -= s; | ||
652 | /* Flip queue if needed */ | ||
653 | tail &= rmask; | ||
654 | } | ||
655 | 643 | ||
656 | /* | ||
657 | * In high performance mode, we don't have to update | ||
658 | * flag_buf or any of the counts or pointers into flip buf. | ||
659 | */ | ||
660 | if (!jsm_rawreadok) { | ||
661 | if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { | 644 | if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { |
662 | for (i = 0; i < len; i++) { | 645 | for (i = 0; i < s; i++) { |
663 | /* | 646 | /* |
664 | * Give the Linux ld the flags in the | 647 | * Give the Linux ld the flags in the |
665 | * format it likes. | 648 | * format it likes. |
666 | */ | 649 | */ |
667 | if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI) | 650 | if (*(ch->ch_equeue +tail +i) & UART_LSR_BI) |
668 | tp->flip.flag_buf_ptr[i] = TTY_BREAK; | 651 | tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_BREAK); |
669 | else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE) | 652 | else if (*(ch->ch_equeue +tail +i) & UART_LSR_PE) |
670 | tp->flip.flag_buf_ptr[i] = TTY_PARITY; | 653 | tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_PARITY); |
671 | else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE) | 654 | else if (*(ch->ch_equeue +tail +i) & UART_LSR_FE) |
672 | tp->flip.flag_buf_ptr[i] = TTY_FRAME; | 655 | tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_FRAME); |
673 | else | 656 | else |
674 | tp->flip.flag_buf_ptr[i] = TTY_NORMAL; | 657 | tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_NORMAL); |
675 | } | 658 | } |
676 | } else { | 659 | } else { |
677 | memset(tp->flip.flag_buf_ptr, 0, len); | 660 | tty_insert_flip_string(tp, ch->ch_rqueue + tail, s) ; |
678 | } | 661 | } |
679 | 662 | tail += s; | |
680 | tp->flip.char_buf_ptr += len; | 663 | n -= s; |
681 | tp->flip.flag_buf_ptr += len; | 664 | /* Flip queue if needed */ |
682 | tp->flip.count += len; | 665 | tail &= rmask; |
683 | } | ||
684 | else if (!tp->real_raw) { | ||
685 | if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { | ||
686 | for (i = 0; i < len; i++) { | ||
687 | /* | ||
688 | * Give the Linux ld the flags in the | ||
689 | * format it likes. | ||
690 | */ | ||
691 | if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI) | ||
692 | tp->flip.flag_buf_ptr[i] = TTY_BREAK; | ||
693 | else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE) | ||
694 | tp->flip.flag_buf_ptr[i] = TTY_PARITY; | ||
695 | else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE) | ||
696 | tp->flip.flag_buf_ptr[i] = TTY_FRAME; | ||
697 | else | ||
698 | tp->flip.flag_buf_ptr[i] = TTY_NORMAL; | ||
699 | } | ||
700 | } else | ||
701 | memset(tp->flip.flag_buf, 0, len); | ||
702 | } | 666 | } |
703 | 667 | ||
704 | /* | 668 | ch->ch_r_tail = tail & rmask; |
705 | * If we're doing raw reads, jam it right into the | 669 | ch->ch_e_tail = tail & rmask; |
706 | * line disc bypassing the flip buffers. | 670 | jsm_check_queue_flow_control(ch); |
707 | */ | 671 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); |
708 | if (jsm_rawreadok) { | ||
709 | if (tp->real_raw) { | ||
710 | ch->ch_r_tail = tail & rmask; | ||
711 | ch->ch_e_tail = tail & rmask; | ||
712 | |||
713 | jsm_check_queue_flow_control(ch); | ||
714 | |||
715 | /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */ | ||
716 | 672 | ||
717 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | 673 | /* Tell the tty layer its okay to "eat" the data now */ |
674 | tty_flip_buffer_push(tp); | ||
718 | 675 | ||
719 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, | 676 | if (ld) |
720 | "jsm_input. %d real_raw len:%d calling receive_buf for board %d\n", | 677 | tty_ldisc_deref(ld); |
721 | __LINE__, len, ch->ch_bd->boardnum); | ||
722 | tp->ldisc.receive_buf(tp, ch->ch_bd->flipbuf, NULL, len); | ||
723 | |||
724 | /* Allow use of channel flip buffer again */ | ||
725 | spin_lock_irqsave(&ch->ch_lock, lock_flags); | ||
726 | ch->ch_flags &= ~CH_FLIPBUF_IN_USE; | ||
727 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
728 | |||
729 | } else { | ||
730 | ch->ch_r_tail = tail & rmask; | ||
731 | ch->ch_e_tail = tail & rmask; | ||
732 | |||
733 | jsm_check_queue_flow_control(ch); | ||
734 | |||
735 | /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */ | ||
736 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
737 | |||
738 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, | ||
739 | "jsm_input. %d not real_raw len:%d calling receive_buf for board %d\n", | ||
740 | __LINE__, len, ch->ch_bd->boardnum); | ||
741 | |||
742 | tp->ldisc.receive_buf(tp, tp->flip.char_buf, tp->flip.flag_buf, len); | ||
743 | } | ||
744 | } else { | ||
745 | ch->ch_r_tail = tail & rmask; | ||
746 | ch->ch_e_tail = tail & rmask; | ||
747 | |||
748 | jsm_check_queue_flow_control(ch); | ||
749 | |||
750 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
751 | |||
752 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, | ||
753 | "jsm_input. %d not jsm_read raw okay scheduling flip\n", __LINE__); | ||
754 | tty_schedule_flip(tp); | ||
755 | } | ||
756 | 678 | ||
757 | jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n"); | 679 | jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n"); |
758 | } | 680 | } |