diff options
author | Alan Cox <alan@redhat.com> | 2008-10-13 05:39:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-13 12:51:41 -0400 |
commit | d450b5a0196b6442cf3f29fc611d9c8daa56b559 (patch) | |
tree | 2a6b641b033bfbe16b194897ddbc988544dcefc2 /drivers/char/moxa.c | |
parent | 4a90f09b20f4622dcbff1f0e1e6bae1704f8ad8c (diff) |
tty: kref usage for isicom and moxa
Rather than blindly keep taking krefs we reorder the code in a few places
to pass the tty down to the right place (which is important as from the user
side it is not the case that tty == port->tty in all situations). For the irq
and related paths use the krefs to stop the tty being freed under us.
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/moxa.c')
-rw-r--r-- | drivers/char/moxa.c | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index d3d7864e0c1e..5df4003ad873 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -205,7 +205,7 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, | |||
205 | static void moxa_poll(unsigned long); | 205 | static void moxa_poll(unsigned long); |
206 | static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); | 206 | static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); |
207 | static void moxa_setup_empty_event(struct tty_struct *); | 207 | static void moxa_setup_empty_event(struct tty_struct *); |
208 | static void moxa_shut_down(struct moxa_port *); | 208 | static void moxa_shut_down(struct tty_struct *); |
209 | /* | 209 | /* |
210 | * moxa board interface functions: | 210 | * moxa board interface functions: |
211 | */ | 211 | */ |
@@ -217,7 +217,7 @@ static void MoxaPortLineCtrl(struct moxa_port *, int, int); | |||
217 | static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int); | 217 | static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int); |
218 | static int MoxaPortLineStatus(struct moxa_port *); | 218 | static int MoxaPortLineStatus(struct moxa_port *); |
219 | static void MoxaPortFlushData(struct moxa_port *, int); | 219 | static void MoxaPortFlushData(struct moxa_port *, int); |
220 | static int MoxaPortWriteData(struct moxa_port *, const unsigned char *, int); | 220 | static int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int); |
221 | static int MoxaPortReadData(struct moxa_port *); | 221 | static int MoxaPortReadData(struct moxa_port *); |
222 | static int MoxaPortTxQueue(struct moxa_port *); | 222 | static int MoxaPortTxQueue(struct moxa_port *); |
223 | static int MoxaPortRxQueue(struct moxa_port *); | 223 | static int MoxaPortRxQueue(struct moxa_port *); |
@@ -332,6 +332,7 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
332 | for (i = 0; i < MAX_BOARDS; i++) { | 332 | for (i = 0; i < MAX_BOARDS; i++) { |
333 | p = moxa_boards[i].ports; | 333 | p = moxa_boards[i].ports; |
334 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { | 334 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { |
335 | struct tty_struct *ttyp; | ||
335 | memset(&tmp, 0, sizeof(tmp)); | 336 | memset(&tmp, 0, sizeof(tmp)); |
336 | if (!moxa_boards[i].ready) | 337 | if (!moxa_boards[i].ready) |
337 | goto copy; | 338 | goto copy; |
@@ -344,10 +345,12 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
344 | if (status & 4) | 345 | if (status & 4) |
345 | tmp.dcd = 1; | 346 | tmp.dcd = 1; |
346 | 347 | ||
347 | if (!p->port.tty || !p->port.tty->termios) | 348 | ttyp = tty_port_tty_get(&p->port); |
349 | if (!ttyp || !ttyp->termios) | ||
348 | tmp.cflag = p->cflag; | 350 | tmp.cflag = p->cflag; |
349 | else | 351 | else |
350 | tmp.cflag = p->port.tty->termios->c_cflag; | 352 | tmp.cflag = ttyp->termios->c_cflag; |
353 | tty_kref_put(tty); | ||
351 | copy: | 354 | copy: |
352 | if (copy_to_user(argm, &tmp, sizeof(tmp))) { | 355 | if (copy_to_user(argm, &tmp, sizeof(tmp))) { |
353 | mutex_unlock(&moxa_openlock); | 356 | mutex_unlock(&moxa_openlock); |
@@ -880,8 +883,14 @@ static void moxa_board_deinit(struct moxa_board_conf *brd) | |||
880 | 883 | ||
881 | /* pci hot-un-plug support */ | 884 | /* pci hot-un-plug support */ |
882 | for (a = 0; a < brd->numPorts; a++) | 885 | for (a = 0; a < brd->numPorts; a++) |
883 | if (brd->ports[a].port.flags & ASYNC_INITIALIZED) | 886 | if (brd->ports[a].port.flags & ASYNC_INITIALIZED) { |
884 | tty_hangup(brd->ports[a].port.tty); | 887 | struct tty_struct *tty = tty_port_tty_get( |
888 | &brd->ports[a].port); | ||
889 | if (tty) { | ||
890 | tty_hangup(tty); | ||
891 | tty_kref_put(tty); | ||
892 | } | ||
893 | } | ||
885 | while (1) { | 894 | while (1) { |
886 | opened = 0; | 895 | opened = 0; |
887 | for (a = 0; a < brd->numPorts; a++) | 896 | for (a = 0; a < brd->numPorts; a++) |
@@ -1096,13 +1105,14 @@ static void __exit moxa_exit(void) | |||
1096 | module_init(moxa_init); | 1105 | module_init(moxa_init); |
1097 | module_exit(moxa_exit); | 1106 | module_exit(moxa_exit); |
1098 | 1107 | ||
1099 | static void moxa_close_port(struct moxa_port *ch) | 1108 | static void moxa_close_port(struct tty_struct *tty) |
1100 | { | 1109 | { |
1101 | moxa_shut_down(ch); | 1110 | struct moxa_port *ch = tty->driver_data; |
1111 | moxa_shut_down(tty); | ||
1102 | MoxaPortFlushData(ch, 2); | 1112 | MoxaPortFlushData(ch, 2); |
1103 | ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 1113 | ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
1104 | ch->port.tty->driver_data = NULL; | 1114 | tty->driver_data = NULL; |
1105 | ch->port.tty = NULL; | 1115 | tty_port_tty_set(&ch->port, NULL); |
1106 | } | 1116 | } |
1107 | 1117 | ||
1108 | static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, | 1118 | static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, |
@@ -1161,7 +1171,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
1161 | ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; | 1171 | ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; |
1162 | ch->port.count++; | 1172 | ch->port.count++; |
1163 | tty->driver_data = ch; | 1173 | tty->driver_data = ch; |
1164 | ch->port.tty = tty; | 1174 | tty_port_tty_set(&ch->port, tty); |
1165 | if (!(ch->port.flags & ASYNC_INITIALIZED)) { | 1175 | if (!(ch->port.flags & ASYNC_INITIALIZED)) { |
1166 | ch->statusflags = 0; | 1176 | ch->statusflags = 0; |
1167 | moxa_set_tty_param(tty, tty->termios); | 1177 | moxa_set_tty_param(tty, tty->termios); |
@@ -1179,7 +1189,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
1179 | if (retval) { | 1189 | if (retval) { |
1180 | if (ch->port.count) /* 0 means already hung up... */ | 1190 | if (ch->port.count) /* 0 means already hung up... */ |
1181 | if (--ch->port.count == 0) | 1191 | if (--ch->port.count == 0) |
1182 | moxa_close_port(ch); | 1192 | moxa_close_port(tty); |
1183 | } else | 1193 | } else |
1184 | ch->port.flags |= ASYNC_NORMAL_ACTIVE; | 1194 | ch->port.flags |= ASYNC_NORMAL_ACTIVE; |
1185 | mutex_unlock(&moxa_openlock); | 1195 | mutex_unlock(&moxa_openlock); |
@@ -1219,7 +1229,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp) | |||
1219 | tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ | 1229 | tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ |
1220 | } | 1230 | } |
1221 | 1231 | ||
1222 | moxa_close_port(ch); | 1232 | moxa_close_port(tty); |
1223 | unlock: | 1233 | unlock: |
1224 | mutex_unlock(&moxa_openlock); | 1234 | mutex_unlock(&moxa_openlock); |
1225 | } | 1235 | } |
@@ -1234,7 +1244,7 @@ static int moxa_write(struct tty_struct *tty, | |||
1234 | return 0; | 1244 | return 0; |
1235 | 1245 | ||
1236 | spin_lock_bh(&moxa_lock); | 1246 | spin_lock_bh(&moxa_lock); |
1237 | len = MoxaPortWriteData(ch, buf, count); | 1247 | len = MoxaPortWriteData(tty, buf, count); |
1238 | spin_unlock_bh(&moxa_lock); | 1248 | spin_unlock_bh(&moxa_lock); |
1239 | 1249 | ||
1240 | ch->statusflags |= LOWWAIT; | 1250 | ch->statusflags |= LOWWAIT; |
@@ -1409,7 +1419,7 @@ static void moxa_hangup(struct tty_struct *tty) | |||
1409 | return; | 1419 | return; |
1410 | } | 1420 | } |
1411 | ch->port.count = 0; | 1421 | ch->port.count = 0; |
1412 | moxa_close_port(ch); | 1422 | moxa_close_port(tty); |
1413 | mutex_unlock(&moxa_openlock); | 1423 | mutex_unlock(&moxa_openlock); |
1414 | 1424 | ||
1415 | wake_up_interruptible(&ch->port.open_wait); | 1425 | wake_up_interruptible(&ch->port.open_wait); |
@@ -1417,11 +1427,14 @@ static void moxa_hangup(struct tty_struct *tty) | |||
1417 | 1427 | ||
1418 | static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) | 1428 | static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) |
1419 | { | 1429 | { |
1430 | struct tty_struct *tty; | ||
1420 | dcd = !!dcd; | 1431 | dcd = !!dcd; |
1421 | 1432 | ||
1422 | if (dcd != p->DCDState && p->port.tty && C_CLOCAL(p->port.tty)) { | 1433 | if (dcd != p->DCDState) { |
1423 | if (!dcd) | 1434 | tty = tty_port_tty_get(&p->port); |
1424 | tty_hangup(p->port.tty); | 1435 | if (tty && C_CLOCAL(tty) && !dcd) |
1436 | tty_hangup(tty); | ||
1437 | tty_kref_put(tty); | ||
1425 | } | 1438 | } |
1426 | p->DCDState = dcd; | 1439 | p->DCDState = dcd; |
1427 | } | 1440 | } |
@@ -1429,7 +1442,7 @@ static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) | |||
1429 | static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | 1442 | static int moxa_poll_port(struct moxa_port *p, unsigned int handle, |
1430 | u16 __iomem *ip) | 1443 | u16 __iomem *ip) |
1431 | { | 1444 | { |
1432 | struct tty_struct *tty = p->port.tty; | 1445 | struct tty_struct *tty = tty_port_tty_get(&p->port); |
1433 | void __iomem *ofsAddr; | 1446 | void __iomem *ofsAddr; |
1434 | unsigned int inited = p->port.flags & ASYNC_INITIALIZED; | 1447 | unsigned int inited = p->port.flags & ASYNC_INITIALIZED; |
1435 | u16 intr; | 1448 | u16 intr; |
@@ -1476,6 +1489,7 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | |||
1476 | tty_insert_flip_char(tty, 0, TTY_BREAK); | 1489 | tty_insert_flip_char(tty, 0, TTY_BREAK); |
1477 | tty_schedule_flip(tty); | 1490 | tty_schedule_flip(tty); |
1478 | } | 1491 | } |
1492 | tty_kref_put(tty); | ||
1479 | 1493 | ||
1480 | if (intr & IntrLine) | 1494 | if (intr & IntrLine) |
1481 | moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state); | 1495 | moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state); |
@@ -1560,9 +1574,9 @@ static void moxa_setup_empty_event(struct tty_struct *tty) | |||
1560 | spin_unlock_bh(&moxa_lock); | 1574 | spin_unlock_bh(&moxa_lock); |
1561 | } | 1575 | } |
1562 | 1576 | ||
1563 | static void moxa_shut_down(struct moxa_port *ch) | 1577 | static void moxa_shut_down(struct tty_struct *tty) |
1564 | { | 1578 | { |
1565 | struct tty_struct *tp = ch->port.tty; | 1579 | struct moxa_port *ch = tty->driver_data; |
1566 | 1580 | ||
1567 | if (!(ch->port.flags & ASYNC_INITIALIZED)) | 1581 | if (!(ch->port.flags & ASYNC_INITIALIZED)) |
1568 | return; | 1582 | return; |
@@ -1572,7 +1586,7 @@ static void moxa_shut_down(struct moxa_port *ch) | |||
1572 | /* | 1586 | /* |
1573 | * If we're a modem control device and HUPCL is on, drop RTS & DTR. | 1587 | * If we're a modem control device and HUPCL is on, drop RTS & DTR. |
1574 | */ | 1588 | */ |
1575 | if (C_HUPCL(tp)) | 1589 | if (C_HUPCL(tty)) |
1576 | MoxaPortLineCtrl(ch, 0, 0); | 1590 | MoxaPortLineCtrl(ch, 0, 0); |
1577 | 1591 | ||
1578 | spin_lock_bh(&moxa_lock); | 1592 | spin_lock_bh(&moxa_lock); |
@@ -1953,9 +1967,10 @@ static int MoxaPortLineStatus(struct moxa_port *port) | |||
1953 | return val; | 1967 | return val; |
1954 | } | 1968 | } |
1955 | 1969 | ||
1956 | static int MoxaPortWriteData(struct moxa_port *port, | 1970 | static int MoxaPortWriteData(struct tty_struct *tty, |
1957 | const unsigned char *buffer, int len) | 1971 | const unsigned char *buffer, int len) |
1958 | { | 1972 | { |
1973 | struct moxa_port *port = tty->driver_data; | ||
1959 | void __iomem *baseAddr, *ofsAddr, *ofs; | 1974 | void __iomem *baseAddr, *ofsAddr, *ofs; |
1960 | unsigned int c, total; | 1975 | unsigned int c, total; |
1961 | u16 head, tail, tx_mask, spage, epage; | 1976 | u16 head, tail, tx_mask, spage, epage; |