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

tty: Introduce some close helpers for ports

Again this is a lot of common code we can unify

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
a6614999 7834909f

+127 -392
+11 -57
drivers/char/isicom.c
··· 945 945 946 946 static void isicom_close(struct tty_struct *tty, struct file *filp) 947 947 { 948 - struct isi_port *port = tty->driver_data; 948 + struct isi_port *ip = tty->driver_data; 949 + struct tty_port *port = &ip->port; 949 950 struct isi_board *card; 950 951 unsigned long flags; 951 952 952 - if (!port) 953 + BUG_ON(!ip); 954 + 955 + card = ip->card; 956 + if (isicom_paranoia_check(ip, tty->name, "isicom_close")) 953 957 return; 954 - card = port->card; 955 - if (isicom_paranoia_check(port, tty->name, "isicom_close")) 956 - return; 957 958 958 - pr_dbg("Close start!!!.\n"); 959 - 960 - spin_lock_irqsave(&port->port.lock, flags); 961 - if (tty_hung_up_p(filp)) { 962 - spin_unlock_irqrestore(&port->port.lock, flags); 963 - return; 964 - } 965 - 966 - if (tty->count == 1 && port->port.count != 1) { 967 - printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port " 968 - "count tty->count = 1 port count = %d.\n", 969 - card->base, port->port.count); 970 - port->port.count = 1; 971 - } 972 - if (--port->port.count < 0) { 973 - printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port " 974 - "count for channel%d = %d", card->base, port->channel, 975 - port->port.count); 976 - port->port.count = 0; 977 - } 978 - 979 - if (port->port.count) { 980 - spin_unlock_irqrestore(&port->port.lock, flags); 981 - return; 982 - } 983 - port->port.flags |= ASYNC_CLOSING; 984 - tty->closing = 1; 985 - spin_unlock_irqrestore(&port->port.lock, flags); 986 - 987 - if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) 988 - tty_wait_until_sent(tty, port->port.closing_wait); 989 959 /* indicate to the card that no more data can be received 990 960 on this port */ 991 961 spin_lock_irqsave(&card->card_lock, flags); 992 - if (port->port.flags & ASYNC_INITIALIZED) { 993 - card->port_status &= ~(1 << port->channel); 962 + if (port->flags & ASYNC_INITIALIZED) { 963 + card->port_status &= ~(1 << ip->channel); 994 964 outw(card->port_status, card->base + 0x02); 995 965 } 996 - isicom_shutdown_port(port); 966 + isicom_shutdown_port(ip); 997 967 spin_unlock_irqrestore(&card->card_lock, flags); 998 968 999 969 isicom_flush_buffer(tty); 1000 - tty_ldisc_flush(tty); 1001 - 1002 - spin_lock_irqsave(&port->port.lock, flags); 1003 - tty->closing = 0; 1004 - 1005 - if (port->port.blocked_open) { 1006 - spin_unlock_irqrestore(&port->port.lock, flags); 1007 - if (port->port.close_delay) { 1008 - pr_dbg("scheduling until time out.\n"); 1009 - msleep_interruptible( 1010 - jiffies_to_msecs(port->port.close_delay)); 1011 - } 1012 - spin_lock_irqsave(&port->port.lock, flags); 1013 - wake_up_interruptible(&port->port.open_wait); 1014 - } 1015 - port->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); 1016 - wake_up_interruptible(&port->port.close_wait); 1017 - spin_unlock_irqrestore(&port->port.lock, flags); 970 + 971 + tty_port_close_end(port, tty); 1018 972 } 1019 973 1020 974 /* write et all */
+29 -49
drivers/char/istallion.c
··· 767 767 break; 768 768 } 769 769 if (i == ARRAY_SIZE(stli_brdstr)) { 770 - printk("STALLION: unknown board name, %s?\n", argp[0]); 770 + printk(KERN_WARNING "istallion: unknown board name, %s?\n", argp[0]); 771 771 return 0; 772 772 } 773 773 ··· 855 855 return; 856 856 port = &portp->port; 857 857 858 - spin_lock_irqsave(&port->lock, flags); 859 - if (tty_hung_up_p(filp)) { 860 - spin_unlock_irqrestore(&port->lock, flags); 858 + if (tty_port_close_start(port, tty, filp) == 0) 861 859 return; 862 - } 863 - if (tty->count == 1 && port->count != 1) 864 - port->count = 1; 865 - if (port->count-- > 1) { 866 - spin_unlock_irqrestore(&port->lock, flags); 867 - return; 868 - } 869 - 870 - port->flags |= ASYNC_CLOSING; 871 - tty->closing = 1; 872 - spin_unlock_irqrestore(&port->lock, flags); 873 860 874 861 /* 875 862 * May want to wait for data to drain before closing. The BUSY flag ··· 869 882 stli_flushchars(tty); 870 883 spin_unlock_irqrestore(&stli_lock, flags); 871 884 885 + /* We end up doing this twice for the moment. This needs looking at 886 + eventually. Note we still use portp->closing_wait as a result */ 872 887 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) 873 888 tty_wait_until_sent(tty, portp->closing_wait); 874 889 ··· 894 905 set_bit(ST_DOFLUSHRX, &portp->state); 895 906 stli_flushbuffer(tty); 896 907 897 - tty->closing = 0; 898 - tty_port_tty_set(&portp->port, NULL); 899 - 900 - if (port->blocked_open) { 901 - if (portp->close_delay) 902 - msleep_interruptible(jiffies_to_msecs(portp->close_delay)); 903 - wake_up_interruptible(&port->open_wait); 904 - } 905 - 906 - port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); 907 - wake_up_interruptible(&port->close_wait); 908 + tty_port_close_end(port, tty); 909 + tty_port_tty_set(port, NULL); 908 910 } 909 911 910 912 /*****************************************************************************/ ··· 1462 1482 sio.irq = 0; 1463 1483 sio.flags = portp->port.flags; 1464 1484 sio.baud_base = portp->baud_base; 1465 - sio.close_delay = portp->close_delay; 1485 + sio.close_delay = portp->port.close_delay; 1466 1486 sio.closing_wait = portp->closing_wait; 1467 1487 sio.custom_divisor = portp->custom_divisor; 1468 1488 sio.xmit_fifo_size = 0; ··· 1494 1514 return -EFAULT; 1495 1515 if (!capable(CAP_SYS_ADMIN)) { 1496 1516 if ((sio.baud_base != portp->baud_base) || 1497 - (sio.close_delay != portp->close_delay) || 1517 + (sio.close_delay != portp->port.close_delay) || 1498 1518 ((sio.flags & ~ASYNC_USR_MASK) != 1499 1519 (portp->port.flags & ~ASYNC_USR_MASK))) 1500 1520 return -EPERM; ··· 1503 1523 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | 1504 1524 (sio.flags & ASYNC_USR_MASK); 1505 1525 portp->baud_base = sio.baud_base; 1506 - portp->close_delay = sio.close_delay; 1526 + portp->port.close_delay = sio.close_delay; 1507 1527 portp->closing_wait = sio.closing_wait; 1508 1528 portp->custom_divisor = sio.custom_divisor; 1509 1529 ··· 2045 2065 unsigned char __iomem *bits; 2046 2066 2047 2067 if (test_bit(ST_CMDING, &portp->state)) { 2048 - printk(KERN_ERR "STALLION: command already busy, cmd=%x!\n", 2068 + printk(KERN_ERR "istallion: command already busy, cmd=%x!\n", 2049 2069 (int) cmd); 2050 2070 return; 2051 2071 } ··· 2605 2625 for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { 2606 2626 portp = kzalloc(sizeof(struct stliport), GFP_KERNEL); 2607 2627 if (!portp) { 2608 - printk("STALLION: failed to allocate port structure\n"); 2628 + printk(KERN_WARNING "istallion: failed to allocate port structure\n"); 2609 2629 continue; 2610 2630 } 2611 2631 tty_port_init(&portp->port); ··· 2615 2635 portp->brdnr = brdp->brdnr; 2616 2636 portp->panelnr = panelnr; 2617 2637 portp->baud_base = STL_BAUDBASE; 2618 - portp->close_delay = STL_CLOSEDELAY; 2638 + portp->port.close_delay = STL_CLOSEDELAY; 2619 2639 portp->closing_wait = 30 * HZ; 2620 2640 init_waitqueue_head(&portp->port.open_wait); 2621 2641 init_waitqueue_head(&portp->port.close_wait); ··· 2672 2692 unsigned char val; 2673 2693 2674 2694 if (offset > brdp->memsize) { 2675 - printk(KERN_ERR "STALLION: shared memory pointer=%x out of " 2695 + printk(KERN_ERR "istallion: shared memory pointer=%x out of " 2676 2696 "range at line=%d(%d), brd=%d\n", 2677 2697 (int) offset, line, __LINE__, brdp->brdnr); 2678 2698 ptr = NULL; ··· 2746 2766 unsigned char val; 2747 2767 2748 2768 if (offset > brdp->memsize) { 2749 - printk(KERN_ERR "STALLION: shared memory pointer=%x out of " 2769 + printk(KERN_ERR "istallion: shared memory pointer=%x out of " 2750 2770 "range at line=%d(%d), brd=%d\n", 2751 2771 (int) offset, line, __LINE__, brdp->brdnr); 2752 2772 ptr = NULL; ··· 2798 2818 unsigned char val; 2799 2819 2800 2820 if (offset > brdp->memsize) { 2801 - printk(KERN_ERR "STALLION: shared memory pointer=%x out of " 2821 + printk(KERN_ERR "istallion: shared memory pointer=%x out of " 2802 2822 "range at line=%d(%d), brd=%d\n", 2803 2823 (int) offset, line, __LINE__, brdp->brdnr); 2804 2824 ptr = NULL; ··· 2843 2863 unsigned char val; 2844 2864 2845 2865 if (offset > brdp->memsize) { 2846 - printk(KERN_ERR "STALLION: shared memory pointer=%x out of " 2866 + printk(KERN_ERR "istallion: shared memory pointer=%x out of " 2847 2867 "range at line=%d(%d), board=%d\n", 2848 2868 (int) offset, line, __LINE__, brdp->brdnr); 2849 2869 ptr = NULL; ··· 2908 2928 void __iomem *ptr; 2909 2929 2910 2930 if (offset > brdp->memsize) { 2911 - printk(KERN_ERR "STALLION: shared memory pointer=%x out of " 2931 + printk(KERN_ERR "istallion: shared memory pointer=%x out of " 2912 2932 "range at line=%d(%d), brd=%d\n", 2913 2933 (int) offset, line, __LINE__, brdp->brdnr); 2914 2934 ptr = NULL; ··· 2974 2994 unsigned char val; 2975 2995 2976 2996 if (offset > brdp->memsize) { 2977 - printk(KERN_ERR "STALLION: shared memory pointer=%x out of " 2997 + printk(KERN_ERR "istallion: shared memory pointer=%x out of " 2978 2998 "range at line=%d(%d), brd=%d\n", 2979 2999 (int) offset, line, __LINE__, brdp->brdnr); 2980 3000 ptr = NULL; ··· 3413 3433 #endif 3414 3434 3415 3435 if (nrdevs < (brdp->nrports + 1)) { 3416 - printk(KERN_ERR "STALLION: slave failed to allocate memory for " 3436 + printk(KERN_ERR "istallion: slave failed to allocate memory for " 3417 3437 "all devices, devices=%d\n", nrdevs); 3418 3438 brdp->nrports = nrdevs - 1; 3419 3439 } ··· 3423 3443 brdp->bitsize = (nrdevs + 7) / 8; 3424 3444 memoff = readl(&hdrp->memp); 3425 3445 if (memoff > brdp->memsize) { 3426 - printk(KERN_ERR "STALLION: corrupted shared memory region?\n"); 3446 + printk(KERN_ERR "istallion: corrupted shared memory region?\n"); 3427 3447 rc = -EIO; 3428 3448 goto stli_donestartup; 3429 3449 } 3430 3450 memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff); 3431 3451 if (readw(&memp->dtype) != TYP_ASYNCTRL) { 3432 - printk(KERN_ERR "STALLION: no slave control device found\n"); 3452 + printk(KERN_ERR "istallion: no slave control device found\n"); 3433 3453 goto stli_donestartup; 3434 3454 } 3435 3455 memp++; ··· 3514 3534 retval = stli_initonb(brdp); 3515 3535 break; 3516 3536 default: 3517 - printk(KERN_ERR "STALLION: board=%d is unknown board " 3537 + printk(KERN_ERR "istallion: board=%d is unknown board " 3518 3538 "type=%d\n", brdp->brdnr, brdp->brdtype); 3519 3539 retval = -ENODEV; 3520 3540 } ··· 3523 3543 return retval; 3524 3544 3525 3545 stli_initports(brdp); 3526 - printk(KERN_INFO "STALLION: %s found, board=%d io=%x mem=%x " 3546 + printk(KERN_INFO "istallion: %s found, board=%d io=%x mem=%x " 3527 3547 "nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype], 3528 3548 brdp->brdnr, brdp->iobase, (int) brdp->memaddr, 3529 3549 brdp->nrpanels, brdp->nrports); ··· 3617 3637 if (! foundit) { 3618 3638 brdp->memaddr = 0; 3619 3639 brdp->membase = NULL; 3620 - printk(KERN_ERR "STALLION: failed to probe shared memory " 3640 + printk(KERN_ERR "istallion: failed to probe shared memory " 3621 3641 "region for %s in EISA slot=%d\n", 3622 3642 stli_brdnames[brdp->brdtype], (brdp->iobase >> 12)); 3623 3643 return -ENODEV; ··· 3762 3782 mutex_lock(&stli_brdslock); 3763 3783 brdnr = stli_getbrdnr(); 3764 3784 if (brdnr < 0) { 3765 - printk(KERN_INFO "STALLION: too many boards found, " 3785 + printk(KERN_INFO "istallion: too many boards found, " 3766 3786 "maximum supported %d\n", STL_MAXBRDS); 3767 3787 mutex_unlock(&stli_brdslock); 3768 3788 retval = -EIO; ··· 3834 3854 3835 3855 brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL); 3836 3856 if (!brdp) { 3837 - printk(KERN_ERR "STALLION: failed to allocate memory " 3857 + printk(KERN_ERR "istallion: failed to allocate memory " 3838 3858 "(size=%Zd)\n", sizeof(struct stlibrd)); 3839 3859 return NULL; 3840 3860 } ··· 4473 4493 4474 4494 stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); 4475 4495 if (!stli_txcookbuf) { 4476 - printk(KERN_ERR "STALLION: failed to allocate memory " 4496 + printk(KERN_ERR "istallion: failed to allocate memory " 4477 4497 "(size=%d)\n", STLI_TXBUFSIZE); 4478 4498 retval = -ENOMEM; 4479 4499 goto err; ··· 4498 4518 4499 4519 retval = tty_register_driver(stli_serial); 4500 4520 if (retval) { 4501 - printk(KERN_ERR "STALLION: failed to register serial driver\n"); 4521 + printk(KERN_ERR "istallion: failed to register serial driver\n"); 4502 4522 goto err_ttyput; 4503 4523 } 4504 4524 ··· 4512 4532 */ 4513 4533 retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem); 4514 4534 if (retval) { 4515 - printk(KERN_ERR "STALLION: failed to register serial memory " 4535 + printk(KERN_ERR "istallion: failed to register serial memory " 4516 4536 "device\n"); 4517 4537 goto err_deinit; 4518 4538 }
+9 -47
drivers/char/mxser.c
··· 1080 1080 static void mxser_close(struct tty_struct *tty, struct file *filp) 1081 1081 { 1082 1082 struct mxser_port *info = tty->driver_data; 1083 + struct tty_port *port = &info->port; 1083 1084 1084 1085 unsigned long timeout; 1085 - unsigned long flags; 1086 1086 1087 1087 if (tty->index == MXSER_PORTS) 1088 1088 return; 1089 1089 if (!info) 1090 1090 return; 1091 1091 1092 - spin_lock_irqsave(&info->port.lock, flags); 1092 + if (tty_port_close_start(port, tty, filp) == 0) 1093 + return; 1093 1094 1094 - if (tty_hung_up_p(filp)) { 1095 - spin_unlock_irqrestore(&info->port.lock, flags); 1096 - return; 1097 - } 1098 - if ((tty->count == 1) && (info->port.count != 1)) { 1099 - /* 1100 - * Uh, oh. tty->count is 1, which means that the tty 1101 - * structure will be freed. Info->port.count should always 1102 - * be one in these conditions. If it's greater than 1103 - * one, we've got real problems, since it means the 1104 - * serial port won't be shutdown. 1105 - */ 1106 - printk(KERN_ERR "mxser_close: bad serial port count; " 1107 - "tty->count is 1, info->port.count is %d\n", info->port.count); 1108 - info->port.count = 1; 1109 - } 1110 - if (--info->port.count < 0) { 1111 - printk(KERN_ERR "mxser_close: bad serial port count for " 1112 - "ttys%d: %d\n", tty->index, info->port.count); 1113 - info->port.count = 0; 1114 - } 1115 - if (info->port.count) { 1116 - spin_unlock_irqrestore(&info->port.lock, flags); 1117 - return; 1118 - } 1119 - info->port.flags |= ASYNC_CLOSING; 1120 - spin_unlock_irqrestore(&info->port.lock, flags); 1121 1095 /* 1122 1096 * Save the termios structure, since this port may have 1123 1097 * separate termios for callout and dialin. 1098 + * 1099 + * FIXME: Can this go ? 1124 1100 */ 1125 1101 if (info->port.flags & ASYNC_NORMAL_ACTIVE) 1126 1102 info->normal_termios = *tty->termios; 1127 - /* 1128 - * Now we wait for the transmit buffer to clear; and we notify 1129 - * the line discipline to only process XON/XOFF characters. 1130 - */ 1131 - tty->closing = 1; 1132 - if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) 1133 - tty_wait_until_sent(tty, info->port.closing_wait); 1134 1103 /* 1135 1104 * At this point we stop accepting input. To do this, we 1136 1105 * disable the receive line status interrupts, and tell the ··· 1125 1156 } 1126 1157 } 1127 1158 mxser_shutdown(tty); 1128 - 1129 1159 mxser_flush_buffer(tty); 1130 - tty_ldisc_flush(tty); 1131 1160 1132 - tty->closing = 0; 1133 - tty_port_tty_set(&info->port, NULL); 1134 - if (info->port.blocked_open) { 1135 - if (info->port.close_delay) 1136 - schedule_timeout_interruptible(info->port.close_delay); 1137 - wake_up_interruptible(&info->port.open_wait); 1138 - } 1139 - 1140 - info->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); 1161 + /* Right now the tty_port set is done outside of the close_end helper 1162 + as we don't yet have everyone using refcounts */ 1163 + tty_port_close_end(port, tty); 1164 + tty_port_tty_set(port, NULL); 1141 1165 } 1142 1166 1143 1167 static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
+5 -44
drivers/char/riscom8.c
··· 929 929 if (!port || rc_paranoia_check(port, tty->name, "close")) 930 930 return; 931 931 932 - spin_lock_irqsave(&port->port.lock, flags); 933 - 934 - if (tty_hung_up_p(filp)) 935 - goto out; 936 - 937 932 bp = port_Board(port); 938 - if ((tty->count == 1) && (port->port.count != 1)) { 939 - printk(KERN_INFO "rc%d: rc_close: bad port count;" 940 - " tty->count is 1, port count is %d\n", 941 - board_No(bp), port->port.count); 942 - port->port.count = 1; 943 - } 944 - if (--port->port.count < 0) { 945 - printk(KERN_INFO "rc%d: rc_close: bad port count " 946 - "for tty%d: %d\n", 947 - board_No(bp), port_No(port), port->port.count); 948 - port->port.count = 0; 949 - } 950 - if (port->port.count) 951 - goto out; 952 - port->port.flags |= ASYNC_CLOSING; 953 - /* 954 - * Now we wait for the transmit buffer to clear; and we notify 955 - * the line discipline to only process XON/XOFF characters. 956 - */ 957 - tty->closing = 1; 958 - spin_unlock_irqrestore(&port->port.lock, flags); 959 - if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) 960 - tty_wait_until_sent(tty, port->port.closing_wait); 933 + 934 + if (tty_port_close_start(&port->port, tty, filp) == 0) 935 + return; 936 + 961 937 /* 962 938 * At this point we stop accepting input. To do this, we 963 939 * disable the receive line status interrupts, and tell the ··· 965 989 rc_shutdown_port(tty, bp, port); 966 990 rc_flush_buffer(tty); 967 991 spin_unlock_irqrestore(&riscom_lock, flags); 968 - tty_ldisc_flush(tty); 969 992 970 - spin_lock_irqsave(&port->port.lock, flags); 971 - tty->closing = 0; 972 - port->port.tty = NULL; 973 - if (port->port.blocked_open) { 974 - spin_unlock_irqrestore(&port->port.lock, flags); 975 - if (port->port.close_delay) 976 - msleep_interruptible(jiffies_to_msecs(port->port.close_delay)); 977 - wake_up_interruptible(&port->port.open_wait); 978 - spin_lock_irqsave(&port->port.lock, flags); 979 - } 980 - port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); 981 - wake_up_interruptible(&port->port.close_wait); 982 - 983 - out: 984 - spin_unlock_irqrestore(&riscom_lock, flags); 993 + tty_port_close_end(&port->port, tty); 985 994 } 986 995 987 996 static int rc_write(struct tty_struct *tty,
+4 -35
drivers/char/stallion.c
··· 833 833 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); 834 834 835 835 portp = tty->driver_data; 836 - if (portp == NULL) 837 - return; 836 + BUG_ON(portp == NULL); 837 + 838 838 port = &portp->port; 839 839 840 - spin_lock_irqsave(&port->lock, flags); 841 - if (tty_hung_up_p(filp)) { 842 - spin_unlock_irqrestore(&port->lock, flags); 840 + if (tty_port_close_start(port, tty, filp) == 0) 843 841 return; 844 - } 845 - if (tty->count == 1 && port->count != 1) 846 - port->count = 1; 847 - if (port->count-- > 1) { 848 - spin_unlock_irqrestore(&port->lock, flags); 849 - return; 850 - } 851 - 852 - port->count = 0; 853 - port->flags |= ASYNC_CLOSING; 854 - 855 842 /* 856 843 * May want to wait for any data to drain before closing. The BUSY 857 844 * flag keeps track of whether we are still sending or not - it is 858 845 * very accurate for the cd1400, not quite so for the sc26198. 859 846 * (The sc26198 has no "end-of-data" interrupt only empty FIFO) 860 847 */ 861 - tty->closing = 1; 862 - 863 - spin_unlock_irqrestore(&port->lock, flags); 864 - 865 - if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) 866 - tty_wait_until_sent(tty, portp->closing_wait); 867 848 stl_waituntilsent(tty, (HZ / 2)); 868 - 869 849 870 850 spin_lock_irqsave(&port->lock, flags); 871 851 portp->port.flags &= ~ASYNC_INITIALIZED; ··· 863 883 portp->tx.head = NULL; 864 884 portp->tx.tail = NULL; 865 885 } 866 - set_bit(TTY_IO_ERROR, &tty->flags); 867 - tty_ldisc_flush(tty); 868 886 869 - tty->closing = 0; 887 + tty_port_close_end(port, tty); 870 888 tty_port_tty_set(port, NULL); 871 - 872 - if (port->blocked_open) { 873 - if (portp->close_delay) 874 - msleep_interruptible(jiffies_to_msecs(portp->close_delay)); 875 - wake_up_interruptible(&portp->port.open_wait); 876 - } 877 - 878 - portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); 879 - wake_up_interruptible(&port->close_wait); 880 889 } 881 890 882 891 /*****************************************************************************/
+3 -55
drivers/char/synclink.c
··· 3104 3104 if (debug_level >= DEBUG_LEVEL_INFO) 3105 3105 printk("%s(%d):mgsl_close(%s) entry, count=%d\n", 3106 3106 __FILE__,__LINE__, info->device_name, info->port.count); 3107 - 3108 - if (!info->port.count) 3109 - return; 3110 3107 3111 - if (tty_hung_up_p(filp)) 3108 + if (tty_port_close_start(&info->port, tty, filp) == 0) 3112 3109 goto cleanup; 3113 3110 3114 - if ((tty->count == 1) && (info->port.count != 1)) { 3115 - /* 3116 - * tty->count is 1 and the tty structure will be freed. 3117 - * info->port.count should be one in this case. 3118 - * if it's not, correct it so that the port is shutdown. 3119 - */ 3120 - printk("mgsl_close: bad refcount; tty->count is 1, " 3121 - "info->port.count is %d\n", info->port.count); 3122 - info->port.count = 1; 3123 - } 3124 - 3125 - info->port.count--; 3126 - 3127 - /* if at least one open remaining, leave hardware active */ 3128 - if (info->port.count) 3129 - goto cleanup; 3130 - 3131 - info->port.flags |= ASYNC_CLOSING; 3132 - 3133 - /* set tty->closing to notify line discipline to 3134 - * only process XON/XOFF characters. Only the N_TTY 3135 - * discipline appears to use this (ppp does not). 3136 - */ 3137 - tty->closing = 1; 3138 - 3139 - /* wait for transmit data to clear all layers */ 3140 - 3141 - if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) { 3142 - if (debug_level >= DEBUG_LEVEL_INFO) 3143 - printk("%s(%d):mgsl_close(%s) calling tty_wait_until_sent\n", 3144 - __FILE__,__LINE__, info->device_name ); 3145 - tty_wait_until_sent(tty, info->port.closing_wait); 3146 - } 3147 - 3148 3111 if (info->port.flags & ASYNC_INITIALIZED) 3149 3112 mgsl_wait_until_sent(tty, info->timeout); 3150 - 3151 3113 mgsl_flush_buffer(tty); 3152 - 3153 3114 tty_ldisc_flush(tty); 3154 - 3155 3115 shutdown(info); 3156 - 3157 - tty->closing = 0; 3116 + 3117 + tty_port_close_end(&info->port, tty); 3158 3118 info->port.tty = NULL; 3159 - 3160 - if (info->port.blocked_open) { 3161 - if (info->port.close_delay) { 3162 - msleep_interruptible(jiffies_to_msecs(info->port.close_delay)); 3163 - } 3164 - wake_up_interruptible(&info->port.open_wait); 3165 - } 3166 - 3167 - info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); 3168 - 3169 - wake_up_interruptible(&info->port.close_wait); 3170 - 3171 3119 cleanup: 3172 3120 if (debug_level >= DEBUG_LEVEL_INFO) 3173 3121 printk("%s(%d):mgsl_close(%s) exit, count=%d\n", __FILE__,__LINE__,
+3 -55
drivers/char/synclinkmp.c
··· 810 810 printk("%s(%d):%s close() entry, count=%d\n", 811 811 __FILE__,__LINE__, info->device_name, info->port.count); 812 812 813 - if (!info->port.count) 814 - return; 815 - 816 - if (tty_hung_up_p(filp)) 813 + if (tty_port_close_start(&info->port, tty, filp) == 0) 817 814 goto cleanup; 818 - 819 - if ((tty->count == 1) && (info->port.count != 1)) { 820 - /* 821 - * tty->count is 1 and the tty structure will be freed. 822 - * info->port.count should be one in this case. 823 - * if it's not, correct it so that the port is shutdown. 824 - */ 825 - printk("%s(%d):%s close: bad refcount; tty->count is 1, " 826 - "info->port.count is %d\n", 827 - __FILE__,__LINE__, info->device_name, info->port.count); 828 - info->port.count = 1; 829 - } 830 - 831 - info->port.count--; 832 - 833 - /* if at least one open remaining, leave hardware active */ 834 - if (info->port.count) 835 - goto cleanup; 836 - 837 - info->port.flags |= ASYNC_CLOSING; 838 - 839 - /* set tty->closing to notify line discipline to 840 - * only process XON/XOFF characters. Only the N_TTY 841 - * discipline appears to use this (ppp does not). 842 - */ 843 - tty->closing = 1; 844 - 845 - /* wait for transmit data to clear all layers */ 846 - 847 - if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) { 848 - if (debug_level >= DEBUG_LEVEL_INFO) 849 - printk("%s(%d):%s close() calling tty_wait_until_sent\n", 850 - __FILE__,__LINE__, info->device_name ); 851 - tty_wait_until_sent(tty, info->port.closing_wait); 852 - } 853 - 815 + 854 816 if (info->port.flags & ASYNC_INITIALIZED) 855 817 wait_until_sent(tty, info->timeout); 856 818 857 819 flush_buffer(tty); 858 - 859 820 tty_ldisc_flush(tty); 860 - 861 821 shutdown(info); 862 822 863 - tty->closing = 0; 823 + tty_port_close_end(&info->port, tty); 864 824 info->port.tty = NULL; 865 - 866 - if (info->port.blocked_open) { 867 - if (info->port.close_delay) { 868 - msleep_interruptible(jiffies_to_msecs(info->port.close_delay)); 869 - } 870 - wake_up_interruptible(&info->port.open_wait); 871 - } 872 - 873 - info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); 874 - 875 - wake_up_interruptible(&info->port.close_wait); 876 - 877 825 cleanup: 878 826 if (debug_level >= DEBUG_LEVEL_INFO) 879 827 printk("%s(%d):%s close() exit, count=%d\n", __FILE__,__LINE__,
+58
drivers/char/tty_port.c
··· 257 257 } 258 258 EXPORT_SYMBOL(tty_port_block_til_ready); 259 259 260 + int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp) 261 + { 262 + unsigned long flags; 263 + 264 + spin_lock_irqsave(&port->lock, flags); 265 + if (tty_hung_up_p(filp)) { 266 + spin_unlock_irqrestore(&port->lock, flags); 267 + return 0; 268 + } 269 + 270 + if( tty->count == 1 && port->count != 1) { 271 + printk(KERN_WARNING 272 + "tty_port_close_start: tty->count = 1 port count = %d.\n", 273 + port->count); 274 + port->count = 1; 275 + } 276 + if (--port->count < 0) { 277 + printk(KERN_WARNING "tty_port_close_start: count = %d\n", 278 + port->count); 279 + port->count = 0; 280 + } 281 + 282 + if (port->count) { 283 + spin_unlock_irqrestore(&port->lock, flags); 284 + return 0; 285 + } 286 + port->flags |= ASYNC_CLOSING; 287 + tty->closing = 1; 288 + spin_unlock_irqrestore(&port->lock, flags); 289 + if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) 290 + tty_wait_until_sent(tty, port->closing_wait); 291 + return 1; 292 + } 293 + EXPORT_SYMBOL(tty_port_close_start); 294 + 295 + void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) 296 + { 297 + unsigned long flags; 298 + 299 + tty_ldisc_flush(tty); 300 + 301 + spin_lock_irqsave(&port->lock, flags); 302 + tty->closing = 0; 303 + 304 + if (port->blocked_open) { 305 + spin_unlock_irqrestore(&port->lock, flags); 306 + if (port->close_delay) { 307 + msleep_interruptible( 308 + jiffies_to_msecs(port->close_delay)); 309 + } 310 + spin_lock_irqsave(&port->lock, flags); 311 + wake_up_interruptible(&port->open_wait); 312 + } 313 + port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); 314 + wake_up_interruptible(&port->close_wait); 315 + spin_unlock_irqrestore(&port->lock, flags); 316 + } 317 + EXPORT_SYMBOL(tty_port_close_end);
-1
include/linux/istallion.h
··· 59 59 unsigned int devnr; 60 60 int baud_base; 61 61 int custom_divisor; 62 - int close_delay; 63 62 int closing_wait; 64 63 int rc; 65 64 int argsize;
+3
include/linux/tty.h
··· 441 441 extern void tty_port_hangup(struct tty_port *port); 442 442 extern int tty_port_block_til_ready(struct tty_port *port, 443 443 struct tty_struct *tty, struct file *filp); 444 + extern int tty_port_close_start(struct tty_port *port, 445 + struct tty_struct *tty, struct file *filp); 446 + extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty); 444 447 445 448 extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc); 446 449 extern int tty_unregister_ldisc(int disc);