diff options
author | Alan Cox <alan@redhat.com> | 2009-01-02 08:46:18 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 13:19:39 -0500 |
commit | 2a6eadbd5a2ae8f458e421f3614f1ad13c0f9a1c (patch) | |
tree | 4eee6f264c83bef40e103aa1e141475f481b0f80 /drivers/char | |
parent | 36c621d82b956ff6ff72273f848af53e6c581aba (diff) |
tty: Rework istallion to use the tty port changes
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/istallion.c | 159 |
1 files changed, 43 insertions, 116 deletions
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index c4682f9e34bb..4c69ab97339a 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -626,8 +626,6 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); | |||
626 | static int stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp); | 626 | static int stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp); |
627 | static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); | 627 | static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); |
628 | static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); | 628 | static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); |
629 | static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp, | ||
630 | struct stliport *portp, struct file *filp); | ||
631 | static int stli_setport(struct tty_struct *tty); | 629 | static int stli_setport(struct tty_struct *tty); |
632 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); | 630 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); |
633 | static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); | 631 | static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); |
@@ -787,6 +785,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
787 | { | 785 | { |
788 | struct stlibrd *brdp; | 786 | struct stlibrd *brdp; |
789 | struct stliport *portp; | 787 | struct stliport *portp; |
788 | struct tty_port *port; | ||
790 | unsigned int minordev, brdnr, portnr; | 789 | unsigned int minordev, brdnr, portnr; |
791 | int rc; | 790 | int rc; |
792 | 791 | ||
@@ -808,30 +807,19 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
808 | return -ENODEV; | 807 | return -ENODEV; |
809 | if (portp->devnr < 1) | 808 | if (portp->devnr < 1) |
810 | return -ENODEV; | 809 | return -ENODEV; |
811 | 810 | port = &portp->port; | |
812 | |||
813 | /* | ||
814 | * Check if this port is in the middle of closing. If so then wait | ||
815 | * until it is closed then return error status based on flag settings. | ||
816 | * The sleep here does not need interrupt protection since the wakeup | ||
817 | * for it is done with the same context. | ||
818 | */ | ||
819 | if (portp->port.flags & ASYNC_CLOSING) { | ||
820 | interruptible_sleep_on(&portp->port.close_wait); | ||
821 | if (portp->port.flags & ASYNC_HUP_NOTIFY) | ||
822 | return -EAGAIN; | ||
823 | return -ERESTARTSYS; | ||
824 | } | ||
825 | 811 | ||
826 | /* | 812 | /* |
827 | * On the first open of the device setup the port hardware, and | 813 | * On the first open of the device setup the port hardware, and |
828 | * initialize the per port data structure. Since initializing the port | 814 | * initialize the per port data structure. Since initializing the port |
829 | * requires several commands to the board we will need to wait for any | 815 | * requires several commands to the board we will need to wait for any |
830 | * other open that is already initializing the port. | 816 | * other open that is already initializing the port. |
817 | * | ||
818 | * Review - locking | ||
831 | */ | 819 | */ |
832 | tty_port_tty_set(&portp->port, tty); | 820 | tty_port_tty_set(port, tty); |
833 | tty->driver_data = portp; | 821 | tty->driver_data = portp; |
834 | portp->port.count++; | 822 | port->count++; |
835 | 823 | ||
836 | wait_event_interruptible(portp->raw_wait, | 824 | wait_event_interruptible(portp->raw_wait, |
837 | !test_bit(ST_INITIALIZING, &portp->state)); | 825 | !test_bit(ST_INITIALIZING, &portp->state)); |
@@ -841,7 +829,8 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
841 | if ((portp->port.flags & ASYNC_INITIALIZED) == 0) { | 829 | if ((portp->port.flags & ASYNC_INITIALIZED) == 0) { |
842 | set_bit(ST_INITIALIZING, &portp->state); | 830 | set_bit(ST_INITIALIZING, &portp->state); |
843 | if ((rc = stli_initopen(tty, brdp, portp)) >= 0) { | 831 | if ((rc = stli_initopen(tty, brdp, portp)) >= 0) { |
844 | portp->port.flags |= ASYNC_INITIALIZED; | 832 | /* Locking */ |
833 | port->flags |= ASYNC_INITIALIZED; | ||
845 | clear_bit(TTY_IO_ERROR, &tty->flags); | 834 | clear_bit(TTY_IO_ERROR, &tty->flags); |
846 | } | 835 | } |
847 | clear_bit(ST_INITIALIZING, &portp->state); | 836 | clear_bit(ST_INITIALIZING, &portp->state); |
@@ -849,31 +838,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
849 | if (rc < 0) | 838 | if (rc < 0) |
850 | return rc; | 839 | return rc; |
851 | } | 840 | } |
852 | 841 | return tty_port_block_til_ready(&portp->port, tty, filp); | |
853 | /* | ||
854 | * Check if this port is in the middle of closing. If so then wait | ||
855 | * until it is closed then return error status, based on flag settings. | ||
856 | * The sleep here does not need interrupt protection since the wakeup | ||
857 | * for it is done with the same context. | ||
858 | */ | ||
859 | if (portp->port.flags & ASYNC_CLOSING) { | ||
860 | interruptible_sleep_on(&portp->port.close_wait); | ||
861 | if (portp->port.flags & ASYNC_HUP_NOTIFY) | ||
862 | return -EAGAIN; | ||
863 | return -ERESTARTSYS; | ||
864 | } | ||
865 | |||
866 | /* | ||
867 | * Based on type of open being done check if it can overlap with any | ||
868 | * previous opens still in effect. If we are a normal serial device | ||
869 | * then also we might have to wait for carrier. | ||
870 | */ | ||
871 | if (!(filp->f_flags & O_NONBLOCK)) { | ||
872 | if ((rc = stli_waitcarrier(tty, brdp, portp, filp)) != 0) | ||
873 | return rc; | ||
874 | } | ||
875 | portp->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
876 | return 0; | ||
877 | } | 842 | } |
878 | 843 | ||
879 | /*****************************************************************************/ | 844 | /*****************************************************************************/ |
@@ -882,25 +847,29 @@ static void stli_close(struct tty_struct *tty, struct file *filp) | |||
882 | { | 847 | { |
883 | struct stlibrd *brdp; | 848 | struct stlibrd *brdp; |
884 | struct stliport *portp; | 849 | struct stliport *portp; |
850 | struct tty_port *port; | ||
885 | unsigned long flags; | 851 | unsigned long flags; |
886 | 852 | ||
887 | portp = tty->driver_data; | 853 | portp = tty->driver_data; |
888 | if (portp == NULL) | 854 | if (portp == NULL) |
889 | return; | 855 | return; |
856 | port = &portp->port; | ||
890 | 857 | ||
891 | spin_lock_irqsave(&stli_lock, flags); | 858 | spin_lock_irqsave(&port->lock, flags); |
892 | if (tty_hung_up_p(filp)) { | 859 | if (tty_hung_up_p(filp)) { |
893 | spin_unlock_irqrestore(&stli_lock, flags); | 860 | spin_unlock_irqrestore(&port->lock, flags); |
894 | return; | 861 | return; |
895 | } | 862 | } |
896 | if ((tty->count == 1) && (portp->port.count != 1)) | 863 | if (tty->count == 1 && port->count != 1) |
897 | portp->port.count = 1; | 864 | port->count = 1; |
898 | if (portp->port.count-- > 1) { | 865 | if (port->count-- > 1) { |
899 | spin_unlock_irqrestore(&stli_lock, flags); | 866 | spin_unlock_irqrestore(&port->lock, flags); |
900 | return; | 867 | return; |
901 | } | 868 | } |
902 | 869 | ||
903 | portp->port.flags |= ASYNC_CLOSING; | 870 | port->flags |= ASYNC_CLOSING; |
871 | tty->closing = 1; | ||
872 | spin_unlock_irqrestore(&port->lock, flags); | ||
904 | 873 | ||
905 | /* | 874 | /* |
906 | * May want to wait for data to drain before closing. The BUSY flag | 875 | * May want to wait for data to drain before closing. The BUSY flag |
@@ -908,15 +877,17 @@ static void stli_close(struct tty_struct *tty, struct file *filp) | |||
908 | * updated by messages from the slave - indicating when all chars | 877 | * updated by messages from the slave - indicating when all chars |
909 | * really have drained. | 878 | * really have drained. |
910 | */ | 879 | */ |
880 | spin_lock_irqsave(&stli_lock, flags); | ||
911 | if (tty == stli_txcooktty) | 881 | if (tty == stli_txcooktty) |
912 | stli_flushchars(tty); | 882 | stli_flushchars(tty); |
913 | tty->closing = 1; | ||
914 | spin_unlock_irqrestore(&stli_lock, flags); | 883 | spin_unlock_irqrestore(&stli_lock, flags); |
915 | 884 | ||
916 | if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 885 | if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
917 | tty_wait_until_sent(tty, portp->closing_wait); | 886 | tty_wait_until_sent(tty, portp->closing_wait); |
918 | 887 | ||
919 | portp->port.flags &= ~ASYNC_INITIALIZED; | 888 | /* FIXME: port locking here needs attending to */ |
889 | port->flags &= ~ASYNC_INITIALIZED; | ||
890 | |||
920 | brdp = stli_brds[portp->brdnr]; | 891 | brdp = stli_brds[portp->brdnr]; |
921 | stli_rawclose(brdp, portp, 0, 0); | 892 | stli_rawclose(brdp, portp, 0, 0); |
922 | if (tty->termios->c_cflag & HUPCL) { | 893 | if (tty->termios->c_cflag & HUPCL) { |
@@ -937,14 +908,14 @@ static void stli_close(struct tty_struct *tty, struct file *filp) | |||
937 | tty->closing = 0; | 908 | tty->closing = 0; |
938 | tty_port_tty_set(&portp->port, NULL); | 909 | tty_port_tty_set(&portp->port, NULL); |
939 | 910 | ||
940 | if (portp->openwaitcnt) { | 911 | if (port->blocked_open) { |
941 | if (portp->close_delay) | 912 | if (portp->close_delay) |
942 | msleep_interruptible(jiffies_to_msecs(portp->close_delay)); | 913 | msleep_interruptible(jiffies_to_msecs(portp->close_delay)); |
943 | wake_up_interruptible(&portp->port.open_wait); | 914 | wake_up_interruptible(&port->open_wait); |
944 | } | 915 | } |
945 | 916 | ||
946 | portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | 917 | port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); |
947 | wake_up_interruptible(&portp->port.close_wait); | 918 | wake_up_interruptible(&port->close_wait); |
948 | } | 919 | } |
949 | 920 | ||
950 | /*****************************************************************************/ | 921 | /*****************************************************************************/ |
@@ -1189,63 +1160,17 @@ static int stli_carrier_raised(struct tty_port *port) | |||
1189 | return (portp->sigs & TIOCM_CD) ? 1 : 0; | 1160 | return (portp->sigs & TIOCM_CD) ? 1 : 0; |
1190 | } | 1161 | } |
1191 | 1162 | ||
1192 | /* | 1163 | static void stli_raise_dtr_rts(struct tty_port *port) |
1193 | * Possibly need to wait for carrier (DCD signal) to come high. Say | ||
1194 | * maybe because if we are clocal then we don't need to wait... | ||
1195 | */ | ||
1196 | |||
1197 | static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp, | ||
1198 | struct stliport *portp, struct file *filp) | ||
1199 | { | 1164 | { |
1200 | unsigned long flags; | 1165 | struct stliport *portp = container_of(port, struct stliport, port); |
1201 | int rc, doclocal; | 1166 | struct stlibrd *brdp = stli_brds[portp->brdnr]; |
1202 | struct tty_port *port = &portp->port; | 1167 | stli_mkasysigs(&portp->asig, 1, 1); |
1203 | 1168 | if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, | |
1204 | rc = 0; | 1169 | sizeof(asysigs_t), 0) < 0) |
1205 | doclocal = 0; | 1170 | printk(KERN_WARNING "istallion: dtr raise failed.\n"); |
1206 | |||
1207 | if (tty->termios->c_cflag & CLOCAL) | ||
1208 | doclocal++; | ||
1209 | |||
1210 | spin_lock_irqsave(&stli_lock, flags); | ||
1211 | portp->openwaitcnt++; | ||
1212 | if (! tty_hung_up_p(filp)) | ||
1213 | port->count--; | ||
1214 | spin_unlock_irqrestore(&stli_lock, flags); | ||
1215 | |||
1216 | for (;;) { | ||
1217 | stli_mkasysigs(&portp->asig, 1, 1); | ||
1218 | if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, | ||
1219 | &portp->asig, sizeof(asysigs_t), 0)) < 0) | ||
1220 | break; | ||
1221 | if (tty_hung_up_p(filp) || | ||
1222 | ((port->flags & ASYNC_INITIALIZED) == 0)) { | ||
1223 | if (port->flags & ASYNC_HUP_NOTIFY) | ||
1224 | rc = -EBUSY; | ||
1225 | else | ||
1226 | rc = -ERESTARTSYS; | ||
1227 | break; | ||
1228 | } | ||
1229 | if (((port->flags & ASYNC_CLOSING) == 0) && | ||
1230 | (doclocal || tty_port_carrier_raised(port))) { | ||
1231 | break; | ||
1232 | } | ||
1233 | if (signal_pending(current)) { | ||
1234 | rc = -ERESTARTSYS; | ||
1235 | break; | ||
1236 | } | ||
1237 | interruptible_sleep_on(&port->open_wait); | ||
1238 | } | ||
1239 | |||
1240 | spin_lock_irqsave(&stli_lock, flags); | ||
1241 | if (! tty_hung_up_p(filp)) | ||
1242 | port->count++; | ||
1243 | portp->openwaitcnt--; | ||
1244 | spin_unlock_irqrestore(&stli_lock, flags); | ||
1245 | |||
1246 | return rc; | ||
1247 | } | 1171 | } |
1248 | 1172 | ||
1173 | |||
1249 | /*****************************************************************************/ | 1174 | /*****************************************************************************/ |
1250 | 1175 | ||
1251 | /* | 1176 | /* |
@@ -1828,6 +1753,7 @@ static void stli_hangup(struct tty_struct *tty) | |||
1828 | { | 1753 | { |
1829 | struct stliport *portp; | 1754 | struct stliport *portp; |
1830 | struct stlibrd *brdp; | 1755 | struct stlibrd *brdp; |
1756 | struct tty_port *port; | ||
1831 | unsigned long flags; | 1757 | unsigned long flags; |
1832 | 1758 | ||
1833 | portp = tty->driver_data; | 1759 | portp = tty->driver_data; |
@@ -1838,8 +1764,11 @@ static void stli_hangup(struct tty_struct *tty) | |||
1838 | brdp = stli_brds[portp->brdnr]; | 1764 | brdp = stli_brds[portp->brdnr]; |
1839 | if (brdp == NULL) | 1765 | if (brdp == NULL) |
1840 | return; | 1766 | return; |
1767 | port = &portp->port; | ||
1841 | 1768 | ||
1842 | portp->port.flags &= ~ASYNC_INITIALIZED; | 1769 | spin_lock_irqsave(&port->lock, flags); |
1770 | port->flags &= ~ASYNC_INITIALIZED; | ||
1771 | spin_unlock_irqrestore(&port->lock, flags); | ||
1843 | 1772 | ||
1844 | if (!test_bit(ST_CLOSING, &portp->state)) | 1773 | if (!test_bit(ST_CLOSING, &portp->state)) |
1845 | stli_rawclose(brdp, portp, 0, 0); | 1774 | stli_rawclose(brdp, portp, 0, 0); |
@@ -1860,12 +1789,9 @@ static void stli_hangup(struct tty_struct *tty) | |||
1860 | clear_bit(ST_TXBUSY, &portp->state); | 1789 | clear_bit(ST_TXBUSY, &portp->state); |
1861 | clear_bit(ST_RXSTOP, &portp->state); | 1790 | clear_bit(ST_RXSTOP, &portp->state); |
1862 | set_bit(TTY_IO_ERROR, &tty->flags); | 1791 | set_bit(TTY_IO_ERROR, &tty->flags); |
1863 | tty_port_tty_set(&portp->port, NULL); | ||
1864 | portp->port.flags &= ~ASYNC_NORMAL_ACTIVE; | ||
1865 | portp->port.count = 0; | ||
1866 | spin_unlock_irqrestore(&stli_lock, flags); | 1792 | spin_unlock_irqrestore(&stli_lock, flags); |
1867 | 1793 | ||
1868 | wake_up_interruptible(&portp->port.open_wait); | 1794 | tty_port_hangup(port); |
1869 | } | 1795 | } |
1870 | 1796 | ||
1871 | /*****************************************************************************/ | 1797 | /*****************************************************************************/ |
@@ -4528,6 +4454,7 @@ static const struct tty_operations stli_ops = { | |||
4528 | 4454 | ||
4529 | static const struct tty_port_operations stli_port_ops = { | 4455 | static const struct tty_port_operations stli_port_ops = { |
4530 | .carrier_raised = stli_carrier_raised, | 4456 | .carrier_raised = stli_carrier_raised, |
4457 | .raise_dtr_rts = stli_raise_dtr_rts, | ||
4531 | }; | 4458 | }; |
4532 | 4459 | ||
4533 | /*****************************************************************************/ | 4460 | /*****************************************************************************/ |