Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Alan Cox and committed by
Linus Torvalds
d450b5a0 4a90f09b

+69 -53
+31 -30
drivers/char/isicom.c
··· 421 421 if (retries >= 100) 422 422 goto unlock; 423 423 424 + tty = tty_port_tty_get(&port->port); 425 + if (tty == NULL) 426 + goto put_unlock; 427 + 424 428 for (; count > 0; count--, port++) { 425 429 /* port not active or tx disabled to force flow control */ 426 430 if (!(port->port.flags & ASYNC_INITIALIZED) || 427 431 !(port->status & ISI_TXOK)) 428 - continue; 429 - 430 - tty = port->port.tty; 431 - 432 - if (tty == NULL) 433 432 continue; 434 433 435 434 txcount = min_t(short, TX_SIZE, port->xmit_cnt); ··· 488 489 tty_wakeup(tty); 489 490 } 490 491 492 + put_unlock: 493 + tty_kref_put(tty); 491 494 unlock: 492 495 spin_unlock_irqrestore(&isi_card[card].card_lock, flags); 493 496 /* schedule another tx for hopefully in about 10ms */ ··· 548 547 return IRQ_HANDLED; 549 548 } 550 549 551 - tty = port->port.tty; 550 + tty = tty_port_tty_get(&port->port); 552 551 if (tty == NULL) { 553 552 word_count = byte_count >> 1; 554 553 while (byte_count > 1) { ··· 589 588 } 590 589 591 590 if (port->port.flags & ASYNC_CTS_FLOW) { 592 - if (port->port.tty->hw_stopped) { 591 + if (tty->hw_stopped) { 593 592 if (header & ISI_CTS) { 594 593 port->port.tty->hw_stopped = 0; 595 594 /* start tx ing */ ··· 598 597 tty_wakeup(tty); 599 598 } 600 599 } else if (!(header & ISI_CTS)) { 601 - port->port.tty->hw_stopped = 1; 600 + tty->hw_stopped = 1; 602 601 /* stop tx ing */ 603 602 port->status &= ~(ISI_TXOK | ISI_CTS); 604 603 } ··· 661 660 } 662 661 outw(0x0000, base+0x04); /* enable interrupts */ 663 662 spin_unlock(&card->card_lock); 663 + tty_kref_put(tty); 664 664 665 665 return IRQ_HANDLED; 666 666 } 667 667 668 - static void isicom_config_port(struct isi_port *port) 668 + static void isicom_config_port(struct tty_struct *tty) 669 669 { 670 + struct isi_port *port = tty->driver_data; 670 671 struct isi_board *card = port->card; 671 - struct tty_struct *tty; 672 672 unsigned long baud; 673 673 unsigned long base = card->base; 674 674 u16 channel_setup, channel = port->channel, 675 675 shift_count = card->shift_count; 676 676 unsigned char flow_ctrl; 677 677 678 - tty = port->port.tty; 679 - 680 - if (tty == NULL) 681 - return; 682 678 /* FIXME: Switch to new tty baud API */ 683 679 baud = C_BAUD(tty); 684 680 if (baud & CBAUDEX) { ··· 688 690 689 691 /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */ 690 692 if (baud < 1 || baud > 4) 691 - port->port.tty->termios->c_cflag &= ~CBAUDEX; 693 + tty->termios->c_cflag &= ~CBAUDEX; 692 694 else 693 695 baud += 15; 694 696 } ··· 795 797 spin_unlock_irqrestore(&bp->card_lock, flags); 796 798 } 797 799 798 - static int isicom_setup_port(struct isi_port *port) 800 + static int isicom_setup_port(struct tty_struct *tty) 799 801 { 802 + struct isi_port *port = tty->driver_data; 800 803 struct isi_board *card = port->card; 801 804 unsigned long flags; 802 805 ··· 807 808 return -ENOMEM; 808 809 809 810 spin_lock_irqsave(&card->card_lock, flags); 810 - if (port->port.tty) 811 - clear_bit(TTY_IO_ERROR, &port->port.tty->flags); 811 + clear_bit(TTY_IO_ERROR, &tty->flags); 812 812 if (port->port.count == 1) 813 813 card->count++; 814 814 ··· 821 823 InterruptTheCard(card->base); 822 824 } 823 825 824 - isicom_config_port(port); 826 + isicom_config_port(tty); 825 827 port->port.flags |= ASYNC_INITIALIZED; 826 828 spin_unlock_irqrestore(&card->card_lock, flags); 827 829 ··· 932 934 933 935 port->port.count++; 934 936 tty->driver_data = port; 935 - port->port.tty = tty; 936 - error = isicom_setup_port(port); 937 + tty_port_tty_set(&port->port, tty); 938 + error = isicom_setup_port(tty); 937 939 if (error == 0) 938 940 error = block_til_ready(tty, filp, port); 939 941 return error; ··· 953 955 struct isi_board *card = port->card; 954 956 struct tty_struct *tty; 955 957 956 - tty = port->port.tty; 958 + tty = tty_port_tty_get(&port->port); 957 959 958 - if (!(port->port.flags & ASYNC_INITIALIZED)) 960 + if (!(port->port.flags & ASYNC_INITIALIZED)) { 961 + tty_kref_put(tty); 959 962 return; 963 + } 960 964 961 965 tty_port_free_xmit_buf(&port->port); 962 966 port->port.flags &= ~ASYNC_INITIALIZED; 963 967 /* 3rd October 2000 : Vinayak P Risbud */ 964 - port->port.tty = NULL; 968 + tty_port_tty_set(&port->port, NULL); 965 969 966 970 /*Fix done by Anil .S on 30-04-2001 967 971 remote login through isi port has dtr toggle problem ··· 1243 1243 return 0; 1244 1244 } 1245 1245 1246 - static int isicom_set_serial_info(struct isi_port *port, 1247 - struct serial_struct __user *info) 1246 + static int isicom_set_serial_info(struct tty_struct *tty, 1247 + struct serial_struct __user *info) 1248 1248 { 1249 + struct isi_port *port = tty->driver_data; 1249 1250 struct serial_struct newinfo; 1250 1251 int reconfig_port; 1251 1252 ··· 1277 1276 if (reconfig_port) { 1278 1277 unsigned long flags; 1279 1278 spin_lock_irqsave(&port->card->card_lock, flags); 1280 - isicom_config_port(port); 1279 + isicom_config_port(tty); 1281 1280 spin_unlock_irqrestore(&port->card->card_lock, flags); 1282 1281 } 1283 1282 unlock_kernel(); ··· 1319 1318 return isicom_get_serial_info(port, argp); 1320 1319 1321 1320 case TIOCSSERIAL: 1322 - return isicom_set_serial_info(port, argp); 1321 + return isicom_set_serial_info(tty, argp); 1323 1322 1324 1323 default: 1325 1324 return -ENOIOCTLCMD; ··· 1342 1341 return; 1343 1342 1344 1343 spin_lock_irqsave(&port->card->card_lock, flags); 1345 - isicom_config_port(port); 1344 + isicom_config_port(tty); 1346 1345 spin_unlock_irqrestore(&port->card->card_lock, flags); 1347 1346 1348 1347 if ((old_termios->c_cflag & CRTSCTS) && ··· 1420 1419 1421 1420 port->port.count = 0; 1422 1421 port->port.flags &= ~ASYNC_NORMAL_ACTIVE; 1423 - port->port.tty = NULL; 1422 + tty_port_tty_set(&port->port, NULL); 1424 1423 wake_up_interruptible(&port->port.open_wait); 1425 1424 } 1426 1425
+38 -23
drivers/char/moxa.c
··· 205 205 static void moxa_poll(unsigned long); 206 206 static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); 207 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 210 * moxa board interface functions: 211 211 */ ··· 217 217 static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int); 218 218 static int MoxaPortLineStatus(struct moxa_port *); 219 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 221 static int MoxaPortReadData(struct moxa_port *); 222 222 static int MoxaPortTxQueue(struct moxa_port *); 223 223 static int MoxaPortRxQueue(struct moxa_port *); ··· 332 332 for (i = 0; i < MAX_BOARDS; i++) { 333 333 p = moxa_boards[i].ports; 334 334 for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { 335 + struct tty_struct *ttyp; 335 336 memset(&tmp, 0, sizeof(tmp)); 336 337 if (!moxa_boards[i].ready) 337 338 goto copy; ··· 345 344 if (status & 4) 346 345 tmp.dcd = 1; 347 346 348 - if (!p->port.tty || !p->port.tty->termios) 347 + ttyp = tty_port_tty_get(&p->port); 348 + if (!ttyp || !ttyp->termios) 349 349 tmp.cflag = p->cflag; 350 350 else 351 - tmp.cflag = p->port.tty->termios->c_cflag; 351 + tmp.cflag = ttyp->termios->c_cflag; 352 + tty_kref_put(tty); 352 353 copy: 353 354 if (copy_to_user(argm, &tmp, sizeof(tmp))) { 354 355 mutex_unlock(&moxa_openlock); ··· 883 880 884 881 /* pci hot-un-plug support */ 885 882 for (a = 0; a < brd->numPorts; a++) 886 - if (brd->ports[a].port.flags & ASYNC_INITIALIZED) 887 - tty_hangup(brd->ports[a].port.tty); 883 + if (brd->ports[a].port.flags & ASYNC_INITIALIZED) { 884 + struct tty_struct *tty = tty_port_tty_get( 885 + &brd->ports[a].port); 886 + if (tty) { 887 + tty_hangup(tty); 888 + tty_kref_put(tty); 889 + } 890 + } 888 891 while (1) { 889 892 opened = 0; 890 893 for (a = 0; a < brd->numPorts; a++) ··· 1105 1096 module_init(moxa_init); 1106 1097 module_exit(moxa_exit); 1107 1098 1108 - static void moxa_close_port(struct moxa_port *ch) 1099 + static void moxa_close_port(struct tty_struct *tty) 1109 1100 { 1110 - moxa_shut_down(ch); 1101 + struct moxa_port *ch = tty->driver_data; 1102 + moxa_shut_down(tty); 1111 1103 MoxaPortFlushData(ch, 2); 1112 1104 ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; 1113 - ch->port.tty->driver_data = NULL; 1114 - ch->port.tty = NULL; 1105 + tty->driver_data = NULL; 1106 + tty_port_tty_set(&ch->port, NULL); 1115 1107 } 1116 1108 1117 1109 static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, ··· 1171 1161 ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; 1172 1162 ch->port.count++; 1173 1163 tty->driver_data = ch; 1174 - ch->port.tty = tty; 1164 + tty_port_tty_set(&ch->port, tty); 1175 1165 if (!(ch->port.flags & ASYNC_INITIALIZED)) { 1176 1166 ch->statusflags = 0; 1177 1167 moxa_set_tty_param(tty, tty->termios); ··· 1189 1179 if (retval) { 1190 1180 if (ch->port.count) /* 0 means already hung up... */ 1191 1181 if (--ch->port.count == 0) 1192 - moxa_close_port(ch); 1182 + moxa_close_port(tty); 1193 1183 } else 1194 1184 ch->port.flags |= ASYNC_NORMAL_ACTIVE; 1195 1185 mutex_unlock(&moxa_openlock); ··· 1229 1219 tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ 1230 1220 } 1231 1221 1232 - moxa_close_port(ch); 1222 + moxa_close_port(tty); 1233 1223 unlock: 1234 1224 mutex_unlock(&moxa_openlock); 1235 1225 } ··· 1244 1234 return 0; 1245 1235 1246 1236 spin_lock_bh(&moxa_lock); 1247 - len = MoxaPortWriteData(ch, buf, count); 1237 + len = MoxaPortWriteData(tty, buf, count); 1248 1238 spin_unlock_bh(&moxa_lock); 1249 1239 1250 1240 ch->statusflags |= LOWWAIT; ··· 1419 1409 return; 1420 1410 } 1421 1411 ch->port.count = 0; 1422 - moxa_close_port(ch); 1412 + moxa_close_port(tty); 1423 1413 mutex_unlock(&moxa_openlock); 1424 1414 1425 1415 wake_up_interruptible(&ch->port.open_wait); ··· 1427 1417 1428 1418 static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) 1429 1419 { 1420 + struct tty_struct *tty; 1430 1421 dcd = !!dcd; 1431 1422 1432 - if (dcd != p->DCDState && p->port.tty && C_CLOCAL(p->port.tty)) { 1433 - if (!dcd) 1434 - tty_hangup(p->port.tty); 1423 + if (dcd != p->DCDState) { 1424 + tty = tty_port_tty_get(&p->port); 1425 + if (tty && C_CLOCAL(tty) && !dcd) 1426 + tty_hangup(tty); 1427 + tty_kref_put(tty); 1435 1428 } 1436 1429 p->DCDState = dcd; 1437 1430 } ··· 1442 1429 static int moxa_poll_port(struct moxa_port *p, unsigned int handle, 1443 1430 u16 __iomem *ip) 1444 1431 { 1445 - struct tty_struct *tty = p->port.tty; 1432 + struct tty_struct *tty = tty_port_tty_get(&p->port); 1446 1433 void __iomem *ofsAddr; 1447 1434 unsigned int inited = p->port.flags & ASYNC_INITIALIZED; 1448 1435 u16 intr; ··· 1489 1476 tty_insert_flip_char(tty, 0, TTY_BREAK); 1490 1477 tty_schedule_flip(tty); 1491 1478 } 1479 + tty_kref_put(tty); 1492 1480 1493 1481 if (intr & IntrLine) 1494 1482 moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state); ··· 1574 1560 spin_unlock_bh(&moxa_lock); 1575 1561 } 1576 1562 1577 - static void moxa_shut_down(struct moxa_port *ch) 1563 + static void moxa_shut_down(struct tty_struct *tty) 1578 1564 { 1579 - struct tty_struct *tp = ch->port.tty; 1565 + struct moxa_port *ch = tty->driver_data; 1580 1566 1581 1567 if (!(ch->port.flags & ASYNC_INITIALIZED)) 1582 1568 return; ··· 1586 1572 /* 1587 1573 * If we're a modem control device and HUPCL is on, drop RTS & DTR. 1588 1574 */ 1589 - if (C_HUPCL(tp)) 1575 + if (C_HUPCL(tty)) 1590 1576 MoxaPortLineCtrl(ch, 0, 0); 1591 1577 1592 1578 spin_lock_bh(&moxa_lock); ··· 1967 1953 return val; 1968 1954 } 1969 1955 1970 - static int MoxaPortWriteData(struct moxa_port *port, 1956 + static int MoxaPortWriteData(struct tty_struct *tty, 1971 1957 const unsigned char *buffer, int len) 1972 1958 { 1959 + struct moxa_port *port = tty->driver_data; 1973 1960 void __iomem *baseAddr, *ofsAddr, *ofs; 1974 1961 unsigned int c, total; 1975 1962 u16 head, tail, tx_mask, spage, epage;