diff options
Diffstat (limited to 'drivers/tty/tty_ldisc.c')
-rw-r--r-- | drivers/tty/tty_ldisc.c | 37 |
1 files changed, 19 insertions, 18 deletions
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 24b95db75d8..173a9000a6c 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
@@ -28,7 +28,6 @@ | |||
28 | 28 | ||
29 | static DEFINE_SPINLOCK(tty_ldisc_lock); | 29 | static DEFINE_SPINLOCK(tty_ldisc_lock); |
30 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); | 30 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); |
31 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_idle); | ||
32 | /* Line disc dispatch table */ | 31 | /* Line disc dispatch table */ |
33 | static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; | 32 | static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; |
34 | 33 | ||
@@ -65,7 +64,7 @@ static void put_ldisc(struct tty_ldisc *ld) | |||
65 | return; | 64 | return; |
66 | } | 65 | } |
67 | local_irq_restore(flags); | 66 | local_irq_restore(flags); |
68 | wake_up(&tty_ldisc_idle); | 67 | wake_up(&ld->wq_idle); |
69 | } | 68 | } |
70 | 69 | ||
71 | /** | 70 | /** |
@@ -200,6 +199,8 @@ static struct tty_ldisc *tty_ldisc_get(int disc) | |||
200 | 199 | ||
201 | ld->ops = ldops; | 200 | ld->ops = ldops; |
202 | atomic_set(&ld->users, 1); | 201 | atomic_set(&ld->users, 1); |
202 | init_waitqueue_head(&ld->wq_idle); | ||
203 | |||
203 | return ld; | 204 | return ld; |
204 | } | 205 | } |
205 | 206 | ||
@@ -538,7 +539,7 @@ static void tty_ldisc_flush_works(struct tty_struct *tty) | |||
538 | static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) | 539 | static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) |
539 | { | 540 | { |
540 | long ret; | 541 | long ret; |
541 | ret = wait_event_timeout(tty_ldisc_idle, | 542 | ret = wait_event_timeout(tty->ldisc->wq_idle, |
542 | atomic_read(&tty->ldisc->users) == 1, timeout); | 543 | atomic_read(&tty->ldisc->users) == 1, timeout); |
543 | return ret > 0 ? 0 : -EBUSY; | 544 | return ret > 0 ? 0 : -EBUSY; |
544 | } | 545 | } |
@@ -567,7 +568,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
567 | if (IS_ERR(new_ldisc)) | 568 | if (IS_ERR(new_ldisc)) |
568 | return PTR_ERR(new_ldisc); | 569 | return PTR_ERR(new_ldisc); |
569 | 570 | ||
570 | tty_lock(); | 571 | tty_lock(tty); |
571 | /* | 572 | /* |
572 | * We need to look at the tty locking here for pty/tty pairs | 573 | * We need to look at the tty locking here for pty/tty pairs |
573 | * when both sides try to change in parallel. | 574 | * when both sides try to change in parallel. |
@@ -581,12 +582,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
581 | */ | 582 | */ |
582 | 583 | ||
583 | if (tty->ldisc->ops->num == ldisc) { | 584 | if (tty->ldisc->ops->num == ldisc) { |
584 | tty_unlock(); | 585 | tty_unlock(tty); |
585 | tty_ldisc_put(new_ldisc); | 586 | tty_ldisc_put(new_ldisc); |
586 | return 0; | 587 | return 0; |
587 | } | 588 | } |
588 | 589 | ||
589 | tty_unlock(); | 590 | tty_unlock(tty); |
590 | /* | 591 | /* |
591 | * Problem: What do we do if this blocks ? | 592 | * Problem: What do we do if this blocks ? |
592 | * We could deadlock here | 593 | * We could deadlock here |
@@ -594,7 +595,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
594 | 595 | ||
595 | tty_wait_until_sent(tty, 0); | 596 | tty_wait_until_sent(tty, 0); |
596 | 597 | ||
597 | tty_lock(); | 598 | tty_lock(tty); |
598 | mutex_lock(&tty->ldisc_mutex); | 599 | mutex_lock(&tty->ldisc_mutex); |
599 | 600 | ||
600 | /* | 601 | /* |
@@ -604,10 +605,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
604 | 605 | ||
605 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { | 606 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { |
606 | mutex_unlock(&tty->ldisc_mutex); | 607 | mutex_unlock(&tty->ldisc_mutex); |
607 | tty_unlock(); | 608 | tty_unlock(tty); |
608 | wait_event(tty_ldisc_wait, | 609 | wait_event(tty_ldisc_wait, |
609 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | 610 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); |
610 | tty_lock(); | 611 | tty_lock(tty); |
611 | mutex_lock(&tty->ldisc_mutex); | 612 | mutex_lock(&tty->ldisc_mutex); |
612 | } | 613 | } |
613 | 614 | ||
@@ -622,7 +623,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
622 | 623 | ||
623 | o_ldisc = tty->ldisc; | 624 | o_ldisc = tty->ldisc; |
624 | 625 | ||
625 | tty_unlock(); | 626 | tty_unlock(tty); |
626 | /* | 627 | /* |
627 | * Make sure we don't change while someone holds a | 628 | * Make sure we don't change while someone holds a |
628 | * reference to the line discipline. The TTY_LDISC bit | 629 | * reference to the line discipline. The TTY_LDISC bit |
@@ -649,7 +650,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
649 | 650 | ||
650 | retval = tty_ldisc_wait_idle(tty, 5 * HZ); | 651 | retval = tty_ldisc_wait_idle(tty, 5 * HZ); |
651 | 652 | ||
652 | tty_lock(); | 653 | tty_lock(tty); |
653 | mutex_lock(&tty->ldisc_mutex); | 654 | mutex_lock(&tty->ldisc_mutex); |
654 | 655 | ||
655 | /* handle wait idle failure locked */ | 656 | /* handle wait idle failure locked */ |
@@ -664,7 +665,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
664 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | 665 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); |
665 | mutex_unlock(&tty->ldisc_mutex); | 666 | mutex_unlock(&tty->ldisc_mutex); |
666 | tty_ldisc_put(new_ldisc); | 667 | tty_ldisc_put(new_ldisc); |
667 | tty_unlock(); | 668 | tty_unlock(tty); |
668 | return -EIO; | 669 | return -EIO; |
669 | } | 670 | } |
670 | 671 | ||
@@ -707,7 +708,7 @@ enable: | |||
707 | if (o_work) | 708 | if (o_work) |
708 | schedule_work(&o_tty->buf.work); | 709 | schedule_work(&o_tty->buf.work); |
709 | mutex_unlock(&tty->ldisc_mutex); | 710 | mutex_unlock(&tty->ldisc_mutex); |
710 | tty_unlock(); | 711 | tty_unlock(tty); |
711 | return retval; | 712 | return retval; |
712 | } | 713 | } |
713 | 714 | ||
@@ -815,11 +816,11 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
815 | * need to wait for another function taking the BTM | 816 | * need to wait for another function taking the BTM |
816 | */ | 817 | */ |
817 | clear_bit(TTY_LDISC, &tty->flags); | 818 | clear_bit(TTY_LDISC, &tty->flags); |
818 | tty_unlock(); | 819 | tty_unlock(tty); |
819 | cancel_work_sync(&tty->buf.work); | 820 | cancel_work_sync(&tty->buf.work); |
820 | mutex_unlock(&tty->ldisc_mutex); | 821 | mutex_unlock(&tty->ldisc_mutex); |
821 | retry: | 822 | retry: |
822 | tty_lock(); | 823 | tty_lock(tty); |
823 | mutex_lock(&tty->ldisc_mutex); | 824 | mutex_lock(&tty->ldisc_mutex); |
824 | 825 | ||
825 | /* At this point we have a closed ldisc and we want to | 826 | /* At this point we have a closed ldisc and we want to |
@@ -830,7 +831,7 @@ retry: | |||
830 | if (atomic_read(&tty->ldisc->users) != 1) { | 831 | if (atomic_read(&tty->ldisc->users) != 1) { |
831 | char cur_n[TASK_COMM_LEN], tty_n[64]; | 832 | char cur_n[TASK_COMM_LEN], tty_n[64]; |
832 | long timeout = 3 * HZ; | 833 | long timeout = 3 * HZ; |
833 | tty_unlock(); | 834 | tty_unlock(tty); |
834 | 835 | ||
835 | while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { | 836 | while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { |
836 | timeout = MAX_SCHEDULE_TIMEOUT; | 837 | timeout = MAX_SCHEDULE_TIMEOUT; |
@@ -911,10 +912,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
911 | * race with the set_ldisc code path. | 912 | * race with the set_ldisc code path. |
912 | */ | 913 | */ |
913 | 914 | ||
914 | tty_unlock(); | 915 | tty_unlock(tty); |
915 | tty_ldisc_halt(tty); | 916 | tty_ldisc_halt(tty); |
916 | tty_ldisc_flush_works(tty); | 917 | tty_ldisc_flush_works(tty); |
917 | tty_lock(); | 918 | tty_lock(tty); |
918 | 919 | ||
919 | mutex_lock(&tty->ldisc_mutex); | 920 | mutex_lock(&tty->ldisc_mutex); |
920 | /* | 921 | /* |