diff options
-rw-r--r-- | drivers/char/rocket.c | 177 | ||||
-rw-r--r-- | drivers/char/tty_port.c | 3 |
2 files changed, 21 insertions, 159 deletions
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index b5e5e77c59de..f59fc5cea067 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -879,108 +879,6 @@ static void raise_dtr_rts(struct tty_port *port) | |||
879 | sSetRTS(&info->channel); | 879 | sSetRTS(&info->channel); |
880 | } | 880 | } |
881 | 881 | ||
882 | /* info->port.count is considered critical, protected by spinlocks. */ | ||
883 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | ||
884 | struct r_port *info) | ||
885 | { | ||
886 | DECLARE_WAITQUEUE(wait, current); | ||
887 | struct tty_port *port = &info->port; | ||
888 | int retval; | ||
889 | int do_clocal = 0, extra_count = 0; | ||
890 | unsigned long flags; | ||
891 | |||
892 | /* | ||
893 | * If the device is in the middle of being closed, then block | ||
894 | * until it's done, and then try again. | ||
895 | */ | ||
896 | if (tty_hung_up_p(filp)) | ||
897 | return ((info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); | ||
898 | if (info->flags & ASYNC_CLOSING) { | ||
899 | if (wait_for_completion_interruptible(&info->close_wait)) | ||
900 | return -ERESTARTSYS; | ||
901 | return ((info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); | ||
902 | } | ||
903 | |||
904 | /* | ||
905 | * If non-blocking mode is set, or the port is not enabled, | ||
906 | * then make the check up front and then exit. | ||
907 | */ | ||
908 | if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { | ||
909 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
910 | return 0; | ||
911 | } | ||
912 | if (tty->termios->c_cflag & CLOCAL) | ||
913 | do_clocal = 1; | ||
914 | |||
915 | /* | ||
916 | * Block waiting for the carrier detect and the line to become free. While we are in | ||
917 | * this loop, port->count is dropped by one, so that rp_close() knows when to free things. | ||
918 | * We restore it upon exit, either normal or abnormal. | ||
919 | */ | ||
920 | retval = 0; | ||
921 | add_wait_queue(&port->open_wait, &wait); | ||
922 | #ifdef ROCKET_DEBUG_OPEN | ||
923 | printk(KERN_INFO "block_til_ready before block: ttyR%d, count = %d\n", info->line, port->count); | ||
924 | #endif | ||
925 | spin_lock_irqsave(&port->lock, flags); | ||
926 | |||
927 | #ifdef ROCKET_DISABLE_SIMUSAGE | ||
928 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
929 | #else | ||
930 | if (!tty_hung_up_p(filp)) { | ||
931 | extra_count = 1; | ||
932 | port->count--; | ||
933 | } | ||
934 | #endif | ||
935 | port->blocked_open++; | ||
936 | |||
937 | spin_unlock_irqrestore(&port->lock, flags); | ||
938 | |||
939 | while (1) { | ||
940 | if (tty->termios->c_cflag & CBAUD) | ||
941 | tty_port_raise_dtr_rts(port); | ||
942 | set_current_state(TASK_INTERRUPTIBLE); | ||
943 | if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)) { | ||
944 | if (info->port.flags & ASYNC_HUP_NOTIFY) | ||
945 | retval = -EAGAIN; | ||
946 | else | ||
947 | retval = -ERESTARTSYS; | ||
948 | break; | ||
949 | } | ||
950 | if (!(info->port.flags & ASYNC_CLOSING) && | ||
951 | (do_clocal || tty_port_carrier_raised(port))) | ||
952 | break; | ||
953 | if (signal_pending(current)) { | ||
954 | retval = -ERESTARTSYS; | ||
955 | break; | ||
956 | } | ||
957 | #ifdef ROCKET_DEBUG_OPEN | ||
958 | printk(KERN_INFO "block_til_ready blocking: ttyR%d, count = %d, flags=0x%0x\n", | ||
959 | info->line, port->count, info->port.flags); | ||
960 | #endif | ||
961 | schedule(); /* Don't hold spinlock here, will hang PC */ | ||
962 | } | ||
963 | __set_current_state(TASK_RUNNING); | ||
964 | remove_wait_queue(&port->open_wait, &wait); | ||
965 | |||
966 | spin_lock_irqsave(&port->lock, flags); | ||
967 | |||
968 | if (extra_count) | ||
969 | port->count++; | ||
970 | port->blocked_open--; | ||
971 | |||
972 | spin_unlock_irqrestore(&port->lock, flags); | ||
973 | |||
974 | #ifdef ROCKET_DEBUG_OPEN | ||
975 | printk(KERN_INFO "block_til_ready after blocking: ttyR%d, count = %d\n", | ||
976 | info->line, port->count); | ||
977 | #endif | ||
978 | if (retval) | ||
979 | return retval; | ||
980 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
981 | return 0; | ||
982 | } | ||
983 | |||
984 | /* | 882 | /* |
985 | * Exception handler that opens a serial port. Creates xmit_buf storage, fills in | 883 | * Exception handler that opens a serial port. Creates xmit_buf storage, fills in |
986 | * port's r_port struct. Initializes the port hardware. | 884 | * port's r_port struct. Initializes the port hardware. |
@@ -988,24 +886,26 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
988 | static int rp_open(struct tty_struct *tty, struct file *filp) | 886 | static int rp_open(struct tty_struct *tty, struct file *filp) |
989 | { | 887 | { |
990 | struct r_port *info; | 888 | struct r_port *info; |
889 | struct tty_port *port; | ||
991 | int line = 0, retval; | 890 | int line = 0, retval; |
992 | CHANNEL_t *cp; | 891 | CHANNEL_t *cp; |
993 | unsigned long page; | 892 | unsigned long page; |
994 | 893 | ||
995 | line = tty->index; | 894 | line = tty->index; |
996 | if ((line < 0) || (line >= MAX_RP_PORTS) || ((info = rp_table[line]) == NULL)) | 895 | if (line < 0 || line >= MAX_RP_PORTS || ((info = rp_table[line]) == NULL)) |
997 | return -ENXIO; | 896 | return -ENXIO; |
998 | 897 | port = &info->port; | |
898 | |||
999 | page = __get_free_page(GFP_KERNEL); | 899 | page = __get_free_page(GFP_KERNEL); |
1000 | if (!page) | 900 | if (!page) |
1001 | return -ENOMEM; | 901 | return -ENOMEM; |
1002 | 902 | ||
1003 | if (info->port.flags & ASYNC_CLOSING) { | 903 | if (port->flags & ASYNC_CLOSING) { |
1004 | retval = wait_for_completion_interruptible(&info->close_wait); | 904 | retval = wait_for_completion_interruptible(&info->close_wait); |
1005 | free_page(page); | 905 | free_page(page); |
1006 | if (retval) | 906 | if (retval) |
1007 | return retval; | 907 | return retval; |
1008 | return ((info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); | 908 | return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); |
1009 | } | 909 | } |
1010 | 910 | ||
1011 | /* | 911 | /* |
@@ -1017,9 +917,9 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
1017 | info->xmit_buf = (unsigned char *) page; | 917 | info->xmit_buf = (unsigned char *) page; |
1018 | 918 | ||
1019 | tty->driver_data = info; | 919 | tty->driver_data = info; |
1020 | tty_port_tty_set(&info->port, tty); | 920 | tty_port_tty_set(port, tty); |
1021 | 921 | ||
1022 | if (info->port.count++ == 0) { | 922 | if (port->count++ == 0) { |
1023 | atomic_inc(&rp_num_ports_open); | 923 | atomic_inc(&rp_num_ports_open); |
1024 | 924 | ||
1025 | #ifdef ROCKET_DEBUG_OPEN | 925 | #ifdef ROCKET_DEBUG_OPEN |
@@ -1034,7 +934,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
1034 | /* | 934 | /* |
1035 | * Info->count is now 1; so it's safe to sleep now. | 935 | * Info->count is now 1; so it's safe to sleep now. |
1036 | */ | 936 | */ |
1037 | if ((info->port.flags & ASYNC_INITIALIZED) == 0) { | 937 | if (!test_bit(ASYNC_INITIALIZED, &port->flags)) { |
1038 | cp = &info->channel; | 938 | cp = &info->channel; |
1039 | sSetRxTrigger(cp, TRIG_1); | 939 | sSetRxTrigger(cp, TRIG_1); |
1040 | if (sGetChanStatus(cp) & CD_ACT) | 940 | if (sGetChanStatus(cp) & CD_ACT) |
@@ -1058,7 +958,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
1058 | sEnRxFIFO(cp); | 958 | sEnRxFIFO(cp); |
1059 | sEnTransmit(cp); | 959 | sEnTransmit(cp); |
1060 | 960 | ||
1061 | info->port.flags |= ASYNC_INITIALIZED; | 961 | set_bit(ASYNC_INITIALIZED, &info->port.flags); |
1062 | 962 | ||
1063 | /* | 963 | /* |
1064 | * Set up the tty->alt_speed kludge | 964 | * Set up the tty->alt_speed kludge |
@@ -1081,7 +981,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
1081 | /* Starts (or resets) the maint polling loop */ | 981 | /* Starts (or resets) the maint polling loop */ |
1082 | mod_timer(&rocket_timer, jiffies + POLL_PERIOD); | 982 | mod_timer(&rocket_timer, jiffies + POLL_PERIOD); |
1083 | 983 | ||
1084 | retval = block_til_ready(tty, filp, info); | 984 | retval = tty_port_block_til_ready(port, tty, filp); |
1085 | if (retval) { | 985 | if (retval) { |
1086 | #ifdef ROCKET_DEBUG_OPEN | 986 | #ifdef ROCKET_DEBUG_OPEN |
1087 | printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval); | 987 | printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval); |
@@ -1098,7 +998,6 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1098 | { | 998 | { |
1099 | struct r_port *info = tty->driver_data; | 999 | struct r_port *info = tty->driver_data; |
1100 | struct tty_port *port = &info->port; | 1000 | struct tty_port *port = &info->port; |
1101 | unsigned long flags; | ||
1102 | int timeout; | 1001 | int timeout; |
1103 | CHANNEL_t *cp; | 1002 | CHANNEL_t *cp; |
1104 | 1003 | ||
@@ -1109,53 +1008,10 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1109 | printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->port.count); | 1008 | printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->port.count); |
1110 | #endif | 1009 | #endif |
1111 | 1010 | ||
1112 | if (tty_hung_up_p(filp)) | 1011 | if (tty_port_close_start(port, tty, filp) == 0) |
1113 | return; | 1012 | return; |
1114 | spin_lock_irqsave(&port->lock, flags); | ||
1115 | |||
1116 | if (tty->count == 1 && port->count != 1) { | ||
1117 | /* | ||
1118 | * Uh, oh. tty->count is 1, which means that the tty | ||
1119 | * structure will be freed. Info->count should always | ||
1120 | * be one in these conditions. If it's greater than | ||
1121 | * one, we've got real problems, since it means the | ||
1122 | * serial port won't be shutdown. | ||
1123 | */ | ||
1124 | printk(KERN_WARNING "rp_close: bad serial port count; " | ||
1125 | "tty->count is 1, info->port.count is %d\n", info->port.count); | ||
1126 | port->count = 1; | ||
1127 | } | ||
1128 | if (--port->count < 0) { | ||
1129 | printk(KERN_WARNING "rp_close: bad serial port count for " | ||
1130 | "ttyR%d: %d\n", info->line, info->port.count); | ||
1131 | port->count = 0; | ||
1132 | } | ||
1133 | if (port->count) { | ||
1134 | spin_unlock_irqrestore(&port->lock, flags); | ||
1135 | return; | ||
1136 | } | ||
1137 | info->port.flags |= ASYNC_CLOSING; | ||
1138 | spin_unlock_irqrestore(&port->lock, flags); | ||
1139 | 1013 | ||
1140 | cp = &info->channel; | 1014 | cp = &info->channel; |
1141 | |||
1142 | /* | ||
1143 | * Notify the line discpline to only process XON/XOFF characters | ||
1144 | */ | ||
1145 | tty->closing = 1; | ||
1146 | |||
1147 | /* | ||
1148 | * If transmission was throttled by the application request, | ||
1149 | * just flush the xmit buffer. | ||
1150 | */ | ||
1151 | if (tty->flow_stopped) | ||
1152 | rp_flush_buffer(tty); | ||
1153 | |||
1154 | /* | ||
1155 | * Wait for the transmit buffer to clear | ||
1156 | */ | ||
1157 | if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
1158 | tty_wait_until_sent(tty, port->closing_wait); | ||
1159 | /* | 1015 | /* |
1160 | * Before we drop DTR, make sure the UART transmitter | 1016 | * Before we drop DTR, make sure the UART transmitter |
1161 | * has completely drained; this is especially | 1017 | * has completely drained; this is especially |
@@ -1184,6 +1040,9 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1184 | 1040 | ||
1185 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); | 1041 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); |
1186 | 1042 | ||
1043 | /* We can't yet use tty_port_close_end as the buffer handling in this | ||
1044 | driver is a bit different to the usual */ | ||
1045 | |||
1187 | if (port->blocked_open) { | 1046 | if (port->blocked_open) { |
1188 | if (port->close_delay) { | 1047 | if (port->close_delay) { |
1189 | msleep_interruptible(jiffies_to_msecs(port->close_delay)); | 1048 | msleep_interruptible(jiffies_to_msecs(port->close_delay)); |
@@ -1197,6 +1056,8 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1197 | } | 1056 | } |
1198 | info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); | 1057 | info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); |
1199 | tty->closing = 0; | 1058 | tty->closing = 0; |
1059 | tty_port_tty_set(port, NULL); | ||
1060 | wake_up_interruptible(&port->close_wait); | ||
1200 | complete_all(&info->close_wait); | 1061 | complete_all(&info->close_wait); |
1201 | atomic_dec(&rp_num_ports_open); | 1062 | atomic_dec(&rp_num_ports_open); |
1202 | 1063 | ||
@@ -1659,9 +1520,7 @@ static void rp_hangup(struct tty_struct *tty) | |||
1659 | atomic_dec(&rp_num_ports_open); | 1520 | atomic_dec(&rp_num_ports_open); |
1660 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); | 1521 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); |
1661 | 1522 | ||
1662 | info->port.count = 0; | 1523 | tty_port_hangup(&info->port); |
1663 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | ||
1664 | tty_port_tty_set(&info->port, NULL); | ||
1665 | 1524 | ||
1666 | cp = &info->channel; | 1525 | cp = &info->channel; |
1667 | sDisRxFIFO(cp); | 1526 | sDisRxFIFO(cp); |
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index b580fcf629f8..9b8004c72686 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c | |||
@@ -286,6 +286,9 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f | |||
286 | port->flags |= ASYNC_CLOSING; | 286 | port->flags |= ASYNC_CLOSING; |
287 | tty->closing = 1; | 287 | tty->closing = 1; |
288 | spin_unlock_irqrestore(&port->lock, flags); | 288 | spin_unlock_irqrestore(&port->lock, flags); |
289 | /* Don't block on a stalled port, just pull the chain */ | ||
290 | if (tty->flow_stopped) | ||
291 | tty_driver_flush_buffer(tty); | ||
289 | if (port->flags & ASYNC_INITIALIZED && | 292 | if (port->flags & ASYNC_INITIALIZED && |
290 | port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 293 | port->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
291 | tty_wait_until_sent(tty, port->closing_wait); | 294 | tty_wait_until_sent(tty, port->closing_wait); |