diff options
author | Jeff Garzik <jeff@garzik.org> | 2008-02-06 04:36:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-06 13:41:00 -0500 |
commit | d9afa43532adf8a31b93c4c7601fda3f423d8972 (patch) | |
tree | 1f5cc6d5050af80b5015b536c8b4f4fe1b6dd3d5 /drivers | |
parent | 1c17d18e3775485bf1e0ce79575eb637a94494a2 (diff) |
riscom8: fix SMP brokenness
After analyzing the elements that save_flags/cli/sti/restore_flags were
protecting, convert their usages to a global spinlock (the easiest and
most obvious next-step). There were some usages of flags being
intentionally cached, because the code already knew the state of
interrupts. These have been taken into account.
This allows us to remove CONFIG_BROKEN_ON_SMP. Completely untested.
[akpm@linux-foundation.org: use DEFINE_SPINLOCK]
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/Kconfig | 2 | ||||
-rw-r--r-- | drivers/char/riscom8.c | 147 |
2 files changed, 94 insertions, 55 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 466629594776..eb5687beea91 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -276,7 +276,7 @@ config N_HDLC | |||
276 | 276 | ||
277 | config RISCOM8 | 277 | config RISCOM8 |
278 | tristate "SDL RISCom/8 card support" | 278 | tristate "SDL RISCom/8 card support" |
279 | depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP | 279 | depends on SERIAL_NONSTANDARD |
280 | help | 280 | help |
281 | This is a driver for the SDL Communications RISCom/8 multiport card, | 281 | This is a driver for the SDL Communications RISCom/8 multiport card, |
282 | which gives you many serial ports. You would need something like | 282 | which gives you many serial ports. You would need something like |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 102ece4c4e0e..d130b87d8ed7 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/init.h> | 47 | #include <linux/init.h> |
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/tty_flip.h> | 49 | #include <linux/tty_flip.h> |
50 | #include <linux/spinlock.h> | ||
50 | 51 | ||
51 | #include <asm/uaccess.h> | 52 | #include <asm/uaccess.h> |
52 | 53 | ||
@@ -81,6 +82,8 @@ | |||
81 | 82 | ||
82 | static struct tty_driver *riscom_driver; | 83 | static struct tty_driver *riscom_driver; |
83 | 84 | ||
85 | static DEFINE_SPINLOCK(riscom_lock); | ||
86 | |||
84 | static struct riscom_board rc_board[RC_NBOARD] = { | 87 | static struct riscom_board rc_board[RC_NBOARD] = { |
85 | { | 88 | { |
86 | .base = RC_IOBASE1, | 89 | .base = RC_IOBASE1, |
@@ -217,13 +220,14 @@ static void __init rc_init_CD180(struct riscom_board const * bp) | |||
217 | { | 220 | { |
218 | unsigned long flags; | 221 | unsigned long flags; |
219 | 222 | ||
220 | save_flags(flags); cli(); | 223 | spin_lock_irqsave(&riscom_lock, flags); |
224 | |||
221 | rc_out(bp, RC_CTOUT, 0); /* Clear timeout */ | 225 | rc_out(bp, RC_CTOUT, 0); /* Clear timeout */ |
222 | rc_wait_CCR(bp); /* Wait for CCR ready */ | 226 | rc_wait_CCR(bp); /* Wait for CCR ready */ |
223 | rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */ | 227 | rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */ |
224 | sti(); | 228 | spin_unlock_irqrestore(&riscom_lock, flags); |
225 | msleep(50); /* Delay 0.05 sec */ | 229 | msleep(50); /* Delay 0.05 sec */ |
226 | cli(); | 230 | spin_lock_irqsave(&riscom_lock, flags); |
227 | rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */ | 231 | rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */ |
228 | rc_out(bp, CD180_GICR, 0); /* Clear all bits */ | 232 | rc_out(bp, CD180_GICR, 0); /* Clear all bits */ |
229 | rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */ | 233 | rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */ |
@@ -234,7 +238,7 @@ static void __init rc_init_CD180(struct riscom_board const * bp) | |||
234 | rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8); | 238 | rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8); |
235 | rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff); | 239 | rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff); |
236 | 240 | ||
237 | restore_flags(flags); | 241 | spin_unlock_irqrestore(&riscom_lock, flags); |
238 | } | 242 | } |
239 | 243 | ||
240 | /* Main probing routine, also sets irq. */ | 244 | /* Main probing routine, also sets irq. */ |
@@ -812,9 +816,9 @@ static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port) | |||
812 | } | 816 | } |
813 | port->xmit_buf = (unsigned char *) tmp; | 817 | port->xmit_buf = (unsigned char *) tmp; |
814 | } | 818 | } |
815 | 819 | ||
816 | save_flags(flags); cli(); | 820 | spin_lock_irqsave(&riscom_lock, flags); |
817 | 821 | ||
818 | if (port->tty) | 822 | if (port->tty) |
819 | clear_bit(TTY_IO_ERROR, &port->tty->flags); | 823 | clear_bit(TTY_IO_ERROR, &port->tty->flags); |
820 | 824 | ||
@@ -825,7 +829,7 @@ static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port) | |||
825 | rc_change_speed(bp, port); | 829 | rc_change_speed(bp, port); |
826 | port->flags |= ASYNC_INITIALIZED; | 830 | port->flags |= ASYNC_INITIALIZED; |
827 | 831 | ||
828 | restore_flags(flags); | 832 | spin_unlock_irqrestore(&riscom_lock, flags); |
829 | return 0; | 833 | return 0; |
830 | } | 834 | } |
831 | 835 | ||
@@ -901,6 +905,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
901 | int retval; | 905 | int retval; |
902 | int do_clocal = 0; | 906 | int do_clocal = 0; |
903 | int CD; | 907 | int CD; |
908 | unsigned long flags; | ||
904 | 909 | ||
905 | /* | 910 | /* |
906 | * If the device is in the middle of being closed, then block | 911 | * If the device is in the middle of being closed, then block |
@@ -936,19 +941,26 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
936 | */ | 941 | */ |
937 | retval = 0; | 942 | retval = 0; |
938 | add_wait_queue(&port->open_wait, &wait); | 943 | add_wait_queue(&port->open_wait, &wait); |
939 | cli(); | 944 | |
945 | spin_lock_irqsave(&riscom_lock, flags); | ||
946 | |||
940 | if (!tty_hung_up_p(filp)) | 947 | if (!tty_hung_up_p(filp)) |
941 | port->count--; | 948 | port->count--; |
942 | sti(); | 949 | |
950 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
951 | |||
943 | port->blocked_open++; | 952 | port->blocked_open++; |
944 | while (1) { | 953 | while (1) { |
945 | cli(); | 954 | spin_lock_irqsave(&riscom_lock, flags); |
955 | |||
946 | rc_out(bp, CD180_CAR, port_No(port)); | 956 | rc_out(bp, CD180_CAR, port_No(port)); |
947 | CD = rc_in(bp, CD180_MSVR) & MSVR_CD; | 957 | CD = rc_in(bp, CD180_MSVR) & MSVR_CD; |
948 | rc_out(bp, CD180_MSVR, MSVR_RTS); | 958 | rc_out(bp, CD180_MSVR, MSVR_RTS); |
949 | bp->DTR &= ~(1u << port_No(port)); | 959 | bp->DTR &= ~(1u << port_No(port)); |
950 | rc_out(bp, RC_DTR, bp->DTR); | 960 | rc_out(bp, RC_DTR, bp->DTR); |
951 | sti(); | 961 | |
962 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
963 | |||
952 | set_current_state(TASK_INTERRUPTIBLE); | 964 | set_current_state(TASK_INTERRUPTIBLE); |
953 | if (tty_hung_up_p(filp) || | 965 | if (tty_hung_up_p(filp) || |
954 | !(port->flags & ASYNC_INITIALIZED)) { | 966 | !(port->flags & ASYNC_INITIALIZED)) { |
@@ -1020,8 +1032,9 @@ static void rc_close(struct tty_struct * tty, struct file * filp) | |||
1020 | 1032 | ||
1021 | if (!port || rc_paranoia_check(port, tty->name, "close")) | 1033 | if (!port || rc_paranoia_check(port, tty->name, "close")) |
1022 | return; | 1034 | return; |
1023 | 1035 | ||
1024 | save_flags(flags); cli(); | 1036 | spin_lock_irqsave(&riscom_lock, flags); |
1037 | |||
1025 | if (tty_hung_up_p(filp)) | 1038 | if (tty_hung_up_p(filp)) |
1026 | goto out; | 1039 | goto out; |
1027 | 1040 | ||
@@ -1088,7 +1101,9 @@ static void rc_close(struct tty_struct * tty, struct file * filp) | |||
1088 | } | 1101 | } |
1089 | port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | 1102 | port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); |
1090 | wake_up_interruptible(&port->close_wait); | 1103 | wake_up_interruptible(&port->close_wait); |
1091 | out: restore_flags(flags); | 1104 | |
1105 | out: | ||
1106 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1092 | } | 1107 | } |
1093 | 1108 | ||
1094 | static int rc_write(struct tty_struct * tty, | 1109 | static int rc_write(struct tty_struct * tty, |
@@ -1107,34 +1122,33 @@ static int rc_write(struct tty_struct * tty, | |||
1107 | if (!tty || !port->xmit_buf) | 1122 | if (!tty || !port->xmit_buf) |
1108 | return 0; | 1123 | return 0; |
1109 | 1124 | ||
1110 | save_flags(flags); | ||
1111 | while (1) { | 1125 | while (1) { |
1112 | cli(); | 1126 | spin_lock_irqsave(&riscom_lock, flags); |
1127 | |||
1113 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, | 1128 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, |
1114 | SERIAL_XMIT_SIZE - port->xmit_head)); | 1129 | SERIAL_XMIT_SIZE - port->xmit_head)); |
1115 | if (c <= 0) { | 1130 | if (c <= 0) |
1116 | restore_flags(flags); | 1131 | break; /* lock continues to be held */ |
1117 | break; | ||
1118 | } | ||
1119 | 1132 | ||
1120 | memcpy(port->xmit_buf + port->xmit_head, buf, c); | 1133 | memcpy(port->xmit_buf + port->xmit_head, buf, c); |
1121 | port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); | 1134 | port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); |
1122 | port->xmit_cnt += c; | 1135 | port->xmit_cnt += c; |
1123 | restore_flags(flags); | 1136 | |
1137 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1124 | 1138 | ||
1125 | buf += c; | 1139 | buf += c; |
1126 | count -= c; | 1140 | count -= c; |
1127 | total += c; | 1141 | total += c; |
1128 | } | 1142 | } |
1129 | 1143 | ||
1130 | cli(); | ||
1131 | if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && | 1144 | if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && |
1132 | !(port->IER & IER_TXRDY)) { | 1145 | !(port->IER & IER_TXRDY)) { |
1133 | port->IER |= IER_TXRDY; | 1146 | port->IER |= IER_TXRDY; |
1134 | rc_out(bp, CD180_CAR, port_No(port)); | 1147 | rc_out(bp, CD180_CAR, port_No(port)); |
1135 | rc_out(bp, CD180_IER, port->IER); | 1148 | rc_out(bp, CD180_IER, port->IER); |
1136 | } | 1149 | } |
1137 | restore_flags(flags); | 1150 | |
1151 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1138 | 1152 | ||
1139 | return total; | 1153 | return total; |
1140 | } | 1154 | } |
@@ -1150,7 +1164,7 @@ static void rc_put_char(struct tty_struct * tty, unsigned char ch) | |||
1150 | if (!tty || !port->xmit_buf) | 1164 | if (!tty || !port->xmit_buf) |
1151 | return; | 1165 | return; |
1152 | 1166 | ||
1153 | save_flags(flags); cli(); | 1167 | spin_lock_irqsave(&riscom_lock, flags); |
1154 | 1168 | ||
1155 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) | 1169 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) |
1156 | goto out; | 1170 | goto out; |
@@ -1158,7 +1172,9 @@ static void rc_put_char(struct tty_struct * tty, unsigned char ch) | |||
1158 | port->xmit_buf[port->xmit_head++] = ch; | 1172 | port->xmit_buf[port->xmit_head++] = ch; |
1159 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; | 1173 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; |
1160 | port->xmit_cnt++; | 1174 | port->xmit_cnt++; |
1161 | out: restore_flags(flags); | 1175 | |
1176 | out: | ||
1177 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1162 | } | 1178 | } |
1163 | 1179 | ||
1164 | static void rc_flush_chars(struct tty_struct * tty) | 1180 | static void rc_flush_chars(struct tty_struct * tty) |
@@ -1173,11 +1189,13 @@ static void rc_flush_chars(struct tty_struct * tty) | |||
1173 | !port->xmit_buf) | 1189 | !port->xmit_buf) |
1174 | return; | 1190 | return; |
1175 | 1191 | ||
1176 | save_flags(flags); cli(); | 1192 | spin_lock_irqsave(&riscom_lock, flags); |
1193 | |||
1177 | port->IER |= IER_TXRDY; | 1194 | port->IER |= IER_TXRDY; |
1178 | rc_out(port_Board(port), CD180_CAR, port_No(port)); | 1195 | rc_out(port_Board(port), CD180_CAR, port_No(port)); |
1179 | rc_out(port_Board(port), CD180_IER, port->IER); | 1196 | rc_out(port_Board(port), CD180_IER, port->IER); |
1180 | restore_flags(flags); | 1197 | |
1198 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1181 | } | 1199 | } |
1182 | 1200 | ||
1183 | static int rc_write_room(struct tty_struct * tty) | 1201 | static int rc_write_room(struct tty_struct * tty) |
@@ -1212,9 +1230,11 @@ static void rc_flush_buffer(struct tty_struct *tty) | |||
1212 | if (rc_paranoia_check(port, tty->name, "rc_flush_buffer")) | 1230 | if (rc_paranoia_check(port, tty->name, "rc_flush_buffer")) |
1213 | return; | 1231 | return; |
1214 | 1232 | ||
1215 | save_flags(flags); cli(); | 1233 | spin_lock_irqsave(&riscom_lock, flags); |
1234 | |||
1216 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 1235 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; |
1217 | restore_flags(flags); | 1236 | |
1237 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1218 | 1238 | ||
1219 | tty_wakeup(tty); | 1239 | tty_wakeup(tty); |
1220 | } | 1240 | } |
@@ -1231,11 +1251,15 @@ static int rc_tiocmget(struct tty_struct *tty, struct file *file) | |||
1231 | return -ENODEV; | 1251 | return -ENODEV; |
1232 | 1252 | ||
1233 | bp = port_Board(port); | 1253 | bp = port_Board(port); |
1234 | save_flags(flags); cli(); | 1254 | |
1255 | spin_lock_irqsave(&riscom_lock, flags); | ||
1256 | |||
1235 | rc_out(bp, CD180_CAR, port_No(port)); | 1257 | rc_out(bp, CD180_CAR, port_No(port)); |
1236 | status = rc_in(bp, CD180_MSVR); | 1258 | status = rc_in(bp, CD180_MSVR); |
1237 | result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG; | 1259 | result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG; |
1238 | restore_flags(flags); | 1260 | |
1261 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1262 | |||
1239 | result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0) | 1263 | result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0) |
1240 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) | 1264 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) |
1241 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) | 1265 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) |
@@ -1256,7 +1280,8 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file, | |||
1256 | 1280 | ||
1257 | bp = port_Board(port); | 1281 | bp = port_Board(port); |
1258 | 1282 | ||
1259 | save_flags(flags); cli(); | 1283 | spin_lock_irqsave(&riscom_lock, flags); |
1284 | |||
1260 | if (set & TIOCM_RTS) | 1285 | if (set & TIOCM_RTS) |
1261 | port->MSVR |= MSVR_RTS; | 1286 | port->MSVR |= MSVR_RTS; |
1262 | if (set & TIOCM_DTR) | 1287 | if (set & TIOCM_DTR) |
@@ -1270,7 +1295,9 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file, | |||
1270 | rc_out(bp, CD180_CAR, port_No(port)); | 1295 | rc_out(bp, CD180_CAR, port_No(port)); |
1271 | rc_out(bp, CD180_MSVR, port->MSVR); | 1296 | rc_out(bp, CD180_MSVR, port->MSVR); |
1272 | rc_out(bp, RC_DTR, bp->DTR); | 1297 | rc_out(bp, RC_DTR, bp->DTR); |
1273 | restore_flags(flags); | 1298 | |
1299 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1300 | |||
1274 | return 0; | 1301 | return 0; |
1275 | } | 1302 | } |
1276 | 1303 | ||
@@ -1279,7 +1306,8 @@ static inline void rc_send_break(struct riscom_port * port, unsigned long length | |||
1279 | struct riscom_board *bp = port_Board(port); | 1306 | struct riscom_board *bp = port_Board(port); |
1280 | unsigned long flags; | 1307 | unsigned long flags; |
1281 | 1308 | ||
1282 | save_flags(flags); cli(); | 1309 | spin_lock_irqsave(&riscom_lock, flags); |
1310 | |||
1283 | port->break_length = RISCOM_TPS / HZ * length; | 1311 | port->break_length = RISCOM_TPS / HZ * length; |
1284 | port->COR2 |= COR2_ETC; | 1312 | port->COR2 |= COR2_ETC; |
1285 | port->IER |= IER_TXRDY; | 1313 | port->IER |= IER_TXRDY; |
@@ -1289,7 +1317,8 @@ static inline void rc_send_break(struct riscom_port * port, unsigned long length | |||
1289 | rc_wait_CCR(bp); | 1317 | rc_wait_CCR(bp); |
1290 | rc_out(bp, CD180_CCR, CCR_CORCHG2); | 1318 | rc_out(bp, CD180_CCR, CCR_CORCHG2); |
1291 | rc_wait_CCR(bp); | 1319 | rc_wait_CCR(bp); |
1292 | restore_flags(flags); | 1320 | |
1321 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1293 | } | 1322 | } |
1294 | 1323 | ||
1295 | static inline int rc_set_serial_info(struct riscom_port * port, | 1324 | static inline int rc_set_serial_info(struct riscom_port * port, |
@@ -1298,7 +1327,6 @@ static inline int rc_set_serial_info(struct riscom_port * port, | |||
1298 | struct serial_struct tmp; | 1327 | struct serial_struct tmp; |
1299 | struct riscom_board *bp = port_Board(port); | 1328 | struct riscom_board *bp = port_Board(port); |
1300 | int change_speed; | 1329 | int change_speed; |
1301 | unsigned long flags; | ||
1302 | 1330 | ||
1303 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) | 1331 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) |
1304 | return -EFAULT; | 1332 | return -EFAULT; |
@@ -1332,9 +1360,11 @@ static inline int rc_set_serial_info(struct riscom_port * port, | |||
1332 | port->closing_wait = tmp.closing_wait; | 1360 | port->closing_wait = tmp.closing_wait; |
1333 | } | 1361 | } |
1334 | if (change_speed) { | 1362 | if (change_speed) { |
1335 | save_flags(flags); cli(); | 1363 | unsigned long flags; |
1364 | |||
1365 | spin_lock_irqsave(&riscom_lock, flags); | ||
1336 | rc_change_speed(bp, port); | 1366 | rc_change_speed(bp, port); |
1337 | restore_flags(flags); | 1367 | spin_unlock_irqrestore(&riscom_lock, flags); |
1338 | } | 1368 | } |
1339 | return 0; | 1369 | return 0; |
1340 | } | 1370 | } |
@@ -1414,17 +1444,19 @@ static void rc_throttle(struct tty_struct * tty) | |||
1414 | return; | 1444 | return; |
1415 | 1445 | ||
1416 | bp = port_Board(port); | 1446 | bp = port_Board(port); |
1417 | 1447 | ||
1418 | save_flags(flags); cli(); | 1448 | spin_lock_irqsave(&riscom_lock, flags); |
1449 | |||
1419 | port->MSVR &= ~MSVR_RTS; | 1450 | port->MSVR &= ~MSVR_RTS; |
1420 | rc_out(bp, CD180_CAR, port_No(port)); | 1451 | rc_out(bp, CD180_CAR, port_No(port)); |
1421 | if (I_IXOFF(tty)) { | 1452 | if (I_IXOFF(tty)) { |
1422 | rc_wait_CCR(bp); | 1453 | rc_wait_CCR(bp); |
1423 | rc_out(bp, CD180_CCR, CCR_SSCH2); | 1454 | rc_out(bp, CD180_CCR, CCR_SSCH2); |
1424 | rc_wait_CCR(bp); | 1455 | rc_wait_CCR(bp); |
1425 | } | 1456 | } |
1426 | rc_out(bp, CD180_MSVR, port->MSVR); | 1457 | rc_out(bp, CD180_MSVR, port->MSVR); |
1427 | restore_flags(flags); | 1458 | |
1459 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1428 | } | 1460 | } |
1429 | 1461 | ||
1430 | static void rc_unthrottle(struct tty_struct * tty) | 1462 | static void rc_unthrottle(struct tty_struct * tty) |
@@ -1438,7 +1470,8 @@ static void rc_unthrottle(struct tty_struct * tty) | |||
1438 | 1470 | ||
1439 | bp = port_Board(port); | 1471 | bp = port_Board(port); |
1440 | 1472 | ||
1441 | save_flags(flags); cli(); | 1473 | spin_lock_irqsave(&riscom_lock, flags); |
1474 | |||
1442 | port->MSVR |= MSVR_RTS; | 1475 | port->MSVR |= MSVR_RTS; |
1443 | rc_out(bp, CD180_CAR, port_No(port)); | 1476 | rc_out(bp, CD180_CAR, port_No(port)); |
1444 | if (I_IXOFF(tty)) { | 1477 | if (I_IXOFF(tty)) { |
@@ -1447,7 +1480,8 @@ static void rc_unthrottle(struct tty_struct * tty) | |||
1447 | rc_wait_CCR(bp); | 1480 | rc_wait_CCR(bp); |
1448 | } | 1481 | } |
1449 | rc_out(bp, CD180_MSVR, port->MSVR); | 1482 | rc_out(bp, CD180_MSVR, port->MSVR); |
1450 | restore_flags(flags); | 1483 | |
1484 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1451 | } | 1485 | } |
1452 | 1486 | ||
1453 | static void rc_stop(struct tty_struct * tty) | 1487 | static void rc_stop(struct tty_struct * tty) |
@@ -1461,11 +1495,13 @@ static void rc_stop(struct tty_struct * tty) | |||
1461 | 1495 | ||
1462 | bp = port_Board(port); | 1496 | bp = port_Board(port); |
1463 | 1497 | ||
1464 | save_flags(flags); cli(); | 1498 | spin_lock_irqsave(&riscom_lock, flags); |
1499 | |||
1465 | port->IER &= ~IER_TXRDY; | 1500 | port->IER &= ~IER_TXRDY; |
1466 | rc_out(bp, CD180_CAR, port_No(port)); | 1501 | rc_out(bp, CD180_CAR, port_No(port)); |
1467 | rc_out(bp, CD180_IER, port->IER); | 1502 | rc_out(bp, CD180_IER, port->IER); |
1468 | restore_flags(flags); | 1503 | |
1504 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1469 | } | 1505 | } |
1470 | 1506 | ||
1471 | static void rc_start(struct tty_struct * tty) | 1507 | static void rc_start(struct tty_struct * tty) |
@@ -1479,13 +1515,15 @@ static void rc_start(struct tty_struct * tty) | |||
1479 | 1515 | ||
1480 | bp = port_Board(port); | 1516 | bp = port_Board(port); |
1481 | 1517 | ||
1482 | save_flags(flags); cli(); | 1518 | spin_lock_irqsave(&riscom_lock, flags); |
1519 | |||
1483 | if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) { | 1520 | if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) { |
1484 | port->IER |= IER_TXRDY; | 1521 | port->IER |= IER_TXRDY; |
1485 | rc_out(bp, CD180_CAR, port_No(port)); | 1522 | rc_out(bp, CD180_CAR, port_No(port)); |
1486 | rc_out(bp, CD180_IER, port->IER); | 1523 | rc_out(bp, CD180_IER, port->IER); |
1487 | } | 1524 | } |
1488 | restore_flags(flags); | 1525 | |
1526 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1489 | } | 1527 | } |
1490 | 1528 | ||
1491 | /* | 1529 | /* |
@@ -1537,9 +1575,9 @@ static void rc_set_termios(struct tty_struct * tty, struct ktermios * old_termio | |||
1537 | tty->termios->c_iflag == old_termios->c_iflag) | 1575 | tty->termios->c_iflag == old_termios->c_iflag) |
1538 | return; | 1576 | return; |
1539 | 1577 | ||
1540 | save_flags(flags); cli(); | 1578 | spin_lock_irqsave(&riscom_lock, flags); |
1541 | rc_change_speed(port_Board(port), port); | 1579 | rc_change_speed(port_Board(port), port); |
1542 | restore_flags(flags); | 1580 | spin_unlock_irqrestore(&riscom_lock, flags); |
1543 | 1581 | ||
1544 | if ((old_termios->c_cflag & CRTSCTS) && | 1582 | if ((old_termios->c_cflag & CRTSCTS) && |
1545 | !(tty->termios->c_cflag & CRTSCTS)) { | 1583 | !(tty->termios->c_cflag & CRTSCTS)) { |
@@ -1627,11 +1665,12 @@ static void rc_release_drivers(void) | |||
1627 | { | 1665 | { |
1628 | unsigned long flags; | 1666 | unsigned long flags; |
1629 | 1667 | ||
1630 | save_flags(flags); | 1668 | spin_lock_irqsave(&riscom_lock, flags); |
1631 | cli(); | 1669 | |
1632 | tty_unregister_driver(riscom_driver); | 1670 | tty_unregister_driver(riscom_driver); |
1633 | put_tty_driver(riscom_driver); | 1671 | put_tty_driver(riscom_driver); |
1634 | restore_flags(flags); | 1672 | |
1673 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1635 | } | 1674 | } |
1636 | 1675 | ||
1637 | #ifndef MODULE | 1676 | #ifndef MODULE |