diff options
| -rw-r--r-- | drivers/char/epca.c | 172 | ||||
| -rw-r--r-- | drivers/char/tty_port.c | 3 |
2 files changed, 26 insertions, 149 deletions
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 7a697055e4f6..71225d1af9ee 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
| @@ -432,58 +432,15 @@ static void pc_close(struct tty_struct *tty, struct file *filp) | |||
| 432 | return; | 432 | return; |
| 433 | port = &ch->port; | 433 | port = &ch->port; |
| 434 | 434 | ||
| 435 | spin_lock_irqsave(&port->lock, flags); | 435 | if (tty_port_close_start(port, tty, filp) == 0) |
| 436 | if (tty_hung_up_p(filp)) { | ||
| 437 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 438 | return; | ||
| 439 | } | ||
| 440 | if (port->count-- > 1) { | ||
| 441 | /* Begin channel is open more than once */ | ||
| 442 | /* | ||
| 443 | * Return without doing anything. Someone might still | ||
| 444 | * be using the channel. | ||
| 445 | */ | ||
| 446 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 447 | return; | 436 | return; |
| 448 | } | ||
| 449 | /* Port open only once go ahead with shutdown & reset */ | ||
| 450 | WARN_ON(port->count < 0); | ||
| 451 | 437 | ||
| 452 | /* | ||
| 453 | * Let the rest of the driver know the channel is being closed. | ||
| 454 | * This becomes important if an open is attempted before close | ||
| 455 | * is finished. | ||
| 456 | */ | ||
| 457 | port->flags |= ASYNC_CLOSING; | ||
| 458 | tty->closing = 1; | ||
| 459 | |||
| 460 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 461 | |||
| 462 | if (port->flags & ASYNC_INITIALIZED) { | ||
| 463 | /* Setup an event to indicate when the | ||
| 464 | transmit buffer empties */ | ||
| 465 | setup_empty_event(tty, ch); | ||
| 466 | /* 30 seconds timeout */ | ||
| 467 | tty_wait_until_sent(tty, 3000); | ||
| 468 | } | ||
| 469 | pc_flush_buffer(tty); | 438 | pc_flush_buffer(tty); |
| 470 | tty_ldisc_flush(tty); | ||
| 471 | shutdown(ch, tty); | 439 | shutdown(ch, tty); |
| 472 | 440 | ||
| 473 | spin_lock_irqsave(&port->lock, flags); | 441 | tty_port_close_end(port, tty); |
| 474 | tty->closing = 0; | 442 | ch->event = 0; /* FIXME: review ch->event locking */ |
| 475 | ch->event = 0; | ||
| 476 | tty_port_tty_set(port, NULL); | 443 | tty_port_tty_set(port, NULL); |
| 477 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 478 | |||
| 479 | if (port->blocked_open) { | ||
| 480 | if (ch->close_delay) | ||
| 481 | msleep_interruptible(jiffies_to_msecs(ch->close_delay)); | ||
| 482 | wake_up_interruptible(&port->open_wait); | ||
| 483 | } | ||
| 484 | port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED | | ||
| 485 | ASYNC_CLOSING); | ||
| 486 | wake_up_interruptible(&port->close_wait); | ||
| 487 | } | 444 | } |
| 488 | 445 | ||
| 489 | static void shutdown(struct channel *ch, struct tty_struct *tty) | 446 | static void shutdown(struct channel *ch, struct tty_struct *tty) |
| @@ -527,7 +484,6 @@ static void shutdown(struct channel *ch, struct tty_struct *tty) | |||
| 527 | static void pc_hangup(struct tty_struct *tty) | 484 | static void pc_hangup(struct tty_struct *tty) |
| 528 | { | 485 | { |
| 529 | struct channel *ch; | 486 | struct channel *ch; |
| 530 | struct tty_port *port; | ||
| 531 | 487 | ||
| 532 | /* | 488 | /* |
| 533 | * verifyChannel returns the channel from the tty struct if it is | 489 | * verifyChannel returns the channel from the tty struct if it is |
| @@ -536,19 +492,13 @@ static void pc_hangup(struct tty_struct *tty) | |||
| 536 | ch = verifyChannel(tty); | 492 | ch = verifyChannel(tty); |
| 537 | if (ch != NULL) { | 493 | if (ch != NULL) { |
| 538 | unsigned long flags; | 494 | unsigned long flags; |
| 539 | port = &ch->port; | ||
| 540 | 495 | ||
| 541 | pc_flush_buffer(tty); | 496 | pc_flush_buffer(tty); |
| 542 | tty_ldisc_flush(tty); | 497 | tty_ldisc_flush(tty); |
| 543 | shutdown(ch, tty); | 498 | shutdown(ch, tty); |
| 544 | 499 | ||
| 545 | spin_lock_irqsave(&port->lock, flags); | ||
| 546 | port->tty = NULL; | ||
| 547 | ch->event = 0; /* FIXME: review locking of ch->event */ | 500 | ch->event = 0; /* FIXME: review locking of ch->event */ |
| 548 | port->count = 0; | 501 | tty_port_hangup(&ch->port); |
| 549 | port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED); | ||
| 550 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 551 | wake_up_interruptible(&port->open_wait); | ||
| 552 | } | 502 | } |
| 553 | } | 503 | } |
| 554 | 504 | ||
| @@ -792,98 +742,18 @@ static void pc_flush_chars(struct tty_struct *tty) | |||
| 792 | } | 742 | } |
| 793 | } | 743 | } |
| 794 | 744 | ||
| 795 | static int block_til_ready(struct tty_struct *tty, | 745 | static int epca_carrier_raised(struct tty_port *port) |
| 796 | struct file *filp, struct channel *ch) | ||
| 797 | { | 746 | { |
| 798 | DECLARE_WAITQUEUE(wait, current); | 747 | struct channel *ch = container_of(port, struct channel, port); |
| 799 | int retval, do_clocal = 0; | 748 | if (ch->imodem & ch->dcd) |
| 800 | unsigned long flags; | 749 | return 1; |
| 801 | struct tty_port *port = &ch->port; | ||
| 802 | |||
| 803 | if (tty_hung_up_p(filp)) { | ||
| 804 | if (port->flags & ASYNC_HUP_NOTIFY) | ||
| 805 | retval = -EAGAIN; | ||
| 806 | else | ||
| 807 | retval = -ERESTARTSYS; | ||
| 808 | return retval; | ||
| 809 | } | ||
| 810 | |||
| 811 | /* | ||
| 812 | * If the device is in the middle of being closed, then block until | ||
| 813 | * it's done, and then try again. | ||
| 814 | */ | ||
| 815 | if (port->flags & ASYNC_CLOSING) { | ||
| 816 | interruptible_sleep_on(&port->close_wait); | ||
| 817 | |||
| 818 | if (port->flags & ASYNC_HUP_NOTIFY) | ||
| 819 | return -EAGAIN; | ||
| 820 | else | ||
| 821 | return -ERESTARTSYS; | ||
| 822 | } | ||
| 823 | |||
| 824 | if (filp->f_flags & O_NONBLOCK) { | ||
| 825 | /* | ||
| 826 | * If non-blocking mode is set, then make the check up front | ||
| 827 | * and then exit. | ||
| 828 | */ | ||
| 829 | port->flags |= ASYNC_NORMAL_ACTIVE; | ||
| 830 | return 0; | ||
| 831 | } | ||
| 832 | if (tty->termios->c_cflag & CLOCAL) | ||
| 833 | do_clocal = 1; | ||
| 834 | /* Block waiting for the carrier detect and the line to become free */ | ||
| 835 | |||
| 836 | retval = 0; | ||
| 837 | add_wait_queue(&port->open_wait, &wait); | ||
| 838 | |||
| 839 | spin_lock_irqsave(&port->lock, flags); | ||
| 840 | /* We dec count so that pc_close will know when to free things */ | ||
| 841 | if (!tty_hung_up_p(filp)) | ||
| 842 | port->count--; | ||
| 843 | port->blocked_open++; | ||
| 844 | while (1) { | ||
| 845 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 846 | if (tty_hung_up_p(filp) || | ||
| 847 | !(port->flags & ASYNC_INITIALIZED)) { | ||
| 848 | if (port->flags & ASYNC_HUP_NOTIFY) | ||
| 849 | retval = -EAGAIN; | ||
| 850 | else | ||
| 851 | retval = -ERESTARTSYS; | ||
| 852 | break; | ||
| 853 | } | ||
| 854 | if (!(port->flags & ASYNC_CLOSING) && | ||
| 855 | (do_clocal || (ch->imodem & ch->dcd))) | ||
| 856 | break; | ||
| 857 | if (signal_pending(current)) { | ||
| 858 | retval = -ERESTARTSYS; | ||
| 859 | break; | ||
| 860 | } | ||
| 861 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 862 | /* | ||
| 863 | * Allow someone else to be scheduled. We will occasionally go | ||
| 864 | * through this loop until one of the above conditions change. | ||
| 865 | * The below schedule call will allow other processes to enter | ||
| 866 | * and prevent this loop from hogging the cpu. | ||
| 867 | */ | ||
| 868 | schedule(); | ||
| 869 | spin_lock_irqsave(&port->lock, flags); | ||
| 870 | } | ||
| 871 | |||
| 872 | __set_current_state(TASK_RUNNING); | ||
| 873 | remove_wait_queue(&port->open_wait, &wait); | ||
| 874 | if (!tty_hung_up_p(filp)) | ||
| 875 | port->count++; | ||
| 876 | port->blocked_open--; | ||
| 877 | |||
| 878 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 879 | |||
| 880 | if (retval) | ||
| 881 | return retval; | ||
| 882 | |||
| 883 | port->flags |= ASYNC_NORMAL_ACTIVE; | ||
| 884 | return 0; | 750 | return 0; |
| 885 | } | 751 | } |
| 886 | 752 | ||
| 753 | static void epca_raise_dtr_rts(struct tty_port *port0 | ||
| 754 | { | ||
| 755 | } | ||
| 756 | |||
| 887 | static int pc_open(struct tty_struct *tty, struct file *filp) | 757 | static int pc_open(struct tty_struct *tty, struct file *filp) |
| 888 | { | 758 | { |
| 889 | struct channel *ch; | 759 | struct channel *ch; |
| @@ -978,7 +848,7 @@ static int pc_open(struct tty_struct *tty, struct file *filp) | |||
| 978 | port->flags |= ASYNC_INITIALIZED; | 848 | port->flags |= ASYNC_INITIALIZED; |
| 979 | spin_unlock_irqrestore(&port->lock, flags); | 849 | spin_unlock_irqrestore(&port->lock, flags); |
| 980 | 850 | ||
| 981 | retval = block_til_ready(tty, filp, ch); | 851 | retval = tty_port_block_til_ready(port, tty, filp); |
| 982 | if (retval) | 852 | if (retval) |
| 983 | return retval; | 853 | return retval; |
| 984 | /* | 854 | /* |
| @@ -1058,6 +928,11 @@ static const struct tty_operations pc_ops = { | |||
| 1058 | .break_ctl = pc_send_break | 928 | .break_ctl = pc_send_break |
| 1059 | }; | 929 | }; |
| 1060 | 930 | ||
| 931 | static const struct tty_port_operations epca_port_ops = { | ||
| 932 | .carrier_raised = epca_carrier_raised, | ||
| 933 | .raise_dtr_rts = epca_raise_dtr_rts, | ||
| 934 | }; | ||
| 935 | |||
| 1061 | static int info_open(struct tty_struct *tty, struct file *filp) | 936 | static int info_open(struct tty_struct *tty, struct file *filp) |
| 1062 | { | 937 | { |
| 1063 | return 0; | 938 | return 0; |
| @@ -1393,6 +1268,7 @@ static void post_fep_init(unsigned int crd) | |||
| 1393 | u16 tseg, rseg; | 1268 | u16 tseg, rseg; |
| 1394 | 1269 | ||
| 1395 | tty_port_init(&ch->port); | 1270 | tty_port_init(&ch->port); |
| 1271 | ch->port.ops - &epca_port_ops; | ||
| 1396 | ch->brdchan = bc; | 1272 | ch->brdchan = bc; |
| 1397 | ch->mailbox = gd; | 1273 | ch->mailbox = gd; |
| 1398 | INIT_WORK(&ch->tqueue, do_softint); | 1274 | INIT_WORK(&ch->tqueue, do_softint); |
| @@ -1526,7 +1402,7 @@ static void post_fep_init(unsigned int crd) | |||
| 1526 | ch->fepstartca = 0; | 1402 | ch->fepstartca = 0; |
| 1527 | ch->fepstopca = 0; | 1403 | ch->fepstopca = 0; |
| 1528 | 1404 | ||
| 1529 | ch->close_delay = 50; | 1405 | ch->port.close_delay = 50; |
| 1530 | 1406 | ||
| 1531 | spin_unlock_irqrestore(&epca_lock, flags); | 1407 | spin_unlock_irqrestore(&epca_lock, flags); |
| 1532 | } | 1408 | } |
| @@ -1647,7 +1523,7 @@ static void doevent(int crd) | |||
| 1647 | if (event & MODEMCHG_IND) { | 1523 | if (event & MODEMCHG_IND) { |
| 1648 | /* A modem signal change has been indicated */ | 1524 | /* A modem signal change has been indicated */ |
| 1649 | ch->imodem = mstat; | 1525 | ch->imodem = mstat; |
| 1650 | if (ch->port.flags & ASYNC_CHECK_CD) { | 1526 | if (test_bit(ASYNC_CHECK_CD, &ch->port.flags)) { |
| 1651 | /* We are now receiving dcd */ | 1527 | /* We are now receiving dcd */ |
| 1652 | if (mstat & ch->dcd) | 1528 | if (mstat & ch->dcd) |
| 1653 | wake_up_interruptible(&ch->port.open_wait); | 1529 | wake_up_interruptible(&ch->port.open_wait); |
| @@ -1894,9 +1770,9 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) | |||
| 1894 | * that the driver will wait on carrier detect. | 1770 | * that the driver will wait on carrier detect. |
| 1895 | */ | 1771 | */ |
| 1896 | if (ts->c_cflag & CLOCAL) | 1772 | if (ts->c_cflag & CLOCAL) |
| 1897 | ch->port.flags &= ~ASYNC_CHECK_CD; | 1773 | clear_bit(ASYNC_CHECK_CD, &ch->port.flags); |
| 1898 | else | 1774 | else |
| 1899 | ch->port.flags |= ASYNC_CHECK_CD; | 1775 | set_bit(ASYNC_CHECK_CD, &ch->port.flags); |
| 1900 | mval = ch->m_dtr | ch->m_rts; | 1776 | mval = ch->m_dtr | ch->m_rts; |
| 1901 | } /* End CBAUD not detected */ | 1777 | } /* End CBAUD not detected */ |
| 1902 | iflag = termios2digi_i(ch, ts->c_iflag); | 1778 | iflag = termios2digi_i(ch, ts->c_iflag); |
| @@ -2373,7 +2249,7 @@ static void do_softint(struct work_struct *work) | |||
| 2373 | if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { | 2249 | if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { |
| 2374 | tty_hangup(tty); | 2250 | tty_hangup(tty); |
| 2375 | wake_up_interruptible(&ch->port.open_wait); | 2251 | wake_up_interruptible(&ch->port.open_wait); |
| 2376 | ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 2252 | clear_bit(ASYNC_NORMAL_ACTIVE, &ch->port.flags); |
| 2377 | } | 2253 | } |
| 2378 | } | 2254 | } |
| 2379 | tty_kref_put(tty); | 2255 | tty_kref_put(tty); |
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index b3175f54fe05..b580fcf629f8 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c | |||
| @@ -286,7 +286,8 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f | |||
| 286 | port->flags |= ASYNC_CLOSING; | 286 | port->flags |= ASYNC_CLOSING; |
| 287 | tty->closing = 1; | 287 | tty->closing = 1; |
| 288 | spin_unlock_irqrestore(&port->lock, flags); | 288 | spin_unlock_irqrestore(&port->lock, flags); |
| 289 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 289 | if (port->flags & ASYNC_INITIALIZED && |
| 290 | port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
| 290 | tty_wait_until_sent(tty, port->closing_wait); | 291 | tty_wait_until_sent(tty, port->closing_wait); |
| 291 | return 1; | 292 | return 1; |
| 292 | } | 293 | } |
