diff options
author | Alan Cox <alan@redhat.com> | 2009-01-02 08:46:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 13:19:40 -0500 |
commit | a6614999e800cf3a134ce93ea46ef837e3c0e76e (patch) | |
tree | 56b0a29ed004a284561a4c3ff3ee52075acabb65 /drivers/char | |
parent | 7834909f1eb96ba7c49ca2b9e3a69b500a2cff76 (diff) |
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>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/isicom.c | 66 | ||||
-rw-r--r-- | drivers/char/istallion.c | 78 | ||||
-rw-r--r-- | drivers/char/mxser.c | 56 | ||||
-rw-r--r-- | drivers/char/riscom8.c | 49 | ||||
-rw-r--r-- | drivers/char/stallion.c | 39 | ||||
-rw-r--r-- | drivers/char/synclink.c | 58 | ||||
-rw-r--r-- | drivers/char/synclink_gt.c | 51 | ||||
-rw-r--r-- | drivers/char/synclinkmp.c | 58 | ||||
-rw-r--r-- | drivers/char/tty_port.c | 58 |
9 files changed, 123 insertions, 390 deletions
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index bac55cf4424..24aa6e88e22 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -945,76 +945,30 @@ static void isicom_flush_buffer(struct tty_struct *tty) | |||
945 | 945 | ||
946 | static void isicom_close(struct tty_struct *tty, struct file *filp) | 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 | struct isi_board *card; | 950 | struct isi_board *card; |
950 | unsigned long flags; | 951 | unsigned long flags; |
951 | 952 | ||
952 | if (!port) | 953 | BUG_ON(!ip); |
953 | return; | ||
954 | card = port->card; | ||
955 | if (isicom_paranoia_check(port, tty->name, "isicom_close")) | ||
956 | return; | ||
957 | |||
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 | 954 | ||
979 | if (port->port.count) { | 955 | card = ip->card; |
980 | spin_unlock_irqrestore(&port->port.lock, flags); | 956 | if (isicom_paranoia_check(ip, tty->name, "isicom_close")) |
981 | return; | 957 | return; |
982 | } | ||
983 | port->port.flags |= ASYNC_CLOSING; | ||
984 | tty->closing = 1; | ||
985 | spin_unlock_irqrestore(&port->port.lock, flags); | ||
986 | 958 | ||
987 | if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
988 | tty_wait_until_sent(tty, port->port.closing_wait); | ||
989 | /* indicate to the card that no more data can be received | 959 | /* indicate to the card that no more data can be received |
990 | on this port */ | 960 | on this port */ |
991 | spin_lock_irqsave(&card->card_lock, flags); | 961 | spin_lock_irqsave(&card->card_lock, flags); |
992 | if (port->port.flags & ASYNC_INITIALIZED) { | 962 | if (port->flags & ASYNC_INITIALIZED) { |
993 | card->port_status &= ~(1 << port->channel); | 963 | card->port_status &= ~(1 << ip->channel); |
994 | outw(card->port_status, card->base + 0x02); | 964 | outw(card->port_status, card->base + 0x02); |
995 | } | 965 | } |
996 | isicom_shutdown_port(port); | 966 | isicom_shutdown_port(ip); |
997 | spin_unlock_irqrestore(&card->card_lock, flags); | 967 | spin_unlock_irqrestore(&card->card_lock, flags); |
998 | 968 | ||
999 | isicom_flush_buffer(tty); | 969 | isicom_flush_buffer(tty); |
1000 | tty_ldisc_flush(tty); | 970 | |
1001 | 971 | tty_port_close_end(port, tty); | |
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); | ||
1018 | } | 972 | } |
1019 | 973 | ||
1020 | /* write et all */ | 974 | /* write et all */ |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 4c69ab97339..5c3dc6b8411 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -767,7 +767,7 @@ static int stli_parsebrd(struct stlconf *confp, char **argp) | |||
767 | break; | 767 | break; |
768 | } | 768 | } |
769 | if (i == ARRAY_SIZE(stli_brdstr)) { | 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 | return 0; | 771 | return 0; |
772 | } | 772 | } |
773 | 773 | ||
@@ -855,21 +855,8 @@ static void stli_close(struct tty_struct *tty, struct file *filp) | |||
855 | return; | 855 | return; |
856 | port = &portp->port; | 856 | port = &portp->port; |
857 | 857 | ||
858 | spin_lock_irqsave(&port->lock, flags); | 858 | if (tty_port_close_start(port, tty, filp) == 0) |
859 | if (tty_hung_up_p(filp)) { | ||
860 | spin_unlock_irqrestore(&port->lock, flags); | ||
861 | 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; | 859 | return; |
868 | } | ||
869 | |||
870 | port->flags |= ASYNC_CLOSING; | ||
871 | tty->closing = 1; | ||
872 | spin_unlock_irqrestore(&port->lock, flags); | ||
873 | 860 | ||
874 | /* | 861 | /* |
875 | * May want to wait for data to drain before closing. The BUSY flag | 862 | * May want to wait for data to drain before closing. The BUSY flag |
@@ -882,6 +869,8 @@ static void stli_close(struct tty_struct *tty, struct file *filp) | |||
882 | stli_flushchars(tty); | 869 | stli_flushchars(tty); |
883 | spin_unlock_irqrestore(&stli_lock, flags); | 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 | if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 874 | if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
886 | tty_wait_until_sent(tty, portp->closing_wait); | 875 | tty_wait_until_sent(tty, portp->closing_wait); |
887 | 876 | ||
@@ -905,17 +894,8 @@ static void stli_close(struct tty_struct *tty, struct file *filp) | |||
905 | set_bit(ST_DOFLUSHRX, &portp->state); | 894 | set_bit(ST_DOFLUSHRX, &portp->state); |
906 | stli_flushbuffer(tty); | 895 | stli_flushbuffer(tty); |
907 | 896 | ||
908 | tty->closing = 0; | 897 | tty_port_close_end(port, tty); |
909 | tty_port_tty_set(&portp->port, NULL); | 898 | tty_port_tty_set(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); | ||
919 | } | 899 | } |
920 | 900 | ||
921 | /*****************************************************************************/ | 901 | /*****************************************************************************/ |
@@ -1482,7 +1462,7 @@ static int stli_getserial(struct stliport *portp, struct serial_struct __user *s | |||
1482 | sio.irq = 0; | 1462 | sio.irq = 0; |
1483 | sio.flags = portp->port.flags; | 1463 | sio.flags = portp->port.flags; |
1484 | sio.baud_base = portp->baud_base; | 1464 | sio.baud_base = portp->baud_base; |
1485 | sio.close_delay = portp->close_delay; | 1465 | sio.close_delay = portp->port.close_delay; |
1486 | sio.closing_wait = portp->closing_wait; | 1466 | sio.closing_wait = portp->closing_wait; |
1487 | sio.custom_divisor = portp->custom_divisor; | 1467 | sio.custom_divisor = portp->custom_divisor; |
1488 | sio.xmit_fifo_size = 0; | 1468 | sio.xmit_fifo_size = 0; |
@@ -1514,7 +1494,7 @@ static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *s | |||
1514 | return -EFAULT; | 1494 | return -EFAULT; |
1515 | if (!capable(CAP_SYS_ADMIN)) { | 1495 | if (!capable(CAP_SYS_ADMIN)) { |
1516 | if ((sio.baud_base != portp->baud_base) || | 1496 | if ((sio.baud_base != portp->baud_base) || |
1517 | (sio.close_delay != portp->close_delay) || | 1497 | (sio.close_delay != portp->port.close_delay) || |
1518 | ((sio.flags & ~ASYNC_USR_MASK) != | 1498 | ((sio.flags & ~ASYNC_USR_MASK) != |
1519 | (portp->port.flags & ~ASYNC_USR_MASK))) | 1499 | (portp->port.flags & ~ASYNC_USR_MASK))) |
1520 | return -EPERM; | 1500 | return -EPERM; |
@@ -1523,7 +1503,7 @@ static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *s | |||
1523 | portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | | 1503 | portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | |
1524 | (sio.flags & ASYNC_USR_MASK); | 1504 | (sio.flags & ASYNC_USR_MASK); |
1525 | portp->baud_base = sio.baud_base; | 1505 | portp->baud_base = sio.baud_base; |
1526 | portp->close_delay = sio.close_delay; | 1506 | portp->port.close_delay = sio.close_delay; |
1527 | portp->closing_wait = sio.closing_wait; | 1507 | portp->closing_wait = sio.closing_wait; |
1528 | portp->custom_divisor = sio.custom_divisor; | 1508 | portp->custom_divisor = sio.custom_divisor; |
1529 | 1509 | ||
@@ -2065,7 +2045,7 @@ static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigne | |||
2065 | unsigned char __iomem *bits; | 2045 | unsigned char __iomem *bits; |
2066 | 2046 | ||
2067 | if (test_bit(ST_CMDING, &portp->state)) { | 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 | (int) cmd); | 2049 | (int) cmd); |
2070 | return; | 2050 | return; |
2071 | } | 2051 | } |
@@ -2625,7 +2605,7 @@ static int stli_initports(struct stlibrd *brdp) | |||
2625 | for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { | 2605 | for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { |
2626 | portp = kzalloc(sizeof(struct stliport), GFP_KERNEL); | 2606 | portp = kzalloc(sizeof(struct stliport), GFP_KERNEL); |
2627 | if (!portp) { | 2607 | if (!portp) { |
2628 | printk("STALLION: failed to allocate port structure\n"); | 2608 | printk(KERN_WARNING "istallion: failed to allocate port structure\n"); |
2629 | continue; | 2609 | continue; |
2630 | } | 2610 | } |
2631 | tty_port_init(&portp->port); | 2611 | tty_port_init(&portp->port); |
@@ -2635,7 +2615,7 @@ static int stli_initports(struct stlibrd *brdp) | |||
2635 | portp->brdnr = brdp->brdnr; | 2615 | portp->brdnr = brdp->brdnr; |
2636 | portp->panelnr = panelnr; | 2616 | portp->panelnr = panelnr; |
2637 | portp->baud_base = STL_BAUDBASE; | 2617 | portp->baud_base = STL_BAUDBASE; |
2638 | portp->close_delay = STL_CLOSEDELAY; | 2618 | portp->port.close_delay = STL_CLOSEDELAY; |
2639 | portp->closing_wait = 30 * HZ; | 2619 | portp->closing_wait = 30 * HZ; |
2640 | init_waitqueue_head(&portp->port.open_wait); | 2620 | init_waitqueue_head(&portp->port.open_wait); |
2641 | init_waitqueue_head(&portp->port.close_wait); | 2621 | init_waitqueue_head(&portp->port.close_wait); |
@@ -2692,7 +2672,7 @@ static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offse | |||
2692 | unsigned char val; | 2672 | unsigned char val; |
2693 | 2673 | ||
2694 | if (offset > brdp->memsize) { | 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 | "range at line=%d(%d), brd=%d\n", | 2676 | "range at line=%d(%d), brd=%d\n", |
2697 | (int) offset, line, __LINE__, brdp->brdnr); | 2677 | (int) offset, line, __LINE__, brdp->brdnr); |
2698 | ptr = NULL; | 2678 | ptr = NULL; |
@@ -2766,7 +2746,7 @@ static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long off | |||
2766 | unsigned char val; | 2746 | unsigned char val; |
2767 | 2747 | ||
2768 | if (offset > brdp->memsize) { | 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 | "range at line=%d(%d), brd=%d\n", | 2750 | "range at line=%d(%d), brd=%d\n", |
2771 | (int) offset, line, __LINE__, brdp->brdnr); | 2751 | (int) offset, line, __LINE__, brdp->brdnr); |
2772 | ptr = NULL; | 2752 | ptr = NULL; |
@@ -2818,7 +2798,7 @@ static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long off | |||
2818 | unsigned char val; | 2798 | unsigned char val; |
2819 | 2799 | ||
2820 | if (offset > brdp->memsize) { | 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 | "range at line=%d(%d), brd=%d\n", | 2802 | "range at line=%d(%d), brd=%d\n", |
2823 | (int) offset, line, __LINE__, brdp->brdnr); | 2803 | (int) offset, line, __LINE__, brdp->brdnr); |
2824 | ptr = NULL; | 2804 | ptr = NULL; |
@@ -2863,7 +2843,7 @@ static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long of | |||
2863 | unsigned char val; | 2843 | unsigned char val; |
2864 | 2844 | ||
2865 | if (offset > brdp->memsize) { | 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 | "range at line=%d(%d), board=%d\n", | 2847 | "range at line=%d(%d), board=%d\n", |
2868 | (int) offset, line, __LINE__, brdp->brdnr); | 2848 | (int) offset, line, __LINE__, brdp->brdnr); |
2869 | ptr = NULL; | 2849 | ptr = NULL; |
@@ -2928,7 +2908,7 @@ static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offse | |||
2928 | void __iomem *ptr; | 2908 | void __iomem *ptr; |
2929 | 2909 | ||
2930 | if (offset > brdp->memsize) { | 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 | "range at line=%d(%d), brd=%d\n", | 2912 | "range at line=%d(%d), brd=%d\n", |
2933 | (int) offset, line, __LINE__, brdp->brdnr); | 2913 | (int) offset, line, __LINE__, brdp->brdnr); |
2934 | ptr = NULL; | 2914 | ptr = NULL; |
@@ -2994,7 +2974,7 @@ static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offs | |||
2994 | unsigned char val; | 2974 | unsigned char val; |
2995 | 2975 | ||
2996 | if (offset > brdp->memsize) { | 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 | "range at line=%d(%d), brd=%d\n", | 2978 | "range at line=%d(%d), brd=%d\n", |
2999 | (int) offset, line, __LINE__, brdp->brdnr); | 2979 | (int) offset, line, __LINE__, brdp->brdnr); |
3000 | ptr = NULL; | 2980 | ptr = NULL; |
@@ -3433,7 +3413,7 @@ static int stli_startbrd(struct stlibrd *brdp) | |||
3433 | #endif | 3413 | #endif |
3434 | 3414 | ||
3435 | if (nrdevs < (brdp->nrports + 1)) { | 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 | "all devices, devices=%d\n", nrdevs); | 3417 | "all devices, devices=%d\n", nrdevs); |
3438 | brdp->nrports = nrdevs - 1; | 3418 | brdp->nrports = nrdevs - 1; |
3439 | } | 3419 | } |
@@ -3443,13 +3423,13 @@ static int stli_startbrd(struct stlibrd *brdp) | |||
3443 | brdp->bitsize = (nrdevs + 7) / 8; | 3423 | brdp->bitsize = (nrdevs + 7) / 8; |
3444 | memoff = readl(&hdrp->memp); | 3424 | memoff = readl(&hdrp->memp); |
3445 | if (memoff > brdp->memsize) { | 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 | rc = -EIO; | 3427 | rc = -EIO; |
3448 | goto stli_donestartup; | 3428 | goto stli_donestartup; |
3449 | } | 3429 | } |
3450 | memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff); | 3430 | memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff); |
3451 | if (readw(&memp->dtype) != TYP_ASYNCTRL) { | 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 | goto stli_donestartup; | 3433 | goto stli_donestartup; |
3454 | } | 3434 | } |
3455 | memp++; | 3435 | memp++; |
@@ -3534,7 +3514,7 @@ static int __devinit stli_brdinit(struct stlibrd *brdp) | |||
3534 | retval = stli_initonb(brdp); | 3514 | retval = stli_initonb(brdp); |
3535 | break; | 3515 | break; |
3536 | default: | 3516 | default: |
3537 | printk(KERN_ERR "STALLION: board=%d is unknown board " | 3517 | printk(KERN_ERR "istallion: board=%d is unknown board " |
3538 | "type=%d\n", brdp->brdnr, brdp->brdtype); | 3518 | "type=%d\n", brdp->brdnr, brdp->brdtype); |
3539 | retval = -ENODEV; | 3519 | retval = -ENODEV; |
3540 | } | 3520 | } |
@@ -3543,7 +3523,7 @@ static int __devinit stli_brdinit(struct stlibrd *brdp) | |||
3543 | return retval; | 3523 | return retval; |
3544 | 3524 | ||
3545 | stli_initports(brdp); | 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 | "nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype], | 3527 | "nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype], |
3548 | brdp->brdnr, brdp->iobase, (int) brdp->memaddr, | 3528 | brdp->brdnr, brdp->iobase, (int) brdp->memaddr, |
3549 | brdp->nrpanels, brdp->nrports); | 3529 | brdp->nrpanels, brdp->nrports); |
@@ -3637,7 +3617,7 @@ static int stli_eisamemprobe(struct stlibrd *brdp) | |||
3637 | if (! foundit) { | 3617 | if (! foundit) { |
3638 | brdp->memaddr = 0; | 3618 | brdp->memaddr = 0; |
3639 | brdp->membase = NULL; | 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 | "region for %s in EISA slot=%d\n", | 3621 | "region for %s in EISA slot=%d\n", |
3642 | stli_brdnames[brdp->brdtype], (brdp->iobase >> 12)); | 3622 | stli_brdnames[brdp->brdtype], (brdp->iobase >> 12)); |
3643 | return -ENODEV; | 3623 | return -ENODEV; |
@@ -3782,7 +3762,7 @@ static int __devinit stli_pciprobe(struct pci_dev *pdev, | |||
3782 | mutex_lock(&stli_brdslock); | 3762 | mutex_lock(&stli_brdslock); |
3783 | brdnr = stli_getbrdnr(); | 3763 | brdnr = stli_getbrdnr(); |
3784 | if (brdnr < 0) { | 3764 | if (brdnr < 0) { |
3785 | printk(KERN_INFO "STALLION: too many boards found, " | 3765 | printk(KERN_INFO "istallion: too many boards found, " |
3786 | "maximum supported %d\n", STL_MAXBRDS); | 3766 | "maximum supported %d\n", STL_MAXBRDS); |
3787 | mutex_unlock(&stli_brdslock); | 3767 | mutex_unlock(&stli_brdslock); |
3788 | retval = -EIO; | 3768 | retval = -EIO; |
@@ -3854,7 +3834,7 @@ static struct stlibrd *stli_allocbrd(void) | |||
3854 | 3834 | ||
3855 | brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL); | 3835 | brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL); |
3856 | if (!brdp) { | 3836 | if (!brdp) { |
3857 | printk(KERN_ERR "STALLION: failed to allocate memory " | 3837 | printk(KERN_ERR "istallion: failed to allocate memory " |
3858 | "(size=%Zd)\n", sizeof(struct stlibrd)); | 3838 | "(size=%Zd)\n", sizeof(struct stlibrd)); |
3859 | return NULL; | 3839 | return NULL; |
3860 | } | 3840 | } |
@@ -4493,7 +4473,7 @@ static int __init istallion_module_init(void) | |||
4493 | 4473 | ||
4494 | stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); | 4474 | stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); |
4495 | if (!stli_txcookbuf) { | 4475 | if (!stli_txcookbuf) { |
4496 | printk(KERN_ERR "STALLION: failed to allocate memory " | 4476 | printk(KERN_ERR "istallion: failed to allocate memory " |
4497 | "(size=%d)\n", STLI_TXBUFSIZE); | 4477 | "(size=%d)\n", STLI_TXBUFSIZE); |
4498 | retval = -ENOMEM; | 4478 | retval = -ENOMEM; |
4499 | goto err; | 4479 | goto err; |
@@ -4518,7 +4498,7 @@ static int __init istallion_module_init(void) | |||
4518 | 4498 | ||
4519 | retval = tty_register_driver(stli_serial); | 4499 | retval = tty_register_driver(stli_serial); |
4520 | if (retval) { | 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 | goto err_ttyput; | 4502 | goto err_ttyput; |
4523 | } | 4503 | } |
4524 | 4504 | ||
@@ -4532,7 +4512,7 @@ static int __init istallion_module_init(void) | |||
4532 | */ | 4512 | */ |
4533 | retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem); | 4513 | retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem); |
4534 | if (retval) { | 4514 | if (retval) { |
4535 | printk(KERN_ERR "STALLION: failed to register serial memory " | 4515 | printk(KERN_ERR "istallion: failed to register serial memory " |
4536 | "device\n"); | 4516 | "device\n"); |
4537 | goto err_deinit; | 4517 | goto err_deinit; |
4538 | } | 4518 | } |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 08ba6eb1a38..402c9f217f8 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -1080,58 +1080,27 @@ static void mxser_flush_buffer(struct tty_struct *tty) | |||
1080 | static void mxser_close(struct tty_struct *tty, struct file *filp) | 1080 | static void mxser_close(struct tty_struct *tty, struct file *filp) |
1081 | { | 1081 | { |
1082 | struct mxser_port *info = tty->driver_data; | 1082 | struct mxser_port *info = tty->driver_data; |
1083 | struct tty_port *port = &info->port; | ||
1083 | 1084 | ||
1084 | unsigned long timeout; | 1085 | unsigned long timeout; |
1085 | unsigned long flags; | ||
1086 | 1086 | ||
1087 | if (tty->index == MXSER_PORTS) | 1087 | if (tty->index == MXSER_PORTS) |
1088 | return; | 1088 | return; |
1089 | if (!info) | 1089 | if (!info) |
1090 | return; | 1090 | return; |
1091 | 1091 | ||
1092 | spin_lock_irqsave(&info->port.lock, flags); | 1092 | if (tty_port_close_start(port, tty, filp) == 0) |
1093 | |||
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; | 1093 | return; |
1118 | } | 1094 | |
1119 | info->port.flags |= ASYNC_CLOSING; | ||
1120 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
1121 | /* | 1095 | /* |
1122 | * Save the termios structure, since this port may have | 1096 | * Save the termios structure, since this port may have |
1123 | * separate termios for callout and dialin. | 1097 | * separate termios for callout and dialin. |
1098 | * | ||
1099 | * FIXME: Can this go ? | ||
1124 | */ | 1100 | */ |
1125 | if (info->port.flags & ASYNC_NORMAL_ACTIVE) | 1101 | if (info->port.flags & ASYNC_NORMAL_ACTIVE) |
1126 | info->normal_termios = *tty->termios; | 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 | * At this point we stop accepting input. To do this, we | 1104 | * At this point we stop accepting input. To do this, we |
1136 | * disable the receive line status interrupts, and tell the | 1105 | * disable the receive line status interrupts, and tell the |
1137 | * interrupt driver to stop checking the data ready bit in the | 1106 | * interrupt driver to stop checking the data ready bit in the |
@@ -1156,19 +1125,12 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1156 | } | 1125 | } |
1157 | } | 1126 | } |
1158 | mxser_shutdown(tty); | 1127 | mxser_shutdown(tty); |
1159 | |||
1160 | mxser_flush_buffer(tty); | 1128 | mxser_flush_buffer(tty); |
1161 | tty_ldisc_flush(tty); | ||
1162 | |||
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 | 1129 | ||
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 | static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) | 1136 | static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index af34c2054a0..9ac5febd8ab 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -929,35 +929,11 @@ static void rc_close(struct tty_struct *tty, struct file *filp) | |||
929 | if (!port || rc_paranoia_check(port, tty->name, "close")) | 929 | if (!port || rc_paranoia_check(port, tty->name, "close")) |
930 | return; | 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 | bp = port_Board(port); | 932 | bp = port_Board(port); |
938 | if ((tty->count == 1) && (port->port.count != 1)) { | 933 | |
939 | printk(KERN_INFO "rc%d: rc_close: bad port count;" | 934 | if (tty_port_close_start(&port->port, tty, filp) == 0) |
940 | " tty->count is 1, port count is %d\n", | 935 | return; |
941 | board_No(bp), port->port.count); | 936 | |
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); | ||
961 | /* | 937 | /* |
962 | * At this point we stop accepting input. To do this, we | 938 | * At this point we stop accepting input. To do this, we |
963 | * disable the receive line status interrupts, and tell the | 939 | * disable the receive line status interrupts, and tell the |
@@ -989,23 +965,8 @@ static void rc_close(struct tty_struct *tty, struct file *filp) | |||
989 | rc_shutdown_port(tty, bp, port); | 965 | rc_shutdown_port(tty, bp, port); |
990 | rc_flush_buffer(tty); | 966 | rc_flush_buffer(tty); |
991 | spin_unlock_irqrestore(&riscom_lock, flags); | 967 | spin_unlock_irqrestore(&riscom_lock, flags); |
992 | tty_ldisc_flush(tty); | ||
993 | 968 | ||
994 | spin_lock_irqsave(&port->port.lock, flags); | 969 | tty_port_close_end(&port->port, tty); |
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); | ||
1009 | } | 970 | } |
1010 | 971 | ||
1011 | static int rc_write(struct tty_struct *tty, | 972 | static int rc_write(struct tty_struct *tty, |
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 77eef61c46f..e1e0dd89ac9 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -833,40 +833,20 @@ static void stl_close(struct tty_struct *tty, struct file *filp) | |||
833 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); | 833 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); |
834 | 834 | ||
835 | portp = tty->driver_data; | 835 | portp = tty->driver_data; |
836 | if (portp == NULL) | 836 | BUG_ON(portp == NULL); |
837 | return; | 837 | |
838 | port = &portp->port; | 838 | port = &portp->port; |
839 | 839 | ||
840 | spin_lock_irqsave(&port->lock, flags); | 840 | if (tty_port_close_start(port, tty, filp) == 0) |
841 | if (tty_hung_up_p(filp)) { | ||
842 | spin_unlock_irqrestore(&port->lock, flags); | ||
843 | return; | 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 | * May want to wait for any data to drain before closing. The BUSY | 843 | * May want to wait for any data to drain before closing. The BUSY |
857 | * flag keeps track of whether we are still sending or not - it is | 844 | * flag keeps track of whether we are still sending or not - it is |
858 | * very accurate for the cd1400, not quite so for the sc26198. | 845 | * very accurate for the cd1400, not quite so for the sc26198. |
859 | * (The sc26198 has no "end-of-data" interrupt only empty FIFO) | 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 | stl_waituntilsent(tty, (HZ / 2)); | 848 | stl_waituntilsent(tty, (HZ / 2)); |
868 | 849 | ||
869 | |||
870 | spin_lock_irqsave(&port->lock, flags); | 850 | spin_lock_irqsave(&port->lock, flags); |
871 | portp->port.flags &= ~ASYNC_INITIALIZED; | 851 | portp->port.flags &= ~ASYNC_INITIALIZED; |
872 | spin_unlock_irqrestore(&port->lock, flags); | 852 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -883,20 +863,9 @@ static void stl_close(struct tty_struct *tty, struct file *filp) | |||
883 | portp->tx.head = NULL; | 863 | portp->tx.head = NULL; |
884 | portp->tx.tail = NULL; | 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 | tty_port_tty_set(port, NULL); | 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 | /*****************************************************************************/ |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 0ded4ed3da3..fbd5a5ce2e1 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -3104,70 +3104,18 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp) | |||
3104 | if (debug_level >= DEBUG_LEVEL_INFO) | 3104 | if (debug_level >= DEBUG_LEVEL_INFO) |
3105 | printk("%s(%d):mgsl_close(%s) entry, count=%d\n", | 3105 | printk("%s(%d):mgsl_close(%s) entry, count=%d\n", |
3106 | __FILE__,__LINE__, info->device_name, info->port.count); | 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 | goto cleanup; | 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 | if (info->port.flags & ASYNC_INITIALIZED) | 3111 | if (info->port.flags & ASYNC_INITIALIZED) |
3149 | mgsl_wait_until_sent(tty, info->timeout); | 3112 | mgsl_wait_until_sent(tty, info->timeout); |
3150 | |||
3151 | mgsl_flush_buffer(tty); | 3113 | mgsl_flush_buffer(tty); |
3152 | |||
3153 | tty_ldisc_flush(tty); | 3114 | tty_ldisc_flush(tty); |
3154 | |||
3155 | shutdown(info); | 3115 | shutdown(info); |
3156 | 3116 | ||
3157 | tty->closing = 0; | 3117 | tty_port_close_end(&info->port, tty); |
3158 | info->port.tty = NULL; | 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 | cleanup: | 3119 | cleanup: |
3172 | if (debug_level >= DEBUG_LEVEL_INFO) | 3120 | if (debug_level >= DEBUG_LEVEL_INFO) |
3173 | printk("%s(%d):mgsl_close(%s) exit, count=%d\n", __FILE__,__LINE__, | 3121 | printk("%s(%d):mgsl_close(%s) exit, count=%d\n", __FILE__,__LINE__, |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 625c9bde3be..53544e21f19 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -720,44 +720,9 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
720 | return; | 720 | return; |
721 | DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count)); | 721 | DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count)); |
722 | 722 | ||
723 | if (!info->port.count) | 723 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
724 | return; | ||
725 | |||
726 | if (tty_hung_up_p(filp)) | ||
727 | goto cleanup; | 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 | if (info->port.flags & ASYNC_INITIALIZED) | 726 | if (info->port.flags & ASYNC_INITIALIZED) |
762 | wait_until_sent(tty, info->timeout); | 727 | wait_until_sent(tty, info->timeout); |
763 | flush_buffer(tty); | 728 | flush_buffer(tty); |
@@ -765,20 +730,8 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
765 | 730 | ||
766 | shutdown(info); | 731 | shutdown(info); |
767 | 732 | ||
768 | tty->closing = 0; | 733 | tty_port_close_end(&info->port, tty); |
769 | info->port.tty = NULL; | 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 | cleanup: | 735 | cleanup: |
783 | DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count)); | 736 | DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count)); |
784 | } | 737 | } |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 1f5c21ec4b1..2aac55bcf5f 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -810,70 +810,18 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
810 | printk("%s(%d):%s close() entry, count=%d\n", | 810 | printk("%s(%d):%s close() entry, count=%d\n", |
811 | __FILE__,__LINE__, info->device_name, info->port.count); | 811 | __FILE__,__LINE__, info->device_name, info->port.count); |
812 | 812 | ||
813 | if (!info->port.count) | 813 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
814 | return; | ||
815 | |||
816 | if (tty_hung_up_p(filp)) | ||
817 | 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; | 814 | goto cleanup; |
836 | 815 | ||
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 | |||
854 | if (info->port.flags & ASYNC_INITIALIZED) | 816 | if (info->port.flags & ASYNC_INITIALIZED) |
855 | wait_until_sent(tty, info->timeout); | 817 | wait_until_sent(tty, info->timeout); |
856 | 818 | ||
857 | flush_buffer(tty); | 819 | flush_buffer(tty); |
858 | |||
859 | tty_ldisc_flush(tty); | 820 | tty_ldisc_flush(tty); |
860 | |||
861 | shutdown(info); | 821 | shutdown(info); |
862 | 822 | ||
863 | tty->closing = 0; | 823 | tty_port_close_end(&info->port, tty); |
864 | info->port.tty = NULL; | 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 | cleanup: | 825 | cleanup: |
878 | if (debug_level >= DEBUG_LEVEL_INFO) | 826 | if (debug_level >= DEBUG_LEVEL_INFO) |
879 | printk("%s(%d):%s close() exit, count=%d\n", __FILE__,__LINE__, | 827 | printk("%s(%d):%s close() exit, count=%d\n", __FILE__,__LINE__, |
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index 0723664fe0a..b3175f54fe0 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c | |||
@@ -257,3 +257,61 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
257 | } | 257 | } |
258 | EXPORT_SYMBOL(tty_port_block_til_ready); | 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); | ||