Commit a6614999e800cf3a134ce93ea46ef837e3c0e76e
Committed by
Linus Torvalds
1 parent
7834909f1e
Exists in
master
and in
39 other branches
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>
Showing 11 changed files with 126 additions and 391 deletions Side-by-side Diff
drivers/char/isicom.c
... | ... | @@ -945,76 +945,30 @@ |
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 | - return; | |
954 | - card = port->card; | |
955 | - if (isicom_paranoia_check(port, tty->name, "isicom_close")) | |
956 | - return; | |
953 | + BUG_ON(!ip); | |
957 | 954 | |
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); | |
955 | + card = ip->card; | |
956 | + if (isicom_paranoia_check(ip, tty->name, "isicom_close")) | |
963 | 957 | return; |
964 | - } | |
965 | 958 | |
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 */ |
drivers/char/istallion.c
... | ... | @@ -767,7 +767,7 @@ |
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 | |
774 | 774 | |
775 | 775 | |
... | ... | @@ -855,22 +855,9 @@ |
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 | 860 | |
870 | - port->flags |= ASYNC_CLOSING; | |
871 | - tty->closing = 1; | |
872 | - spin_unlock_irqrestore(&port->lock, flags); | |
873 | - | |
874 | 861 | /* |
875 | 862 | * May want to wait for data to drain before closing. The BUSY flag |
876 | 863 | * keeps track of whether we are still transmitting or not. It is |
... | ... | @@ -882,6 +869,8 @@ |
882 | 869 | stli_flushchars(tty); |
883 | 870 | spin_unlock_irqrestore(&stli_lock, flags); |
884 | 871 | |
872 | + /* We end up doing this twice for the moment. This needs looking at | |
873 | + eventually. Note we still use portp->closing_wait as a result */ | |
885 | 874 | if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
886 | 875 | tty_wait_until_sent(tty, portp->closing_wait); |
887 | 876 | |
... | ... | @@ -905,17 +894,8 @@ |
905 | 894 | set_bit(ST_DOFLUSHRX, &portp->state); |
906 | 895 | stli_flushbuffer(tty); |
907 | 896 | |
908 | - tty->closing = 0; | |
909 | - tty_port_tty_set(&portp->port, NULL); | |
910 | - | |
911 | - if (port->blocked_open) { | |
912 | - if (portp->close_delay) | |
913 | - msleep_interruptible(jiffies_to_msecs(portp->close_delay)); | |
914 | - wake_up_interruptible(&port->open_wait); | |
915 | - } | |
916 | - | |
917 | - port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | |
918 | - wake_up_interruptible(&port->close_wait); | |
897 | + tty_port_close_end(port, tty); | |
898 | + tty_port_tty_set(port, NULL); | |
919 | 899 | } |
920 | 900 | |
921 | 901 | /*****************************************************************************/ |
... | ... | @@ -1482,7 +1462,7 @@ |
1482 | 1462 | sio.irq = 0; |
1483 | 1463 | sio.flags = portp->port.flags; |
1484 | 1464 | sio.baud_base = portp->baud_base; |
1485 | - sio.close_delay = portp->close_delay; | |
1465 | + sio.close_delay = portp->port.close_delay; | |
1486 | 1466 | sio.closing_wait = portp->closing_wait; |
1487 | 1467 | sio.custom_divisor = portp->custom_divisor; |
1488 | 1468 | sio.xmit_fifo_size = 0; |
... | ... | @@ -1514,7 +1494,7 @@ |
1514 | 1494 | return -EFAULT; |
1515 | 1495 | if (!capable(CAP_SYS_ADMIN)) { |
1516 | 1496 | if ((sio.baud_base != portp->baud_base) || |
1517 | - (sio.close_delay != portp->close_delay) || | |
1497 | + (sio.close_delay != portp->port.close_delay) || | |
1518 | 1498 | ((sio.flags & ~ASYNC_USR_MASK) != |
1519 | 1499 | (portp->port.flags & ~ASYNC_USR_MASK))) |
1520 | 1500 | return -EPERM; |
... | ... | @@ -1523,7 +1503,7 @@ |
1523 | 1503 | portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | |
1524 | 1504 | (sio.flags & ASYNC_USR_MASK); |
1525 | 1505 | portp->baud_base = sio.baud_base; |
1526 | - portp->close_delay = sio.close_delay; | |
1506 | + portp->port.close_delay = sio.close_delay; | |
1527 | 1507 | portp->closing_wait = sio.closing_wait; |
1528 | 1508 | portp->custom_divisor = sio.custom_divisor; |
1529 | 1509 | |
... | ... | @@ -2065,7 +2045,7 @@ |
2065 | 2045 | unsigned char __iomem *bits; |
2066 | 2046 | |
2067 | 2047 | if (test_bit(ST_CMDING, &portp->state)) { |
2068 | - printk(KERN_ERR "STALLION: command already busy, cmd=%x!\n", | |
2048 | + printk(KERN_ERR "istallion: command already busy, cmd=%x!\n", | |
2069 | 2049 | (int) cmd); |
2070 | 2050 | return; |
2071 | 2051 | } |
... | ... | @@ -2625,7 +2605,7 @@ |
2625 | 2605 | for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { |
2626 | 2606 | portp = kzalloc(sizeof(struct stliport), GFP_KERNEL); |
2627 | 2607 | if (!portp) { |
2628 | - printk("STALLION: failed to allocate port structure\n"); | |
2608 | + printk(KERN_WARNING "istallion: failed to allocate port structure\n"); | |
2629 | 2609 | continue; |
2630 | 2610 | } |
2631 | 2611 | tty_port_init(&portp->port); |
... | ... | @@ -2635,7 +2615,7 @@ |
2635 | 2615 | portp->brdnr = brdp->brdnr; |
2636 | 2616 | portp->panelnr = panelnr; |
2637 | 2617 | portp->baud_base = STL_BAUDBASE; |
2638 | - portp->close_delay = STL_CLOSEDELAY; | |
2618 | + portp->port.close_delay = STL_CLOSEDELAY; | |
2639 | 2619 | portp->closing_wait = 30 * HZ; |
2640 | 2620 | init_waitqueue_head(&portp->port.open_wait); |
2641 | 2621 | init_waitqueue_head(&portp->port.close_wait); |
... | ... | @@ -2692,7 +2672,7 @@ |
2692 | 2672 | unsigned char val; |
2693 | 2673 | |
2694 | 2674 | if (offset > brdp->memsize) { |
2695 | - printk(KERN_ERR "STALLION: shared memory pointer=%x out of " | |
2675 | + printk(KERN_ERR "istallion: shared memory pointer=%x out of " | |
2696 | 2676 | "range at line=%d(%d), brd=%d\n", |
2697 | 2677 | (int) offset, line, __LINE__, brdp->brdnr); |
2698 | 2678 | ptr = NULL; |
... | ... | @@ -2766,7 +2746,7 @@ |
2766 | 2746 | unsigned char val; |
2767 | 2747 | |
2768 | 2748 | if (offset > brdp->memsize) { |
2769 | - printk(KERN_ERR "STALLION: shared memory pointer=%x out of " | |
2749 | + printk(KERN_ERR "istallion: shared memory pointer=%x out of " | |
2770 | 2750 | "range at line=%d(%d), brd=%d\n", |
2771 | 2751 | (int) offset, line, __LINE__, brdp->brdnr); |
2772 | 2752 | ptr = NULL; |
... | ... | @@ -2818,7 +2798,7 @@ |
2818 | 2798 | unsigned char val; |
2819 | 2799 | |
2820 | 2800 | if (offset > brdp->memsize) { |
2821 | - printk(KERN_ERR "STALLION: shared memory pointer=%x out of " | |
2801 | + printk(KERN_ERR "istallion: shared memory pointer=%x out of " | |
2822 | 2802 | "range at line=%d(%d), brd=%d\n", |
2823 | 2803 | (int) offset, line, __LINE__, brdp->brdnr); |
2824 | 2804 | ptr = NULL; |
... | ... | @@ -2863,7 +2843,7 @@ |
2863 | 2843 | unsigned char val; |
2864 | 2844 | |
2865 | 2845 | if (offset > brdp->memsize) { |
2866 | - printk(KERN_ERR "STALLION: shared memory pointer=%x out of " | |
2846 | + printk(KERN_ERR "istallion: shared memory pointer=%x out of " | |
2867 | 2847 | "range at line=%d(%d), board=%d\n", |
2868 | 2848 | (int) offset, line, __LINE__, brdp->brdnr); |
2869 | 2849 | ptr = NULL; |
... | ... | @@ -2928,7 +2908,7 @@ |
2928 | 2908 | void __iomem *ptr; |
2929 | 2909 | |
2930 | 2910 | if (offset > brdp->memsize) { |
2931 | - printk(KERN_ERR "STALLION: shared memory pointer=%x out of " | |
2911 | + printk(KERN_ERR "istallion: shared memory pointer=%x out of " | |
2932 | 2912 | "range at line=%d(%d), brd=%d\n", |
2933 | 2913 | (int) offset, line, __LINE__, brdp->brdnr); |
2934 | 2914 | ptr = NULL; |
... | ... | @@ -2994,7 +2974,7 @@ |
2994 | 2974 | unsigned char val; |
2995 | 2975 | |
2996 | 2976 | if (offset > brdp->memsize) { |
2997 | - printk(KERN_ERR "STALLION: shared memory pointer=%x out of " | |
2977 | + printk(KERN_ERR "istallion: shared memory pointer=%x out of " | |
2998 | 2978 | "range at line=%d(%d), brd=%d\n", |
2999 | 2979 | (int) offset, line, __LINE__, brdp->brdnr); |
3000 | 2980 | ptr = NULL; |
... | ... | @@ -3433,7 +3413,7 @@ |
3433 | 3413 | #endif |
3434 | 3414 | |
3435 | 3415 | if (nrdevs < (brdp->nrports + 1)) { |
3436 | - printk(KERN_ERR "STALLION: slave failed to allocate memory for " | |
3416 | + printk(KERN_ERR "istallion: slave failed to allocate memory for " | |
3437 | 3417 | "all devices, devices=%d\n", nrdevs); |
3438 | 3418 | brdp->nrports = nrdevs - 1; |
3439 | 3419 | } |
3440 | 3420 | |
... | ... | @@ -3443,13 +3423,13 @@ |
3443 | 3423 | brdp->bitsize = (nrdevs + 7) / 8; |
3444 | 3424 | memoff = readl(&hdrp->memp); |
3445 | 3425 | if (memoff > brdp->memsize) { |
3446 | - printk(KERN_ERR "STALLION: corrupted shared memory region?\n"); | |
3426 | + printk(KERN_ERR "istallion: corrupted shared memory region?\n"); | |
3447 | 3427 | rc = -EIO; |
3448 | 3428 | goto stli_donestartup; |
3449 | 3429 | } |
3450 | 3430 | memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff); |
3451 | 3431 | if (readw(&memp->dtype) != TYP_ASYNCTRL) { |
3452 | - printk(KERN_ERR "STALLION: no slave control device found\n"); | |
3432 | + printk(KERN_ERR "istallion: no slave control device found\n"); | |
3453 | 3433 | goto stli_donestartup; |
3454 | 3434 | } |
3455 | 3435 | memp++; |
... | ... | @@ -3534,7 +3514,7 @@ |
3534 | 3514 | retval = stli_initonb(brdp); |
3535 | 3515 | break; |
3536 | 3516 | default: |
3537 | - printk(KERN_ERR "STALLION: board=%d is unknown board " | |
3517 | + printk(KERN_ERR "istallion: board=%d is unknown board " | |
3538 | 3518 | "type=%d\n", brdp->brdnr, brdp->brdtype); |
3539 | 3519 | retval = -ENODEV; |
3540 | 3520 | } |
... | ... | @@ -3543,7 +3523,7 @@ |
3543 | 3523 | return retval; |
3544 | 3524 | |
3545 | 3525 | stli_initports(brdp); |
3546 | - printk(KERN_INFO "STALLION: %s found, board=%d io=%x mem=%x " | |
3526 | + printk(KERN_INFO "istallion: %s found, board=%d io=%x mem=%x " | |
3547 | 3527 | "nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype], |
3548 | 3528 | brdp->brdnr, brdp->iobase, (int) brdp->memaddr, |
3549 | 3529 | brdp->nrpanels, brdp->nrports); |
... | ... | @@ -3637,7 +3617,7 @@ |
3637 | 3617 | if (! foundit) { |
3638 | 3618 | brdp->memaddr = 0; |
3639 | 3619 | brdp->membase = NULL; |
3640 | - printk(KERN_ERR "STALLION: failed to probe shared memory " | |
3620 | + printk(KERN_ERR "istallion: failed to probe shared memory " | |
3641 | 3621 | "region for %s in EISA slot=%d\n", |
3642 | 3622 | stli_brdnames[brdp->brdtype], (brdp->iobase >> 12)); |
3643 | 3623 | return -ENODEV; |
... | ... | @@ -3782,7 +3762,7 @@ |
3782 | 3762 | mutex_lock(&stli_brdslock); |
3783 | 3763 | brdnr = stli_getbrdnr(); |
3784 | 3764 | if (brdnr < 0) { |
3785 | - printk(KERN_INFO "STALLION: too many boards found, " | |
3765 | + printk(KERN_INFO "istallion: too many boards found, " | |
3786 | 3766 | "maximum supported %d\n", STL_MAXBRDS); |
3787 | 3767 | mutex_unlock(&stli_brdslock); |
3788 | 3768 | retval = -EIO; |
... | ... | @@ -3854,7 +3834,7 @@ |
3854 | 3834 | |
3855 | 3835 | brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL); |
3856 | 3836 | if (!brdp) { |
3857 | - printk(KERN_ERR "STALLION: failed to allocate memory " | |
3837 | + printk(KERN_ERR "istallion: failed to allocate memory " | |
3858 | 3838 | "(size=%Zd)\n", sizeof(struct stlibrd)); |
3859 | 3839 | return NULL; |
3860 | 3840 | } |
... | ... | @@ -4493,7 +4473,7 @@ |
4493 | 4473 | |
4494 | 4474 | stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); |
4495 | 4475 | if (!stli_txcookbuf) { |
4496 | - printk(KERN_ERR "STALLION: failed to allocate memory " | |
4476 | + printk(KERN_ERR "istallion: failed to allocate memory " | |
4497 | 4477 | "(size=%d)\n", STLI_TXBUFSIZE); |
4498 | 4478 | retval = -ENOMEM; |
4499 | 4479 | goto err; |
... | ... | @@ -4518,7 +4498,7 @@ |
4518 | 4498 | |
4519 | 4499 | retval = tty_register_driver(stli_serial); |
4520 | 4500 | if (retval) { |
4521 | - printk(KERN_ERR "STALLION: failed to register serial driver\n"); | |
4501 | + printk(KERN_ERR "istallion: failed to register serial driver\n"); | |
4522 | 4502 | goto err_ttyput; |
4523 | 4503 | } |
4524 | 4504 | |
... | ... | @@ -4532,7 +4512,7 @@ |
4532 | 4512 | */ |
4533 | 4513 | retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem); |
4534 | 4514 | if (retval) { |
4535 | - printk(KERN_ERR "STALLION: failed to register serial memory " | |
4515 | + printk(KERN_ERR "istallion: failed to register serial memory " | |
4536 | 4516 | "device\n"); |
4537 | 4517 | goto err_deinit; |
4538 | 4518 | } |
drivers/char/mxser.c
... | ... | @@ -1080,58 +1080,27 @@ |
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); | |
1093 | - | |
1094 | - if (tty_hung_up_p(filp)) { | |
1095 | - spin_unlock_irqrestore(&info->port.lock, flags); | |
1092 | + if (tty_port_close_start(port, tty, filp) == 0) | |
1096 | 1093 | 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); | |
1094 | + | |
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 | 1103 | /* |
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 | - /* | |
1135 | 1104 | * At this point we stop accepting input. To do this, we |
1136 | 1105 | * disable the receive line status interrupts, and tell the |
1137 | 1106 | * interrupt driver to stop checking the data ready bit in the |
1138 | 1107 | |
1139 | 1108 | |
... | ... | @@ -1156,19 +1125,12 @@ |
1156 | 1125 | } |
1157 | 1126 | } |
1158 | 1127 | mxser_shutdown(tty); |
1159 | - | |
1160 | 1128 | mxser_flush_buffer(tty); |
1161 | - tty_ldisc_flush(tty); | |
1162 | 1129 | |
1163 | - tty->closing = 0; | |
1164 | - tty_port_tty_set(&info->port, NULL); | |
1165 | - if (info->port.blocked_open) { | |
1166 | - if (info->port.close_delay) | |
1167 | - schedule_timeout_interruptible(info->port.close_delay); | |
1168 | - wake_up_interruptible(&info->port.open_wait); | |
1169 | - } | |
1170 | - | |
1171 | - info->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); | |
1130 | + /* Right now the tty_port set is done outside of the close_end helper | |
1131 | + as we don't yet have everyone using refcounts */ | |
1132 | + tty_port_close_end(port, tty); | |
1133 | + tty_port_tty_set(port, NULL); | |
1172 | 1134 | } |
1173 | 1135 | |
1174 | 1136 | static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) |
drivers/char/riscom8.c
... | ... | @@ -929,36 +929,12 @@ |
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; | |
933 | + | |
934 | + if (tty_port_close_start(&port->port, tty, filp) == 0) | |
935 | + return; | |
936 | + | |
953 | 937 | /* |
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); | |
961 | - /* | |
962 | 938 | * At this point we stop accepting input. To do this, we |
963 | 939 | * disable the receive line status interrupts, and tell the |
964 | 940 | * interrupt driver to stop checking the data ready bit in the |
965 | 941 | |
... | ... | @@ -989,23 +965,8 @@ |
989 | 965 | rc_shutdown_port(tty, bp, port); |
990 | 966 | rc_flush_buffer(tty); |
991 | 967 | spin_unlock_irqrestore(&riscom_lock, flags); |
992 | - tty_ldisc_flush(tty); | |
993 | 968 | |
994 | - spin_lock_irqsave(&port->port.lock, flags); | |
995 | - tty->closing = 0; | |
996 | - port->port.tty = NULL; | |
997 | - if (port->port.blocked_open) { | |
998 | - spin_unlock_irqrestore(&port->port.lock, flags); | |
999 | - if (port->port.close_delay) | |
1000 | - msleep_interruptible(jiffies_to_msecs(port->port.close_delay)); | |
1001 | - wake_up_interruptible(&port->port.open_wait); | |
1002 | - spin_lock_irqsave(&port->port.lock, flags); | |
1003 | - } | |
1004 | - port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | |
1005 | - wake_up_interruptible(&port->port.close_wait); | |
1006 | - | |
1007 | -out: | |
1008 | - spin_unlock_irqrestore(&riscom_lock, flags); | |
969 | + tty_port_close_end(&port->port, tty); | |
1009 | 970 | } |
1010 | 971 | |
1011 | 972 | static int rc_write(struct tty_struct *tty, |
drivers/char/stallion.c
... | ... | @@ -833,40 +833,20 @@ |
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 | 849 | |
869 | - | |
870 | 850 | spin_lock_irqsave(&port->lock, flags); |
871 | 851 | portp->port.flags &= ~ASYNC_INITIALIZED; |
872 | 852 | spin_unlock_irqrestore(&port->lock, flags); |
873 | 853 | |
874 | 854 | |
... | ... | @@ -883,20 +863,9 @@ |
883 | 863 | portp->tx.head = NULL; |
884 | 864 | portp->tx.tail = NULL; |
885 | 865 | } |
886 | - set_bit(TTY_IO_ERROR, &tty->flags); | |
887 | - tty_ldisc_flush(tty); | |
888 | 866 | |
889 | - tty->closing = 0; | |
867 | + tty_port_close_end(port, tty); | |
890 | 868 | tty_port_tty_set(port, NULL); |
891 | - | |
892 | - if (port->blocked_open) { | |
893 | - if (portp->close_delay) | |
894 | - msleep_interruptible(jiffies_to_msecs(portp->close_delay)); | |
895 | - wake_up_interruptible(&portp->port.open_wait); | |
896 | - } | |
897 | - | |
898 | - portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | |
899 | - wake_up_interruptible(&port->close_wait); | |
900 | 869 | } |
901 | 870 | |
902 | 871 | /*****************************************************************************/ |
drivers/char/synclink.c
... | ... | @@ -3104,70 +3104,18 @@ |
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__, |
drivers/char/synclink_gt.c
... | ... | @@ -720,44 +720,9 @@ |
720 | 720 | return; |
721 | 721 | DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count)); |
722 | 722 | |
723 | - if (!info->port.count) | |
724 | - return; | |
725 | - | |
726 | - if (tty_hung_up_p(filp)) | |
723 | + if (tty_port_close_start(&info->port, tty, filp) == 0) | |
727 | 724 | goto cleanup; |
728 | 725 | |
729 | - if ((tty->count == 1) && (info->port.count != 1)) { | |
730 | - /* | |
731 | - * tty->count is 1 and the tty structure will be freed. | |
732 | - * info->port.count should be one in this case. | |
733 | - * if it's not, correct it so that the port is shutdown. | |
734 | - */ | |
735 | - DBGERR(("%s close: bad refcount; tty->count=1, " | |
736 | - "info->port.count=%d\n", info->device_name, info->port.count)); | |
737 | - info->port.count = 1; | |
738 | - } | |
739 | - | |
740 | - info->port.count--; | |
741 | - | |
742 | - /* if at least one open remaining, leave hardware active */ | |
743 | - if (info->port.count) | |
744 | - goto cleanup; | |
745 | - | |
746 | - info->port.flags |= ASYNC_CLOSING; | |
747 | - | |
748 | - /* set tty->closing to notify line discipline to | |
749 | - * only process XON/XOFF characters. Only the N_TTY | |
750 | - * discipline appears to use this (ppp does not). | |
751 | - */ | |
752 | - tty->closing = 1; | |
753 | - | |
754 | - /* wait for transmit data to clear all layers */ | |
755 | - | |
756 | - if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) { | |
757 | - DBGINFO(("%s call tty_wait_until_sent\n", info->device_name)); | |
758 | - tty_wait_until_sent(tty, info->port.closing_wait); | |
759 | - } | |
760 | - | |
761 | 726 | if (info->port.flags & ASYNC_INITIALIZED) |
762 | 727 | wait_until_sent(tty, info->timeout); |
763 | 728 | flush_buffer(tty); |
764 | 729 | |
... | ... | @@ -765,20 +730,8 @@ |
765 | 730 | |
766 | 731 | shutdown(info); |
767 | 732 | |
768 | - tty->closing = 0; | |
733 | + tty_port_close_end(&info->port, tty); | |
769 | 734 | info->port.tty = NULL; |
770 | - | |
771 | - if (info->port.blocked_open) { | |
772 | - if (info->port.close_delay) { | |
773 | - msleep_interruptible(jiffies_to_msecs(info->port.close_delay)); | |
774 | - } | |
775 | - wake_up_interruptible(&info->port.open_wait); | |
776 | - } | |
777 | - | |
778 | - info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | |
779 | - | |
780 | - wake_up_interruptible(&info->port.close_wait); | |
781 | - | |
782 | 735 | cleanup: |
783 | 736 | DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count)); |
784 | 737 | } |
drivers/char/synclinkmp.c
... | ... | @@ -810,70 +810,18 @@ |
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__, |
drivers/char/tty_port.c
... | ... | @@ -256,4 +256,63 @@ |
256 | 256 | |
257 | 257 | } |
258 | 258 | EXPORT_SYMBOL(tty_port_block_til_ready); |
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); |
include/linux/istallion.h
include/linux/tty.h
... | ... | @@ -441,6 +441,9 @@ |
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); |