diff options
Diffstat (limited to 'drivers/char/stallion.c')
-rw-r--r-- | drivers/char/stallion.c | 169 |
1 files changed, 43 insertions, 126 deletions
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 963b03fb29e5..e1e0dd89ac9a 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -130,6 +130,8 @@ static char stl_unwanted[SC26198_RXFIFOSIZE]; | |||
130 | static DEFINE_MUTEX(stl_brdslock); | 130 | static DEFINE_MUTEX(stl_brdslock); |
131 | static struct stlbrd *stl_brds[STL_MAXBRDS]; | 131 | static struct stlbrd *stl_brds[STL_MAXBRDS]; |
132 | 132 | ||
133 | static const struct tty_port_operations stl_port_ops; | ||
134 | |||
133 | /* | 135 | /* |
134 | * Per board state flags. Used with the state field of the board struct. | 136 | * Per board state flags. Used with the state field of the board struct. |
135 | * Not really much here! | 137 | * Not really much here! |
@@ -407,7 +409,6 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns | |||
407 | static int stl_brdinit(struct stlbrd *brdp); | 409 | static int stl_brdinit(struct stlbrd *brdp); |
408 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); | 410 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); |
409 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); | 411 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); |
410 | static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, struct file *filp); | ||
411 | 412 | ||
412 | /* | 413 | /* |
413 | * CD1400 uart specific handling functions. | 414 | * CD1400 uart specific handling functions. |
@@ -703,8 +704,9 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
703 | { | 704 | { |
704 | struct stlport *portp; | 705 | struct stlport *portp; |
705 | struct stlbrd *brdp; | 706 | struct stlbrd *brdp; |
707 | struct tty_port *port; | ||
706 | unsigned int minordev, brdnr, panelnr; | 708 | unsigned int minordev, brdnr, panelnr; |
707 | int portnr, rc; | 709 | int portnr; |
708 | 710 | ||
709 | pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name); | 711 | pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name); |
710 | 712 | ||
@@ -715,6 +717,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
715 | brdp = stl_brds[brdnr]; | 717 | brdp = stl_brds[brdnr]; |
716 | if (brdp == NULL) | 718 | if (brdp == NULL) |
717 | return -ENODEV; | 719 | return -ENODEV; |
720 | |||
718 | minordev = MINOR2PORT(minordev); | 721 | minordev = MINOR2PORT(minordev); |
719 | for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) { | 722 | for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) { |
720 | if (brdp->panels[panelnr] == NULL) | 723 | if (brdp->panels[panelnr] == NULL) |
@@ -731,16 +734,17 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
731 | portp = brdp->panels[panelnr]->ports[portnr]; | 734 | portp = brdp->panels[panelnr]->ports[portnr]; |
732 | if (portp == NULL) | 735 | if (portp == NULL) |
733 | return -ENODEV; | 736 | return -ENODEV; |
737 | port = &portp->port; | ||
734 | 738 | ||
735 | /* | 739 | /* |
736 | * On the first open of the device setup the port hardware, and | 740 | * On the first open of the device setup the port hardware, and |
737 | * initialize the per port data structure. | 741 | * initialize the per port data structure. |
738 | */ | 742 | */ |
739 | tty_port_tty_set(&portp->port, tty); | 743 | tty_port_tty_set(port, tty); |
740 | tty->driver_data = portp; | 744 | tty->driver_data = portp; |
741 | portp->port.count++; | 745 | port->count++; |
742 | 746 | ||
743 | if ((portp->port.flags & ASYNC_INITIALIZED) == 0) { | 747 | if ((port->flags & ASYNC_INITIALIZED) == 0) { |
744 | if (!portp->tx.buf) { | 748 | if (!portp->tx.buf) { |
745 | portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); | 749 | portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); |
746 | if (!portp->tx.buf) | 750 | if (!portp->tx.buf) |
@@ -754,91 +758,24 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
754 | stl_enablerxtx(portp, 1, 1); | 758 | stl_enablerxtx(portp, 1, 1); |
755 | stl_startrxtx(portp, 1, 0); | 759 | stl_startrxtx(portp, 1, 0); |
756 | clear_bit(TTY_IO_ERROR, &tty->flags); | 760 | clear_bit(TTY_IO_ERROR, &tty->flags); |
757 | portp->port.flags |= ASYNC_INITIALIZED; | 761 | port->flags |= ASYNC_INITIALIZED; |
758 | } | ||
759 | |||
760 | /* | ||
761 | * Check if this port is in the middle of closing. If so then wait | ||
762 | * until it is closed then return error status, based on flag settings. | ||
763 | * The sleep here does not need interrupt protection since the wakeup | ||
764 | * for it is done with the same context. | ||
765 | */ | ||
766 | if (portp->port.flags & ASYNC_CLOSING) { | ||
767 | interruptible_sleep_on(&portp->port.close_wait); | ||
768 | if (portp->port.flags & ASYNC_HUP_NOTIFY) | ||
769 | return -EAGAIN; | ||
770 | return -ERESTARTSYS; | ||
771 | } | 762 | } |
772 | 763 | return tty_port_block_til_ready(port, tty, filp); | |
773 | /* | ||
774 | * Based on type of open being done check if it can overlap with any | ||
775 | * previous opens still in effect. If we are a normal serial device | ||
776 | * then also we might have to wait for carrier. | ||
777 | */ | ||
778 | if (!(filp->f_flags & O_NONBLOCK)) | ||
779 | if ((rc = stl_waitcarrier(tty, portp, filp)) != 0) | ||
780 | return rc; | ||
781 | |||
782 | portp->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
783 | |||
784 | return 0; | ||
785 | } | 764 | } |
786 | 765 | ||
787 | /*****************************************************************************/ | 766 | /*****************************************************************************/ |
788 | 767 | ||
789 | /* | 768 | static int stl_carrier_raised(struct tty_port *port) |
790 | * Possibly need to wait for carrier (DCD signal) to come high. Say | ||
791 | * maybe because if we are clocal then we don't need to wait... | ||
792 | */ | ||
793 | |||
794 | static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, | ||
795 | struct file *filp) | ||
796 | { | 769 | { |
797 | unsigned long flags; | 770 | struct stlport *portp = container_of(port, struct stlport, port); |
798 | int rc, doclocal; | 771 | return (portp->sigs & TIOCM_CD) ? 1 : 0; |
799 | 772 | } | |
800 | pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp); | ||
801 | |||
802 | rc = 0; | ||
803 | doclocal = 0; | ||
804 | |||
805 | spin_lock_irqsave(&stallion_lock, flags); | ||
806 | |||
807 | if (tty->termios->c_cflag & CLOCAL) | ||
808 | doclocal++; | ||
809 | |||
810 | portp->openwaitcnt++; | ||
811 | if (! tty_hung_up_p(filp)) | ||
812 | portp->port.count--; | ||
813 | |||
814 | for (;;) { | ||
815 | /* Takes brd_lock internally */ | ||
816 | stl_setsignals(portp, 1, 1); | ||
817 | if (tty_hung_up_p(filp) || | ||
818 | ((portp->port.flags & ASYNC_INITIALIZED) == 0)) { | ||
819 | if (portp->port.flags & ASYNC_HUP_NOTIFY) | ||
820 | rc = -EBUSY; | ||
821 | else | ||
822 | rc = -ERESTARTSYS; | ||
823 | break; | ||
824 | } | ||
825 | if (((portp->port.flags & ASYNC_CLOSING) == 0) && | ||
826 | (doclocal || (portp->sigs & TIOCM_CD))) | ||
827 | break; | ||
828 | if (signal_pending(current)) { | ||
829 | rc = -ERESTARTSYS; | ||
830 | break; | ||
831 | } | ||
832 | /* FIXME */ | ||
833 | interruptible_sleep_on(&portp->port.open_wait); | ||
834 | } | ||
835 | |||
836 | if (! tty_hung_up_p(filp)) | ||
837 | portp->port.count++; | ||
838 | portp->openwaitcnt--; | ||
839 | spin_unlock_irqrestore(&stallion_lock, flags); | ||
840 | 773 | ||
841 | return rc; | 774 | static void stl_raise_dtr_rts(struct tty_port *port) |
775 | { | ||
776 | struct stlport *portp = container_of(port, struct stlport, port); | ||
777 | /* Takes brd_lock internally */ | ||
778 | stl_setsignals(portp, 1, 1); | ||
842 | } | 779 | } |
843 | 780 | ||
844 | /*****************************************************************************/ | 781 | /*****************************************************************************/ |
@@ -890,47 +827,29 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) | |||
890 | static void stl_close(struct tty_struct *tty, struct file *filp) | 827 | static void stl_close(struct tty_struct *tty, struct file *filp) |
891 | { | 828 | { |
892 | struct stlport *portp; | 829 | struct stlport *portp; |
830 | struct tty_port *port; | ||
893 | unsigned long flags; | 831 | unsigned long flags; |
894 | 832 | ||
895 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); | 833 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); |
896 | 834 | ||
897 | portp = tty->driver_data; | 835 | portp = tty->driver_data; |
898 | if (portp == NULL) | 836 | BUG_ON(portp == NULL); |
899 | return; | ||
900 | 837 | ||
901 | spin_lock_irqsave(&stallion_lock, flags); | 838 | port = &portp->port; |
902 | if (tty_hung_up_p(filp)) { | ||
903 | spin_unlock_irqrestore(&stallion_lock, flags); | ||
904 | return; | ||
905 | } | ||
906 | if ((tty->count == 1) && (portp->port.count != 1)) | ||
907 | portp->port.count = 1; | ||
908 | if (portp->port.count-- > 1) { | ||
909 | spin_unlock_irqrestore(&stallion_lock, flags); | ||
910 | return; | ||
911 | } | ||
912 | |||
913 | portp->port.count = 0; | ||
914 | portp->port.flags |= ASYNC_CLOSING; | ||
915 | 839 | ||
840 | if (tty_port_close_start(port, tty, filp) == 0) | ||
841 | return; | ||
916 | /* | 842 | /* |
917 | * May want to wait for any data to drain before closing. The BUSY | 843 | * May want to wait for any data to drain before closing. The BUSY |
918 | * flag keeps track of whether we are still sending or not - it is | 844 | * flag keeps track of whether we are still sending or not - it is |
919 | * very accurate for the cd1400, not quite so for the sc26198. | 845 | * very accurate for the cd1400, not quite so for the sc26198. |
920 | * (The sc26198 has no "end-of-data" interrupt only empty FIFO) | 846 | * (The sc26198 has no "end-of-data" interrupt only empty FIFO) |
921 | */ | 847 | */ |
922 | tty->closing = 1; | ||
923 | |||
924 | spin_unlock_irqrestore(&stallion_lock, flags); | ||
925 | |||
926 | if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
927 | tty_wait_until_sent(tty, portp->closing_wait); | ||
928 | stl_waituntilsent(tty, (HZ / 2)); | 848 | stl_waituntilsent(tty, (HZ / 2)); |
929 | 849 | ||
930 | 850 | spin_lock_irqsave(&port->lock, flags); | |
931 | spin_lock_irqsave(&stallion_lock, flags); | ||
932 | portp->port.flags &= ~ASYNC_INITIALIZED; | 851 | portp->port.flags &= ~ASYNC_INITIALIZED; |
933 | spin_unlock_irqrestore(&stallion_lock, flags); | 852 | spin_unlock_irqrestore(&port->lock, flags); |
934 | 853 | ||
935 | stl_disableintrs(portp); | 854 | stl_disableintrs(portp); |
936 | if (tty->termios->c_cflag & HUPCL) | 855 | if (tty->termios->c_cflag & HUPCL) |
@@ -944,20 +863,9 @@ static void stl_close(struct tty_struct *tty, struct file *filp) | |||
944 | portp->tx.head = NULL; | 863 | portp->tx.head = NULL; |
945 | portp->tx.tail = NULL; | 864 | portp->tx.tail = NULL; |
946 | } | 865 | } |
947 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
948 | tty_ldisc_flush(tty); | ||
949 | 866 | ||
950 | tty->closing = 0; | 867 | tty_port_close_end(port, tty); |
951 | tty_port_tty_set(&portp->port, NULL); | 868 | tty_port_tty_set(port, NULL); |
952 | |||
953 | if (portp->openwaitcnt) { | ||
954 | if (portp->close_delay) | ||
955 | msleep_interruptible(jiffies_to_msecs(portp->close_delay)); | ||
956 | wake_up_interruptible(&portp->port.open_wait); | ||
957 | } | ||
958 | |||
959 | portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
960 | wake_up_interruptible(&portp->port.close_wait); | ||
961 | } | 869 | } |
962 | 870 | ||
963 | /*****************************************************************************/ | 871 | /*****************************************************************************/ |
@@ -1405,14 +1313,20 @@ static void stl_stop(struct tty_struct *tty) | |||
1405 | static void stl_hangup(struct tty_struct *tty) | 1313 | static void stl_hangup(struct tty_struct *tty) |
1406 | { | 1314 | { |
1407 | struct stlport *portp; | 1315 | struct stlport *portp; |
1316 | struct tty_port *port; | ||
1317 | unsigned long flags; | ||
1408 | 1318 | ||
1409 | pr_debug("stl_hangup(tty=%p)\n", tty); | 1319 | pr_debug("stl_hangup(tty=%p)\n", tty); |
1410 | 1320 | ||
1411 | portp = tty->driver_data; | 1321 | portp = tty->driver_data; |
1412 | if (portp == NULL) | 1322 | if (portp == NULL) |
1413 | return; | 1323 | return; |
1324 | port = &portp->port; | ||
1325 | |||
1326 | spin_lock_irqsave(&port->lock, flags); | ||
1327 | port->flags &= ~ASYNC_INITIALIZED; | ||
1328 | spin_unlock_irqrestore(&port->lock, flags); | ||
1414 | 1329 | ||
1415 | portp->port.flags &= ~ASYNC_INITIALIZED; | ||
1416 | stl_disableintrs(portp); | 1330 | stl_disableintrs(portp); |
1417 | if (tty->termios->c_cflag & HUPCL) | 1331 | if (tty->termios->c_cflag & HUPCL) |
1418 | stl_setsignals(portp, 0, 0); | 1332 | stl_setsignals(portp, 0, 0); |
@@ -1426,10 +1340,7 @@ static void stl_hangup(struct tty_struct *tty) | |||
1426 | portp->tx.head = NULL; | 1340 | portp->tx.head = NULL; |
1427 | portp->tx.tail = NULL; | 1341 | portp->tx.tail = NULL; |
1428 | } | 1342 | } |
1429 | tty_port_tty_set(&portp->port, NULL); | 1343 | tty_port_hangup(port); |
1430 | portp->port.flags &= ~ASYNC_NORMAL_ACTIVE; | ||
1431 | portp->port.count = 0; | ||
1432 | wake_up_interruptible(&portp->port.open_wait); | ||
1433 | } | 1344 | } |
1434 | 1345 | ||
1435 | /*****************************************************************************/ | 1346 | /*****************************************************************************/ |
@@ -1776,6 +1687,7 @@ static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp) | |||
1776 | break; | 1687 | break; |
1777 | } | 1688 | } |
1778 | tty_port_init(&portp->port); | 1689 | tty_port_init(&portp->port); |
1690 | portp->port.ops = &stl_port_ops; | ||
1779 | portp->magic = STL_PORTMAGIC; | 1691 | portp->magic = STL_PORTMAGIC; |
1780 | portp->portnr = i; | 1692 | portp->portnr = i; |
1781 | portp->brdnr = panelp->brdnr; | 1693 | portp->brdnr = panelp->brdnr; |
@@ -2659,6 +2571,11 @@ static const struct tty_operations stl_ops = { | |||
2659 | .tiocmset = stl_tiocmset, | 2571 | .tiocmset = stl_tiocmset, |
2660 | }; | 2572 | }; |
2661 | 2573 | ||
2574 | static const struct tty_port_operations stl_port_ops = { | ||
2575 | .carrier_raised = stl_carrier_raised, | ||
2576 | .raise_dtr_rts = stl_raise_dtr_rts, | ||
2577 | }; | ||
2578 | |||
2662 | /*****************************************************************************/ | 2579 | /*****************************************************************************/ |
2663 | /* CD1400 HARDWARE FUNCTIONS */ | 2580 | /* CD1400 HARDWARE FUNCTIONS */ |
2664 | /*****************************************************************************/ | 2581 | /*****************************************************************************/ |