aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/istallion.c159
-rw-r--r--include/linux/istallion.h1
2 files changed, 43 insertions, 117 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);
626static int stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp); 626static int stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp);
627static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); 627static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
628static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); 628static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
629static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp,
630 struct stliport *portp, struct file *filp);
631static int stli_setport(struct tty_struct *tty); 629static int stli_setport(struct tty_struct *tty);
632static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); 630static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
633static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); 631static 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/* 1163static 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
1197static 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
4529static const struct tty_port_operations stli_port_ops = { 4455static 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/*****************************************************************************/
diff --git a/include/linux/istallion.h b/include/linux/istallion.h
index 0d1840723249..053d5aea925c 100644
--- a/include/linux/istallion.h
+++ b/include/linux/istallion.h
@@ -61,7 +61,6 @@ struct stliport {
61 int custom_divisor; 61 int custom_divisor;
62 int close_delay; 62 int close_delay;
63 int closing_wait; 63 int closing_wait;
64 int openwaitcnt;
65 int rc; 64 int rc;
66 int argsize; 65 int argsize;
67 void *argp; 66 void *argp;