diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-11-26 23:07:25 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-11-26 23:07:25 -0500 |
commit | dd7c7c3f69291baa488b8a50db683d5fbf44166a (patch) | |
tree | 925bf294f30dffaa67a983c3859926ff53937e14 /drivers/tty/tty_ldisc.c | |
parent | 161e773cbd0c3d1b5b8cc00602e1f72de61ed4f7 (diff) | |
parent | caca6a03d365883564885f2c1da3e88dcf65d139 (diff) |
Merge 3.2-rc3 into tty-next to handle merge conflict in tty_ldisc.c
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/tty/tty_ldisc.c')
-rw-r--r-- | drivers/tty/tty_ldisc.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 174db3b0c09e..24b95db75d84 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/bitops.h> | 18 | #include <linux/bitops.h> |
19 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
20 | #include <linux/uaccess.h> | 20 | #include <linux/uaccess.h> |
21 | #include <linux/ratelimit.h> | ||
21 | 22 | ||
22 | /* | 23 | /* |
23 | * This guards the refcounted line discipline lists. The lock | 24 | * This guards the refcounted line discipline lists. The lock |
@@ -529,15 +530,16 @@ static void tty_ldisc_flush_works(struct tty_struct *tty) | |||
529 | /** | 530 | /** |
530 | * tty_ldisc_wait_idle - wait for the ldisc to become idle | 531 | * tty_ldisc_wait_idle - wait for the ldisc to become idle |
531 | * @tty: tty to wait for | 532 | * @tty: tty to wait for |
533 | * @timeout: for how long to wait at most | ||
532 | * | 534 | * |
533 | * Wait for the line discipline to become idle. The discipline must | 535 | * Wait for the line discipline to become idle. The discipline must |
534 | * have been halted for this to guarantee it remains idle. | 536 | * have been halted for this to guarantee it remains idle. |
535 | */ | 537 | */ |
536 | static int tty_ldisc_wait_idle(struct tty_struct *tty) | 538 | static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) |
537 | { | 539 | { |
538 | int ret; | 540 | long ret; |
539 | ret = wait_event_timeout(tty_ldisc_idle, | 541 | ret = wait_event_timeout(tty_ldisc_idle, |
540 | atomic_read(&tty->ldisc->users) == 1, 5 * HZ); | 542 | atomic_read(&tty->ldisc->users) == 1, timeout); |
541 | return ret > 0 ? 0 : -EBUSY; | 543 | return ret > 0 ? 0 : -EBUSY; |
542 | } | 544 | } |
543 | 545 | ||
@@ -645,7 +647,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
645 | 647 | ||
646 | tty_ldisc_flush_works(tty); | 648 | tty_ldisc_flush_works(tty); |
647 | 649 | ||
648 | retval = tty_ldisc_wait_idle(tty); | 650 | retval = tty_ldisc_wait_idle(tty, 5 * HZ); |
649 | 651 | ||
650 | tty_lock(); | 652 | tty_lock(); |
651 | mutex_lock(&tty->ldisc_mutex); | 653 | mutex_lock(&tty->ldisc_mutex); |
@@ -742,8 +744,6 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) | |||
742 | if (IS_ERR(ld)) | 744 | if (IS_ERR(ld)) |
743 | return -1; | 745 | return -1; |
744 | 746 | ||
745 | WARN_ON_ONCE(tty_ldisc_wait_idle(tty)); | ||
746 | |||
747 | tty_ldisc_close(tty, tty->ldisc); | 747 | tty_ldisc_close(tty, tty->ldisc); |
748 | tty_ldisc_put(tty->ldisc); | 748 | tty_ldisc_put(tty->ldisc); |
749 | tty->ldisc = NULL; | 749 | tty->ldisc = NULL; |
@@ -818,7 +818,7 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
818 | tty_unlock(); | 818 | tty_unlock(); |
819 | cancel_work_sync(&tty->buf.work); | 819 | cancel_work_sync(&tty->buf.work); |
820 | mutex_unlock(&tty->ldisc_mutex); | 820 | mutex_unlock(&tty->ldisc_mutex); |
821 | 821 | retry: | |
822 | tty_lock(); | 822 | tty_lock(); |
823 | mutex_lock(&tty->ldisc_mutex); | 823 | mutex_lock(&tty->ldisc_mutex); |
824 | 824 | ||
@@ -827,6 +827,22 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
827 | it means auditing a lot of other paths so this is | 827 | it means auditing a lot of other paths so this is |
828 | a FIXME */ | 828 | a FIXME */ |
829 | if (tty->ldisc) { /* Not yet closed */ | 829 | if (tty->ldisc) { /* Not yet closed */ |
830 | if (atomic_read(&tty->ldisc->users) != 1) { | ||
831 | char cur_n[TASK_COMM_LEN], tty_n[64]; | ||
832 | long timeout = 3 * HZ; | ||
833 | tty_unlock(); | ||
834 | |||
835 | while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { | ||
836 | timeout = MAX_SCHEDULE_TIMEOUT; | ||
837 | printk_ratelimited(KERN_WARNING | ||
838 | "%s: waiting (%s) for %s took too long, but we keep waiting...\n", | ||
839 | __func__, get_task_comm(cur_n, current), | ||
840 | tty_name(tty, tty_n)); | ||
841 | } | ||
842 | mutex_unlock(&tty->ldisc_mutex); | ||
843 | goto retry; | ||
844 | } | ||
845 | |||
830 | if (reset == 0) { | 846 | if (reset == 0) { |
831 | 847 | ||
832 | if (!tty_ldisc_reinit(tty, tty->termios->c_line)) | 848 | if (!tty_ldisc_reinit(tty, tty->termios->c_line)) |