diff options
author | Alan Cox <alan@linux.intel.com> | 2009-11-30 08:18:02 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 18:18:07 -0500 |
commit | a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539 (patch) | |
tree | 9f00e6494e1ee25d29f979d8723ac361003e03d4 /drivers/char | |
parent | f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5b (diff) |
tty: moxa: Locking clean up
- The open lock is needed to fix up the case of a board reset occuring during
tty open but too early for a sane hangup response.
- The lock can however got for other cases
- Use the port mutex for get/setserial
- Fix up the confused lack of locking on the THROTTLE and other bits in the
private flags. Just use set/test/clear bit and it covers the cases we need
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/moxa.c | 58 |
1 files changed, 25 insertions, 33 deletions
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 474d936d3b31..7ab720f1f30c 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -151,10 +151,10 @@ struct mon_str { | |||
151 | }; | 151 | }; |
152 | 152 | ||
153 | /* statusflags */ | 153 | /* statusflags */ |
154 | #define TXSTOPPED 0x1 | 154 | #define TXSTOPPED 1 |
155 | #define LOWWAIT 0x2 | 155 | #define LOWWAIT 2 |
156 | #define EMPTYWAIT 0x4 | 156 | #define EMPTYWAIT 3 |
157 | #define THROTTLE 0x8 | 157 | #define THROTTLE 4 |
158 | 158 | ||
159 | #define SERIAL_DO_RESTART | 159 | #define SERIAL_DO_RESTART |
160 | 160 | ||
@@ -235,6 +235,8 @@ static void MoxaSetFifo(struct moxa_port *port, int enable); | |||
235 | * I/O functions | 235 | * I/O functions |
236 | */ | 236 | */ |
237 | 237 | ||
238 | static DEFINE_SPINLOCK(moxafunc_lock); | ||
239 | |||
238 | static void moxa_wait_finish(void __iomem *ofsAddr) | 240 | static void moxa_wait_finish(void __iomem *ofsAddr) |
239 | { | 241 | { |
240 | unsigned long end = jiffies + moxaFuncTout; | 242 | unsigned long end = jiffies + moxaFuncTout; |
@@ -381,14 +383,14 @@ copy: | |||
381 | break; | 383 | break; |
382 | } | 384 | } |
383 | case TIOCGSERIAL: | 385 | case TIOCGSERIAL: |
384 | mutex_lock(&moxa_openlock); | 386 | mutex_lock(&ch->port.mutex); |
385 | ret = moxa_get_serial_info(ch, argp); | 387 | ret = moxa_get_serial_info(ch, argp); |
386 | mutex_unlock(&moxa_openlock); | 388 | mutex_unlock(&ch->port.mutex); |
387 | break; | 389 | break; |
388 | case TIOCSSERIAL: | 390 | case TIOCSSERIAL: |
389 | mutex_lock(&moxa_openlock); | 391 | mutex_lock(&ch->port.mutex); |
390 | ret = moxa_set_serial_info(ch, argp); | 392 | ret = moxa_set_serial_info(ch, argp); |
391 | mutex_unlock(&moxa_openlock); | 393 | mutex_unlock(&ch->port.mutex); |
392 | break; | 394 | break; |
393 | default: | 395 | default: |
394 | ret = -ENOIOCTLCMD; | 396 | ret = -ENOIOCTLCMD; |
@@ -433,7 +435,6 @@ static const struct tty_port_operations moxa_port_ops = { | |||
433 | static struct tty_driver *moxaDriver; | 435 | static struct tty_driver *moxaDriver; |
434 | static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); | 436 | static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); |
435 | static DEFINE_SPINLOCK(moxa_lock); | 437 | static DEFINE_SPINLOCK(moxa_lock); |
436 | static DEFINE_SPINLOCK(moxafunc_lock); | ||
437 | 438 | ||
438 | /* | 439 | /* |
439 | * HW init | 440 | * HW init |
@@ -1208,9 +1209,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp) | |||
1208 | { | 1209 | { |
1209 | struct moxa_port *ch = tty->driver_data; | 1210 | struct moxa_port *ch = tty->driver_data; |
1210 | ch->cflag = tty->termios->c_cflag; | 1211 | ch->cflag = tty->termios->c_cflag; |
1211 | mutex_lock(&moxa_openlock); | ||
1212 | tty_port_close(&ch->port, tty, filp); | 1212 | tty_port_close(&ch->port, tty, filp); |
1213 | mutex_unlock(&moxa_openlock); | ||
1214 | } | 1213 | } |
1215 | 1214 | ||
1216 | static int moxa_write(struct tty_struct *tty, | 1215 | static int moxa_write(struct tty_struct *tty, |
@@ -1226,7 +1225,7 @@ static int moxa_write(struct tty_struct *tty, | |||
1226 | len = MoxaPortWriteData(tty, buf, count); | 1225 | len = MoxaPortWriteData(tty, buf, count); |
1227 | spin_unlock_bh(&moxa_lock); | 1226 | spin_unlock_bh(&moxa_lock); |
1228 | 1227 | ||
1229 | ch->statusflags |= LOWWAIT; | 1228 | set_bit(LOWWAIT, &ch->statusflags); |
1230 | return len; | 1229 | return len; |
1231 | } | 1230 | } |
1232 | 1231 | ||
@@ -1264,7 +1263,7 @@ static int moxa_chars_in_buffer(struct tty_struct *tty) | |||
1264 | * Make it possible to wakeup anything waiting for output | 1263 | * Make it possible to wakeup anything waiting for output |
1265 | * in tty_ioctl.c, etc. | 1264 | * in tty_ioctl.c, etc. |
1266 | */ | 1265 | */ |
1267 | if (!(ch->statusflags & EMPTYWAIT)) | 1266 | if (!test_bit(EMPTYWAIT, &ch->statusflags)) |
1268 | moxa_setup_empty_event(tty); | 1267 | moxa_setup_empty_event(tty); |
1269 | } | 1268 | } |
1270 | unlock_kernel(); | 1269 | unlock_kernel(); |
@@ -1332,14 +1331,14 @@ static void moxa_throttle(struct tty_struct *tty) | |||
1332 | { | 1331 | { |
1333 | struct moxa_port *ch = tty->driver_data; | 1332 | struct moxa_port *ch = tty->driver_data; |
1334 | 1333 | ||
1335 | ch->statusflags |= THROTTLE; | 1334 | set_bit(THROTTLE, &ch->statusflags); |
1336 | } | 1335 | } |
1337 | 1336 | ||
1338 | static void moxa_unthrottle(struct tty_struct *tty) | 1337 | static void moxa_unthrottle(struct tty_struct *tty) |
1339 | { | 1338 | { |
1340 | struct moxa_port *ch = tty->driver_data; | 1339 | struct moxa_port *ch = tty->driver_data; |
1341 | 1340 | ||
1342 | ch->statusflags &= ~THROTTLE; | 1341 | clear_bit(THROTTLE, &ch->statusflags); |
1343 | } | 1342 | } |
1344 | 1343 | ||
1345 | static void moxa_set_termios(struct tty_struct *tty, | 1344 | static void moxa_set_termios(struct tty_struct *tty, |
@@ -1361,7 +1360,7 @@ static void moxa_stop(struct tty_struct *tty) | |||
1361 | if (ch == NULL) | 1360 | if (ch == NULL) |
1362 | return; | 1361 | return; |
1363 | MoxaPortTxDisable(ch); | 1362 | MoxaPortTxDisable(ch); |
1364 | ch->statusflags |= TXSTOPPED; | 1363 | set_bit(TXSTOPPED, &ch->statusflags); |
1365 | } | 1364 | } |
1366 | 1365 | ||
1367 | 1366 | ||
@@ -1376,17 +1375,13 @@ static void moxa_start(struct tty_struct *tty) | |||
1376 | return; | 1375 | return; |
1377 | 1376 | ||
1378 | MoxaPortTxEnable(ch); | 1377 | MoxaPortTxEnable(ch); |
1379 | ch->statusflags &= ~TXSTOPPED; | 1378 | clear_bit(TXSTOPPED, &ch->statusflags); |
1380 | } | 1379 | } |
1381 | 1380 | ||
1382 | static void moxa_hangup(struct tty_struct *tty) | 1381 | static void moxa_hangup(struct tty_struct *tty) |
1383 | { | 1382 | { |
1384 | struct moxa_port *ch; | 1383 | struct moxa_port *ch = tty->driver_data; |
1385 | |||
1386 | mutex_lock(&moxa_openlock); | ||
1387 | ch = tty->driver_data; | ||
1388 | tty_port_hangup(&ch->port); | 1384 | tty_port_hangup(&ch->port); |
1389 | mutex_unlock(&moxa_openlock); | ||
1390 | } | 1385 | } |
1391 | 1386 | ||
1392 | static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) | 1387 | static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) |
@@ -1412,24 +1407,24 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | |||
1412 | u16 intr; | 1407 | u16 intr; |
1413 | 1408 | ||
1414 | if (tty) { | 1409 | if (tty) { |
1415 | if ((p->statusflags & EMPTYWAIT) && | 1410 | if (test_bit(EMPTYWAIT, &p->statusflags) && |
1416 | MoxaPortTxQueue(p) == 0) { | 1411 | MoxaPortTxQueue(p) == 0) { |
1417 | p->statusflags &= ~EMPTYWAIT; | 1412 | clear_bit(EMPTYWAIT, &p->statusflags); |
1418 | tty_wakeup(tty); | 1413 | tty_wakeup(tty); |
1419 | } | 1414 | } |
1420 | if ((p->statusflags & LOWWAIT) && !tty->stopped && | 1415 | if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped && |
1421 | MoxaPortTxQueue(p) <= WAKEUP_CHARS) { | 1416 | MoxaPortTxQueue(p) <= WAKEUP_CHARS) { |
1422 | p->statusflags &= ~LOWWAIT; | 1417 | clear_bit(LOWWAIT, &p->statusflags); |
1423 | tty_wakeup(tty); | 1418 | tty_wakeup(tty); |
1424 | } | 1419 | } |
1425 | 1420 | ||
1426 | if (inited && !(p->statusflags & THROTTLE) && | 1421 | if (inited && !test_bit(THROTTLE, &p->statusflags) && |
1427 | MoxaPortRxQueue(p) > 0) { /* RX */ | 1422 | MoxaPortRxQueue(p) > 0) { /* RX */ |
1428 | MoxaPortReadData(p); | 1423 | MoxaPortReadData(p); |
1429 | tty_schedule_flip(tty); | 1424 | tty_schedule_flip(tty); |
1430 | } | 1425 | } |
1431 | } else { | 1426 | } else { |
1432 | p->statusflags &= ~EMPTYWAIT; | 1427 | clear_bit(EMPTYWAIT, &p->statusflags); |
1433 | MoxaPortFlushData(p, 0); /* flush RX */ | 1428 | MoxaPortFlushData(p, 0); /* flush RX */ |
1434 | } | 1429 | } |
1435 | 1430 | ||
@@ -1533,10 +1528,7 @@ static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_term | |||
1533 | static void moxa_setup_empty_event(struct tty_struct *tty) | 1528 | static void moxa_setup_empty_event(struct tty_struct *tty) |
1534 | { | 1529 | { |
1535 | struct moxa_port *ch = tty->driver_data; | 1530 | struct moxa_port *ch = tty->driver_data; |
1536 | 1531 | set_bit(EMPTYWAIT, &ch->statusflags); | |
1537 | spin_lock_bh(&moxa_lock); | ||
1538 | ch->statusflags |= EMPTYWAIT; | ||
1539 | spin_unlock_bh(&moxa_lock); | ||
1540 | } | 1532 | } |
1541 | 1533 | ||
1542 | /***************************************************************************** | 1534 | /***************************************************************************** |
@@ -1845,7 +1837,7 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, | |||
1845 | writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); | 1837 | writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); |
1846 | writeb(FC_SetXonXoff, ofsAddr + FuncCode); | 1838 | writeb(FC_SetXonXoff, ofsAddr + FuncCode); |
1847 | moxa_wait_finish(ofsAddr); | 1839 | moxa_wait_finish(ofsAddr); |
1848 | spin_unlock_irqrestore(&moxafunc_lock); | 1840 | spin_unlock_irq(&moxafunc_lock); |
1849 | 1841 | ||
1850 | } | 1842 | } |
1851 | return baud; | 1843 | return baud; |