diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 18:34:40 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 18:34:40 -0500 |
commit | 0f4974c439dd7826c85bae4e6a8088ce2db0f498 (patch) | |
tree | fdabc7d9bb7d7bc49aad547c0aac3a633ce01f09 /drivers/char/moxa.c | |
parent | 3126c136bc30225d7a43af741778aa50e95e467a (diff) | |
parent | 36ba782e9674cdc29ec7003757df0b375e99fa96 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (58 commits)
tty: split the lock up a bit further
tty: Move the leader test in disassociate
tty: Push the bkl down a bit in the hangup code
tty: Push the lock down further into the ldisc code
tty: push the BKL down into the handlers a bit
tty: moxa: split open lock
tty: moxa: Kill the use of lock_kernel
tty: moxa: Fix modem op locking
tty: moxa: Kill off the throttle method
tty: moxa: Locking clean up
tty: moxa: rework the locking a bit
tty: moxa: Use more tty_port ops
tty: isicom: fix deadlock on shutdown
tty: mxser: Use the new locking rules to fix setserial properly
tty: mxser: use the tty_port_open method
tty: isicom: sort out the board init logic
tty: isicom: switch to the new tty_port_open helper
tty: tty_port: Add a kref object to the tty port
tty: istallion: tty port open/close methods
tty: stallion: Convert to the tty_port_open/close methods
...
Diffstat (limited to 'drivers/char/moxa.c')
-rw-r--r-- | drivers/char/moxa.c | 289 |
1 files changed, 83 insertions, 206 deletions
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index dd0083bbb64a..63ee3bbc1ce4 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/tty.h> | 34 | #include <linux/tty.h> |
35 | #include <linux/tty_flip.h> | 35 | #include <linux/tty_flip.h> |
36 | #include <linux/major.h> | 36 | #include <linux/major.h> |
37 | #include <linux/smp_lock.h> | ||
38 | #include <linux/string.h> | 37 | #include <linux/string.h> |
39 | #include <linux/fcntl.h> | 38 | #include <linux/fcntl.h> |
40 | #include <linux/ptrace.h> | 39 | #include <linux/ptrace.h> |
@@ -139,7 +138,7 @@ struct moxa_port { | |||
139 | int cflag; | 138 | int cflag; |
140 | unsigned long statusflags; | 139 | unsigned long statusflags; |
141 | 140 | ||
142 | u8 DCDState; | 141 | u8 DCDState; /* Protected by the port lock */ |
143 | u8 lineCtrl; | 142 | u8 lineCtrl; |
144 | u8 lowChkFlag; | 143 | u8 lowChkFlag; |
145 | }; | 144 | }; |
@@ -151,10 +150,9 @@ struct mon_str { | |||
151 | }; | 150 | }; |
152 | 151 | ||
153 | /* statusflags */ | 152 | /* statusflags */ |
154 | #define TXSTOPPED 0x1 | 153 | #define TXSTOPPED 1 |
155 | #define LOWWAIT 0x2 | 154 | #define LOWWAIT 2 |
156 | #define EMPTYWAIT 0x4 | 155 | #define EMPTYWAIT 3 |
157 | #define THROTTLE 0x8 | ||
158 | 156 | ||
159 | #define SERIAL_DO_RESTART | 157 | #define SERIAL_DO_RESTART |
160 | 158 | ||
@@ -165,6 +163,7 @@ static struct mon_str moxaLog; | |||
165 | static unsigned int moxaFuncTout = HZ / 2; | 163 | static unsigned int moxaFuncTout = HZ / 2; |
166 | static unsigned int moxaLowWaterChk; | 164 | static unsigned int moxaLowWaterChk; |
167 | static DEFINE_MUTEX(moxa_openlock); | 165 | static DEFINE_MUTEX(moxa_openlock); |
166 | static DEFINE_SPINLOCK(moxa_lock); | ||
168 | /* Variables for insmod */ | 167 | /* Variables for insmod */ |
169 | #ifdef MODULE | 168 | #ifdef MODULE |
170 | static unsigned long baseaddr[MAX_BOARDS]; | 169 | static unsigned long baseaddr[MAX_BOARDS]; |
@@ -194,8 +193,6 @@ static int moxa_write(struct tty_struct *, const unsigned char *, int); | |||
194 | static int moxa_write_room(struct tty_struct *); | 193 | static int moxa_write_room(struct tty_struct *); |
195 | static void moxa_flush_buffer(struct tty_struct *); | 194 | static void moxa_flush_buffer(struct tty_struct *); |
196 | static int moxa_chars_in_buffer(struct tty_struct *); | 195 | static int moxa_chars_in_buffer(struct tty_struct *); |
197 | static void moxa_throttle(struct tty_struct *); | ||
198 | static void moxa_unthrottle(struct tty_struct *); | ||
199 | static void moxa_set_termios(struct tty_struct *, struct ktermios *); | 196 | static void moxa_set_termios(struct tty_struct *, struct ktermios *); |
200 | static void moxa_stop(struct tty_struct *); | 197 | static void moxa_stop(struct tty_struct *); |
201 | static void moxa_start(struct tty_struct *); | 198 | static void moxa_start(struct tty_struct *); |
@@ -205,9 +202,9 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, | |||
205 | unsigned int set, unsigned int clear); | 202 | unsigned int set, unsigned int clear); |
206 | static void moxa_poll(unsigned long); | 203 | static void moxa_poll(unsigned long); |
207 | static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); | 204 | static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); |
208 | static void moxa_setup_empty_event(struct tty_struct *); | 205 | static void moxa_shutdown(struct tty_port *); |
209 | static void moxa_shut_down(struct tty_struct *); | ||
210 | static int moxa_carrier_raised(struct tty_port *); | 206 | static int moxa_carrier_raised(struct tty_port *); |
207 | static void moxa_dtr_rts(struct tty_port *, int); | ||
211 | /* | 208 | /* |
212 | * moxa board interface functions: | 209 | * moxa board interface functions: |
213 | */ | 210 | */ |
@@ -234,6 +231,8 @@ static void MoxaSetFifo(struct moxa_port *port, int enable); | |||
234 | * I/O functions | 231 | * I/O functions |
235 | */ | 232 | */ |
236 | 233 | ||
234 | static DEFINE_SPINLOCK(moxafunc_lock); | ||
235 | |||
237 | static void moxa_wait_finish(void __iomem *ofsAddr) | 236 | static void moxa_wait_finish(void __iomem *ofsAddr) |
238 | { | 237 | { |
239 | unsigned long end = jiffies + moxaFuncTout; | 238 | unsigned long end = jiffies + moxaFuncTout; |
@@ -247,9 +246,25 @@ static void moxa_wait_finish(void __iomem *ofsAddr) | |||
247 | 246 | ||
248 | static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg) | 247 | static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg) |
249 | { | 248 | { |
249 | unsigned long flags; | ||
250 | spin_lock_irqsave(&moxafunc_lock, flags); | ||
250 | writew(arg, ofsAddr + FuncArg); | 251 | writew(arg, ofsAddr + FuncArg); |
251 | writew(cmd, ofsAddr + FuncCode); | 252 | writew(cmd, ofsAddr + FuncCode); |
252 | moxa_wait_finish(ofsAddr); | 253 | moxa_wait_finish(ofsAddr); |
254 | spin_unlock_irqrestore(&moxafunc_lock, flags); | ||
255 | } | ||
256 | |||
257 | static int moxafuncret(void __iomem *ofsAddr, u16 cmd, u16 arg) | ||
258 | { | ||
259 | unsigned long flags; | ||
260 | u16 ret; | ||
261 | spin_lock_irqsave(&moxafunc_lock, flags); | ||
262 | writew(arg, ofsAddr + FuncArg); | ||
263 | writew(cmd, ofsAddr + FuncCode); | ||
264 | moxa_wait_finish(ofsAddr); | ||
265 | ret = readw(ofsAddr + FuncArg); | ||
266 | spin_unlock_irqrestore(&moxafunc_lock, flags); | ||
267 | return ret; | ||
253 | } | 268 | } |
254 | 269 | ||
255 | static void moxa_low_water_check(void __iomem *ofsAddr) | 270 | static void moxa_low_water_check(void __iomem *ofsAddr) |
@@ -299,22 +314,20 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
299 | struct moxa_port *p; | 314 | struct moxa_port *p; |
300 | unsigned int i, j; | 315 | unsigned int i, j; |
301 | 316 | ||
302 | mutex_lock(&moxa_openlock); | ||
303 | for (i = 0; i < MAX_BOARDS; i++) { | 317 | for (i = 0; i < MAX_BOARDS; i++) { |
304 | p = moxa_boards[i].ports; | 318 | p = moxa_boards[i].ports; |
305 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { | 319 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { |
306 | memset(&tmp, 0, sizeof(tmp)); | 320 | memset(&tmp, 0, sizeof(tmp)); |
321 | spin_lock_bh(&moxa_lock); | ||
307 | if (moxa_boards[i].ready) { | 322 | if (moxa_boards[i].ready) { |
308 | tmp.inq = MoxaPortRxQueue(p); | 323 | tmp.inq = MoxaPortRxQueue(p); |
309 | tmp.outq = MoxaPortTxQueue(p); | 324 | tmp.outq = MoxaPortTxQueue(p); |
310 | } | 325 | } |
311 | if (copy_to_user(argm, &tmp, sizeof(tmp))) { | 326 | spin_unlock_bh(&moxa_lock); |
312 | mutex_unlock(&moxa_openlock); | 327 | if (copy_to_user(argm, &tmp, sizeof(tmp))) |
313 | return -EFAULT; | 328 | return -EFAULT; |
314 | } | ||
315 | } | 329 | } |
316 | } | 330 | } |
317 | mutex_unlock(&moxa_openlock); | ||
318 | break; | 331 | break; |
319 | } case MOXA_GET_OQUEUE: | 332 | } case MOXA_GET_OQUEUE: |
320 | status = MoxaPortTxQueue(ch); | 333 | status = MoxaPortTxQueue(ch); |
@@ -330,16 +343,20 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
330 | struct moxa_port *p; | 343 | struct moxa_port *p; |
331 | unsigned int i, j; | 344 | unsigned int i, j; |
332 | 345 | ||
333 | mutex_lock(&moxa_openlock); | ||
334 | for (i = 0; i < MAX_BOARDS; i++) { | 346 | for (i = 0; i < MAX_BOARDS; i++) { |
335 | p = moxa_boards[i].ports; | 347 | p = moxa_boards[i].ports; |
336 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { | 348 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { |
337 | struct tty_struct *ttyp; | 349 | struct tty_struct *ttyp; |
338 | memset(&tmp, 0, sizeof(tmp)); | 350 | memset(&tmp, 0, sizeof(tmp)); |
339 | if (!moxa_boards[i].ready) | 351 | spin_lock_bh(&moxa_lock); |
352 | if (!moxa_boards[i].ready) { | ||
353 | spin_unlock_bh(&moxa_lock); | ||
340 | goto copy; | 354 | goto copy; |
355 | } | ||
341 | 356 | ||
342 | status = MoxaPortLineStatus(p); | 357 | status = MoxaPortLineStatus(p); |
358 | spin_unlock_bh(&moxa_lock); | ||
359 | |||
343 | if (status & 1) | 360 | if (status & 1) |
344 | tmp.cts = 1; | 361 | tmp.cts = 1; |
345 | if (status & 2) | 362 | if (status & 2) |
@@ -354,24 +371,21 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
354 | tmp.cflag = ttyp->termios->c_cflag; | 371 | tmp.cflag = ttyp->termios->c_cflag; |
355 | tty_kref_put(tty); | 372 | tty_kref_put(tty); |
356 | copy: | 373 | copy: |
357 | if (copy_to_user(argm, &tmp, sizeof(tmp))) { | 374 | if (copy_to_user(argm, &tmp, sizeof(tmp))) |
358 | mutex_unlock(&moxa_openlock); | ||
359 | return -EFAULT; | 375 | return -EFAULT; |
360 | } | ||
361 | } | 376 | } |
362 | } | 377 | } |
363 | mutex_unlock(&moxa_openlock); | ||
364 | break; | 378 | break; |
365 | } | 379 | } |
366 | case TIOCGSERIAL: | 380 | case TIOCGSERIAL: |
367 | mutex_lock(&moxa_openlock); | 381 | mutex_lock(&ch->port.mutex); |
368 | ret = moxa_get_serial_info(ch, argp); | 382 | ret = moxa_get_serial_info(ch, argp); |
369 | mutex_unlock(&moxa_openlock); | 383 | mutex_unlock(&ch->port.mutex); |
370 | break; | 384 | break; |
371 | case TIOCSSERIAL: | 385 | case TIOCSSERIAL: |
372 | mutex_lock(&moxa_openlock); | 386 | mutex_lock(&ch->port.mutex); |
373 | ret = moxa_set_serial_info(ch, argp); | 387 | ret = moxa_set_serial_info(ch, argp); |
374 | mutex_unlock(&moxa_openlock); | 388 | mutex_unlock(&ch->port.mutex); |
375 | break; | 389 | break; |
376 | default: | 390 | default: |
377 | ret = -ENOIOCTLCMD; | 391 | ret = -ENOIOCTLCMD; |
@@ -396,8 +410,6 @@ static const struct tty_operations moxa_ops = { | |||
396 | .flush_buffer = moxa_flush_buffer, | 410 | .flush_buffer = moxa_flush_buffer, |
397 | .chars_in_buffer = moxa_chars_in_buffer, | 411 | .chars_in_buffer = moxa_chars_in_buffer, |
398 | .ioctl = moxa_ioctl, | 412 | .ioctl = moxa_ioctl, |
399 | .throttle = moxa_throttle, | ||
400 | .unthrottle = moxa_unthrottle, | ||
401 | .set_termios = moxa_set_termios, | 413 | .set_termios = moxa_set_termios, |
402 | .stop = moxa_stop, | 414 | .stop = moxa_stop, |
403 | .start = moxa_start, | 415 | .start = moxa_start, |
@@ -409,11 +421,12 @@ static const struct tty_operations moxa_ops = { | |||
409 | 421 | ||
410 | static const struct tty_port_operations moxa_port_ops = { | 422 | static const struct tty_port_operations moxa_port_ops = { |
411 | .carrier_raised = moxa_carrier_raised, | 423 | .carrier_raised = moxa_carrier_raised, |
424 | .dtr_rts = moxa_dtr_rts, | ||
425 | .shutdown = moxa_shutdown, | ||
412 | }; | 426 | }; |
413 | 427 | ||
414 | static struct tty_driver *moxaDriver; | 428 | static struct tty_driver *moxaDriver; |
415 | static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); | 429 | static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); |
416 | static DEFINE_SPINLOCK(moxa_lock); | ||
417 | 430 | ||
418 | /* | 431 | /* |
419 | * HW init | 432 | * HW init |
@@ -1112,14 +1125,12 @@ static void __exit moxa_exit(void) | |||
1112 | module_init(moxa_init); | 1125 | module_init(moxa_init); |
1113 | module_exit(moxa_exit); | 1126 | module_exit(moxa_exit); |
1114 | 1127 | ||
1115 | static void moxa_close_port(struct tty_struct *tty) | 1128 | static void moxa_shutdown(struct tty_port *port) |
1116 | { | 1129 | { |
1117 | struct moxa_port *ch = tty->driver_data; | 1130 | struct moxa_port *ch = container_of(port, struct moxa_port, port); |
1118 | moxa_shut_down(tty); | 1131 | MoxaPortDisable(ch); |
1119 | MoxaPortFlushData(ch, 2); | 1132 | MoxaPortFlushData(ch, 2); |
1120 | ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 1133 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); |
1121 | tty->driver_data = NULL; | ||
1122 | tty_port_tty_set(&ch->port, NULL); | ||
1123 | } | 1134 | } |
1124 | 1135 | ||
1125 | static int moxa_carrier_raised(struct tty_port *port) | 1136 | static int moxa_carrier_raised(struct tty_port *port) |
@@ -1127,45 +1138,19 @@ static int moxa_carrier_raised(struct tty_port *port) | |||
1127 | struct moxa_port *ch = container_of(port, struct moxa_port, port); | 1138 | struct moxa_port *ch = container_of(port, struct moxa_port, port); |
1128 | int dcd; | 1139 | int dcd; |
1129 | 1140 | ||
1130 | spin_lock_bh(&moxa_lock); | 1141 | spin_lock_irq(&port->lock); |
1131 | dcd = ch->DCDState; | 1142 | dcd = ch->DCDState; |
1132 | spin_unlock_bh(&moxa_lock); | 1143 | spin_unlock_irq(&port->lock); |
1133 | return dcd; | 1144 | return dcd; |
1134 | } | 1145 | } |
1135 | 1146 | ||
1136 | static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, | 1147 | static void moxa_dtr_rts(struct tty_port *port, int onoff) |
1137 | struct moxa_port *ch) | ||
1138 | { | 1148 | { |
1139 | struct tty_port *port = &ch->port; | 1149 | struct moxa_port *ch = container_of(port, struct moxa_port, port); |
1140 | DEFINE_WAIT(wait); | 1150 | MoxaPortLineCtrl(ch, onoff, onoff); |
1141 | int retval = 0; | ||
1142 | u8 dcd; | ||
1143 | |||
1144 | while (1) { | ||
1145 | prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); | ||
1146 | if (tty_hung_up_p(filp)) { | ||
1147 | #ifdef SERIAL_DO_RESTART | ||
1148 | retval = -ERESTARTSYS; | ||
1149 | #else | ||
1150 | retval = -EAGAIN; | ||
1151 | #endif | ||
1152 | break; | ||
1153 | } | ||
1154 | dcd = tty_port_carrier_raised(port); | ||
1155 | if (dcd) | ||
1156 | break; | ||
1157 | |||
1158 | if (signal_pending(current)) { | ||
1159 | retval = -ERESTARTSYS; | ||
1160 | break; | ||
1161 | } | ||
1162 | schedule(); | ||
1163 | } | ||
1164 | finish_wait(&port->open_wait, &wait); | ||
1165 | |||
1166 | return retval; | ||
1167 | } | 1151 | } |
1168 | 1152 | ||
1153 | |||
1169 | static int moxa_open(struct tty_struct *tty, struct file *filp) | 1154 | static int moxa_open(struct tty_struct *tty, struct file *filp) |
1170 | { | 1155 | { |
1171 | struct moxa_board_conf *brd; | 1156 | struct moxa_board_conf *brd; |
@@ -1194,6 +1179,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
1194 | ch->port.count++; | 1179 | ch->port.count++; |
1195 | tty->driver_data = ch; | 1180 | tty->driver_data = ch; |
1196 | tty_port_tty_set(&ch->port, tty); | 1181 | tty_port_tty_set(&ch->port, tty); |
1182 | mutex_lock(&ch->port.mutex); | ||
1197 | if (!(ch->port.flags & ASYNC_INITIALIZED)) { | 1183 | if (!(ch->port.flags & ASYNC_INITIALIZED)) { |
1198 | ch->statusflags = 0; | 1184 | ch->statusflags = 0; |
1199 | moxa_set_tty_param(tty, tty->termios); | 1185 | moxa_set_tty_param(tty, tty->termios); |
@@ -1202,58 +1188,20 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
1202 | MoxaSetFifo(ch, ch->type == PORT_16550A); | 1188 | MoxaSetFifo(ch, ch->type == PORT_16550A); |
1203 | ch->port.flags |= ASYNC_INITIALIZED; | 1189 | ch->port.flags |= ASYNC_INITIALIZED; |
1204 | } | 1190 | } |
1191 | mutex_unlock(&ch->port.mutex); | ||
1205 | mutex_unlock(&moxa_openlock); | 1192 | mutex_unlock(&moxa_openlock); |
1206 | 1193 | ||
1207 | retval = 0; | 1194 | retval = tty_port_block_til_ready(&ch->port, tty, filp); |
1208 | if (!(filp->f_flags & O_NONBLOCK) && !C_CLOCAL(tty)) | 1195 | if (retval == 0) |
1209 | retval = moxa_block_till_ready(tty, filp, ch); | 1196 | set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags); |
1210 | mutex_lock(&moxa_openlock); | ||
1211 | if (retval) { | ||
1212 | if (ch->port.count) /* 0 means already hung up... */ | ||
1213 | if (--ch->port.count == 0) | ||
1214 | moxa_close_port(tty); | ||
1215 | } else | ||
1216 | ch->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
1217 | mutex_unlock(&moxa_openlock); | ||
1218 | |||
1219 | return retval; | 1197 | return retval; |
1220 | } | 1198 | } |
1221 | 1199 | ||
1222 | static void moxa_close(struct tty_struct *tty, struct file *filp) | 1200 | static void moxa_close(struct tty_struct *tty, struct file *filp) |
1223 | { | 1201 | { |
1224 | struct moxa_port *ch; | 1202 | struct moxa_port *ch = tty->driver_data; |
1225 | int port; | ||
1226 | |||
1227 | port = tty->index; | ||
1228 | if (port == MAX_PORTS || tty_hung_up_p(filp)) | ||
1229 | return; | ||
1230 | |||
1231 | mutex_lock(&moxa_openlock); | ||
1232 | ch = tty->driver_data; | ||
1233 | if (ch == NULL) | ||
1234 | goto unlock; | ||
1235 | if (tty->count == 1 && ch->port.count != 1) { | ||
1236 | printk(KERN_WARNING "moxa_close: bad serial port count; " | ||
1237 | "tty->count is 1, ch->port.count is %d\n", ch->port.count); | ||
1238 | ch->port.count = 1; | ||
1239 | } | ||
1240 | if (--ch->port.count < 0) { | ||
1241 | printk(KERN_WARNING "moxa_close: bad serial port count, " | ||
1242 | "device=%s\n", tty->name); | ||
1243 | ch->port.count = 0; | ||
1244 | } | ||
1245 | if (ch->port.count) | ||
1246 | goto unlock; | ||
1247 | |||
1248 | ch->cflag = tty->termios->c_cflag; | 1203 | ch->cflag = tty->termios->c_cflag; |
1249 | if (ch->port.flags & ASYNC_INITIALIZED) { | 1204 | tty_port_close(&ch->port, tty, filp); |
1250 | moxa_setup_empty_event(tty); | ||
1251 | tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ | ||
1252 | } | ||
1253 | |||
1254 | moxa_close_port(tty); | ||
1255 | unlock: | ||
1256 | mutex_unlock(&moxa_openlock); | ||
1257 | } | 1205 | } |
1258 | 1206 | ||
1259 | static int moxa_write(struct tty_struct *tty, | 1207 | static int moxa_write(struct tty_struct *tty, |
@@ -1269,7 +1217,7 @@ static int moxa_write(struct tty_struct *tty, | |||
1269 | len = MoxaPortWriteData(tty, buf, count); | 1217 | len = MoxaPortWriteData(tty, buf, count); |
1270 | spin_unlock_bh(&moxa_lock); | 1218 | spin_unlock_bh(&moxa_lock); |
1271 | 1219 | ||
1272 | ch->statusflags |= LOWWAIT; | 1220 | set_bit(LOWWAIT, &ch->statusflags); |
1273 | return len; | 1221 | return len; |
1274 | } | 1222 | } |
1275 | 1223 | ||
@@ -1300,40 +1248,21 @@ static int moxa_chars_in_buffer(struct tty_struct *tty) | |||
1300 | struct moxa_port *ch = tty->driver_data; | 1248 | struct moxa_port *ch = tty->driver_data; |
1301 | int chars; | 1249 | int chars; |
1302 | 1250 | ||
1303 | /* | ||
1304 | * Sigh...I have to check if driver_data is NULL here, because | ||
1305 | * if an open() fails, the TTY subsystem eventually calls | ||
1306 | * tty_wait_until_sent(), which calls the driver's chars_in_buffer() | ||
1307 | * routine. And since the open() failed, we return 0 here. TDJ | ||
1308 | */ | ||
1309 | if (ch == NULL) | ||
1310 | return 0; | ||
1311 | lock_kernel(); | ||
1312 | chars = MoxaPortTxQueue(ch); | 1251 | chars = MoxaPortTxQueue(ch); |
1313 | if (chars) { | 1252 | if (chars) |
1314 | /* | 1253 | /* |
1315 | * Make it possible to wakeup anything waiting for output | 1254 | * Make it possible to wakeup anything waiting for output |
1316 | * in tty_ioctl.c, etc. | 1255 | * in tty_ioctl.c, etc. |
1317 | */ | 1256 | */ |
1318 | if (!(ch->statusflags & EMPTYWAIT)) | 1257 | set_bit(EMPTYWAIT, &ch->statusflags); |
1319 | moxa_setup_empty_event(tty); | ||
1320 | } | ||
1321 | unlock_kernel(); | ||
1322 | return chars; | 1258 | return chars; |
1323 | } | 1259 | } |
1324 | 1260 | ||
1325 | static int moxa_tiocmget(struct tty_struct *tty, struct file *file) | 1261 | static int moxa_tiocmget(struct tty_struct *tty, struct file *file) |
1326 | { | 1262 | { |
1327 | struct moxa_port *ch; | 1263 | struct moxa_port *ch = tty->driver_data; |
1328 | int flag = 0, dtr, rts; | 1264 | int flag = 0, dtr, rts; |
1329 | 1265 | ||
1330 | mutex_lock(&moxa_openlock); | ||
1331 | ch = tty->driver_data; | ||
1332 | if (!ch) { | ||
1333 | mutex_unlock(&moxa_openlock); | ||
1334 | return -EINVAL; | ||
1335 | } | ||
1336 | |||
1337 | MoxaPortGetLineOut(ch, &dtr, &rts); | 1266 | MoxaPortGetLineOut(ch, &dtr, &rts); |
1338 | if (dtr) | 1267 | if (dtr) |
1339 | flag |= TIOCM_DTR; | 1268 | flag |= TIOCM_DTR; |
@@ -1346,7 +1275,6 @@ static int moxa_tiocmget(struct tty_struct *tty, struct file *file) | |||
1346 | flag |= TIOCM_DSR; | 1275 | flag |= TIOCM_DSR; |
1347 | if (dtr & 4) | 1276 | if (dtr & 4) |
1348 | flag |= TIOCM_CD; | 1277 | flag |= TIOCM_CD; |
1349 | mutex_unlock(&moxa_openlock); | ||
1350 | return flag; | 1278 | return flag; |
1351 | } | 1279 | } |
1352 | 1280 | ||
@@ -1379,20 +1307,6 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, | |||
1379 | return 0; | 1307 | return 0; |
1380 | } | 1308 | } |
1381 | 1309 | ||
1382 | static void moxa_throttle(struct tty_struct *tty) | ||
1383 | { | ||
1384 | struct moxa_port *ch = tty->driver_data; | ||
1385 | |||
1386 | ch->statusflags |= THROTTLE; | ||
1387 | } | ||
1388 | |||
1389 | static void moxa_unthrottle(struct tty_struct *tty) | ||
1390 | { | ||
1391 | struct moxa_port *ch = tty->driver_data; | ||
1392 | |||
1393 | ch->statusflags &= ~THROTTLE; | ||
1394 | } | ||
1395 | |||
1396 | static void moxa_set_termios(struct tty_struct *tty, | 1310 | static void moxa_set_termios(struct tty_struct *tty, |
1397 | struct ktermios *old_termios) | 1311 | struct ktermios *old_termios) |
1398 | { | 1312 | { |
@@ -1412,7 +1326,7 @@ static void moxa_stop(struct tty_struct *tty) | |||
1412 | if (ch == NULL) | 1326 | if (ch == NULL) |
1413 | return; | 1327 | return; |
1414 | MoxaPortTxDisable(ch); | 1328 | MoxaPortTxDisable(ch); |
1415 | ch->statusflags |= TXSTOPPED; | 1329 | set_bit(TXSTOPPED, &ch->statusflags); |
1416 | } | 1330 | } |
1417 | 1331 | ||
1418 | 1332 | ||
@@ -1427,38 +1341,32 @@ static void moxa_start(struct tty_struct *tty) | |||
1427 | return; | 1341 | return; |
1428 | 1342 | ||
1429 | MoxaPortTxEnable(ch); | 1343 | MoxaPortTxEnable(ch); |
1430 | ch->statusflags &= ~TXSTOPPED; | 1344 | clear_bit(TXSTOPPED, &ch->statusflags); |
1431 | } | 1345 | } |
1432 | 1346 | ||
1433 | static void moxa_hangup(struct tty_struct *tty) | 1347 | static void moxa_hangup(struct tty_struct *tty) |
1434 | { | 1348 | { |
1435 | struct moxa_port *ch; | 1349 | struct moxa_port *ch = tty->driver_data; |
1436 | 1350 | tty_port_hangup(&ch->port); | |
1437 | mutex_lock(&moxa_openlock); | ||
1438 | ch = tty->driver_data; | ||
1439 | if (ch == NULL) { | ||
1440 | mutex_unlock(&moxa_openlock); | ||
1441 | return; | ||
1442 | } | ||
1443 | ch->port.count = 0; | ||
1444 | moxa_close_port(tty); | ||
1445 | mutex_unlock(&moxa_openlock); | ||
1446 | |||
1447 | wake_up_interruptible(&ch->port.open_wait); | ||
1448 | } | 1351 | } |
1449 | 1352 | ||
1450 | static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) | 1353 | static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) |
1451 | { | 1354 | { |
1452 | struct tty_struct *tty; | 1355 | struct tty_struct *tty; |
1356 | unsigned long flags; | ||
1453 | dcd = !!dcd; | 1357 | dcd = !!dcd; |
1454 | 1358 | ||
1359 | spin_lock_irqsave(&p->port.lock, flags); | ||
1455 | if (dcd != p->DCDState) { | 1360 | if (dcd != p->DCDState) { |
1361 | p->DCDState = dcd; | ||
1362 | spin_unlock_irqrestore(&p->port.lock, flags); | ||
1456 | tty = tty_port_tty_get(&p->port); | 1363 | tty = tty_port_tty_get(&p->port); |
1457 | if (tty && C_CLOCAL(tty) && !dcd) | 1364 | if (tty && C_CLOCAL(tty) && !dcd) |
1458 | tty_hangup(tty); | 1365 | tty_hangup(tty); |
1459 | tty_kref_put(tty); | 1366 | tty_kref_put(tty); |
1460 | } | 1367 | } |
1461 | p->DCDState = dcd; | 1368 | else |
1369 | spin_unlock_irqrestore(&p->port.lock, flags); | ||
1462 | } | 1370 | } |
1463 | 1371 | ||
1464 | static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | 1372 | static int moxa_poll_port(struct moxa_port *p, unsigned int handle, |
@@ -1470,24 +1378,24 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | |||
1470 | u16 intr; | 1378 | u16 intr; |
1471 | 1379 | ||
1472 | if (tty) { | 1380 | if (tty) { |
1473 | if ((p->statusflags & EMPTYWAIT) && | 1381 | if (test_bit(EMPTYWAIT, &p->statusflags) && |
1474 | MoxaPortTxQueue(p) == 0) { | 1382 | MoxaPortTxQueue(p) == 0) { |
1475 | p->statusflags &= ~EMPTYWAIT; | 1383 | clear_bit(EMPTYWAIT, &p->statusflags); |
1476 | tty_wakeup(tty); | 1384 | tty_wakeup(tty); |
1477 | } | 1385 | } |
1478 | if ((p->statusflags & LOWWAIT) && !tty->stopped && | 1386 | if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped && |
1479 | MoxaPortTxQueue(p) <= WAKEUP_CHARS) { | 1387 | MoxaPortTxQueue(p) <= WAKEUP_CHARS) { |
1480 | p->statusflags &= ~LOWWAIT; | 1388 | clear_bit(LOWWAIT, &p->statusflags); |
1481 | tty_wakeup(tty); | 1389 | tty_wakeup(tty); |
1482 | } | 1390 | } |
1483 | 1391 | ||
1484 | if (inited && !(p->statusflags & THROTTLE) && | 1392 | if (inited && !test_bit(TTY_THROTTLED, &tty->flags) && |
1485 | MoxaPortRxQueue(p) > 0) { /* RX */ | 1393 | MoxaPortRxQueue(p) > 0) { /* RX */ |
1486 | MoxaPortReadData(p); | 1394 | MoxaPortReadData(p); |
1487 | tty_schedule_flip(tty); | 1395 | tty_schedule_flip(tty); |
1488 | } | 1396 | } |
1489 | } else { | 1397 | } else { |
1490 | p->statusflags &= ~EMPTYWAIT; | 1398 | clear_bit(EMPTYWAIT, &p->statusflags); |
1491 | MoxaPortFlushData(p, 0); /* flush RX */ | 1399 | MoxaPortFlushData(p, 0); /* flush RX */ |
1492 | } | 1400 | } |
1493 | 1401 | ||
@@ -1588,35 +1496,6 @@ static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_term | |||
1588 | tty_encode_baud_rate(tty, baud, baud); | 1496 | tty_encode_baud_rate(tty, baud, baud); |
1589 | } | 1497 | } |
1590 | 1498 | ||
1591 | static void moxa_setup_empty_event(struct tty_struct *tty) | ||
1592 | { | ||
1593 | struct moxa_port *ch = tty->driver_data; | ||
1594 | |||
1595 | spin_lock_bh(&moxa_lock); | ||
1596 | ch->statusflags |= EMPTYWAIT; | ||
1597 | spin_unlock_bh(&moxa_lock); | ||
1598 | } | ||
1599 | |||
1600 | static void moxa_shut_down(struct tty_struct *tty) | ||
1601 | { | ||
1602 | struct moxa_port *ch = tty->driver_data; | ||
1603 | |||
1604 | if (!(ch->port.flags & ASYNC_INITIALIZED)) | ||
1605 | return; | ||
1606 | |||
1607 | MoxaPortDisable(ch); | ||
1608 | |||
1609 | /* | ||
1610 | * If we're a modem control device and HUPCL is on, drop RTS & DTR. | ||
1611 | */ | ||
1612 | if (C_HUPCL(tty)) | ||
1613 | MoxaPortLineCtrl(ch, 0, 0); | ||
1614 | |||
1615 | spin_lock_bh(&moxa_lock); | ||
1616 | ch->port.flags &= ~ASYNC_INITIALIZED; | ||
1617 | spin_unlock_bh(&moxa_lock); | ||
1618 | } | ||
1619 | |||
1620 | /***************************************************************************** | 1499 | /***************************************************************************** |
1621 | * Driver level functions: * | 1500 | * Driver level functions: * |
1622 | *****************************************************************************/ | 1501 | *****************************************************************************/ |
@@ -1918,10 +1797,12 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, | |||
1918 | baud = MoxaPortSetBaud(port, baud); | 1797 | baud = MoxaPortSetBaud(port, baud); |
1919 | 1798 | ||
1920 | if (termio->c_iflag & (IXON | IXOFF | IXANY)) { | 1799 | if (termio->c_iflag & (IXON | IXOFF | IXANY)) { |
1800 | spin_lock_irq(&moxafunc_lock); | ||
1921 | writeb(termio->c_cc[VSTART], ofsAddr + FuncArg); | 1801 | writeb(termio->c_cc[VSTART], ofsAddr + FuncArg); |
1922 | writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); | 1802 | writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); |
1923 | writeb(FC_SetXonXoff, ofsAddr + FuncCode); | 1803 | writeb(FC_SetXonXoff, ofsAddr + FuncCode); |
1924 | moxa_wait_finish(ofsAddr); | 1804 | moxa_wait_finish(ofsAddr); |
1805 | spin_unlock_irq(&moxafunc_lock); | ||
1925 | 1806 | ||
1926 | } | 1807 | } |
1927 | return baud; | 1808 | return baud; |
@@ -1974,18 +1855,14 @@ static int MoxaPortLineStatus(struct moxa_port *port) | |||
1974 | int val; | 1855 | int val; |
1975 | 1856 | ||
1976 | ofsAddr = port->tableAddr; | 1857 | ofsAddr = port->tableAddr; |
1977 | if (MOXA_IS_320(port->board)) { | 1858 | if (MOXA_IS_320(port->board)) |
1978 | moxafunc(ofsAddr, FC_LineStatus, 0); | 1859 | val = moxafuncret(ofsAddr, FC_LineStatus, 0); |
1979 | val = readw(ofsAddr + FuncArg); | 1860 | else |
1980 | } else { | ||
1981 | val = readw(ofsAddr + FlagStat) >> 4; | 1861 | val = readw(ofsAddr + FlagStat) >> 4; |
1982 | } | ||
1983 | val &= 0x0B; | 1862 | val &= 0x0B; |
1984 | if (val & 8) | 1863 | if (val & 8) |
1985 | val |= 4; | 1864 | val |= 4; |
1986 | spin_lock_bh(&moxa_lock); | ||
1987 | moxa_new_dcdstate(port, val & 8); | 1865 | moxa_new_dcdstate(port, val & 8); |
1988 | spin_unlock_bh(&moxa_lock); | ||
1989 | val &= 7; | 1866 | val &= 7; |
1990 | return val; | 1867 | return val; |
1991 | } | 1868 | } |