From 759c25cd0806f6487b5d66057c32280e37bce0e4 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Mon, 11 Mar 2013 16:44:29 -0400 Subject: [PATCH] --- yaml --- r: 364257 b: refs/heads/master c: f4cf7a384587c16c59565dd6930dd763f243dba4 h: refs/heads/master i: 364255: 86fe476a520aefc94cd988846f2a4dd92c539298 v: v3 --- [refs] | 2 +- trunk/drivers/tty/tty_ldisc.c | 38 +++++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/[refs] b/[refs] index 1fd7440066fe..7c15b212977a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: cf5284765862ac65e4a3e5b34652e593ffda2bdf +refs/heads/master: f4cf7a384587c16c59565dd6930dd763f243dba4 diff --git a/trunk/drivers/tty/tty_ldisc.c b/trunk/drivers/tty/tty_ldisc.c index 525ee535c10d..77120911e016 100644 --- a/trunk/drivers/tty/tty_ldisc.c +++ b/trunk/drivers/tty/tty_ldisc.c @@ -530,14 +530,17 @@ static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) /** * tty_ldisc_halt - shut down the line discipline * @tty: tty device + * @o_tty: paired pty device (can be NULL) * @pending: returns true if work was scheduled when cancelled * (can be set to NULL) + * @o_pending: returns true if work was scheduled when cancelled + * (can be set to NULL) * @timeout: # of jiffies to wait for ldisc refs to be released * - * Shut down the line discipline and work queue for this tty device. - * The TTY_LDISC flag being cleared ensures no further references can - * be obtained while the delayed work queue halt ensures that no more - * data is fed to the ldisc. + * Shut down the line discipline and work queue for this tty device and + * its paired pty (if exists). Clearing the TTY_LDISC flag ensures + * no further references can be obtained while the work queue halt + * ensures that no more data is fed to the ldisc. * * Furthermore, guarantee that existing ldisc references have been * released, which in turn, guarantees that no future buffer work @@ -548,19 +551,32 @@ static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) * flushed. */ -static int tty_ldisc_halt(struct tty_struct *tty, int *pending, long timeout) +static int tty_ldisc_halt(struct tty_struct *tty, struct tty_struct *o_tty, + int *pending, int *o_pending, long timeout) { - int scheduled, retval; + int scheduled, o_scheduled, retval; clear_bit(TTY_LDISC, &tty->flags); + if (o_tty) + clear_bit(TTY_LDISC, &o_tty->flags); + retval = tty_ldisc_wait_idle(tty, timeout); + if (!retval && o_tty) + retval = tty_ldisc_wait_idle(o_tty, timeout); if (retval) return retval; scheduled = cancel_work_sync(&tty->port->buf.work); set_bit(TTY_LDISC_HALTED, &tty->flags); + if (o_tty) { + o_scheduled = cancel_work_sync(&o_tty->port->buf.work); + set_bit(TTY_LDISC_HALTED, &o_tty->flags); + } + if (pending) *pending = scheduled; + if (o_tty && o_pending) + *o_pending = o_scheduled; return 0; } @@ -702,9 +718,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) * parallel to the change and re-referencing the tty. */ - retval = tty_ldisc_halt(tty, &work, 5 * HZ); - if (!retval && o_tty) - retval = tty_ldisc_halt(o_tty, &o_work, 5 * HZ); + retval = tty_ldisc_halt(tty, o_tty, &work, &o_work, 5 * HZ); /* * Wait for ->hangup_work and ->buf.work handlers to terminate. @@ -965,12 +979,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) * race with the set_ldisc code path. */ - tty_ldisc_halt(tty, NULL, MAX_SCHEDULE_TIMEOUT); + tty_ldisc_halt(tty, o_tty, NULL, NULL, MAX_SCHEDULE_TIMEOUT); tty_ldisc_flush_works(tty); - if (o_tty) { - tty_ldisc_halt(o_tty, NULL, MAX_SCHEDULE_TIMEOUT); + if (o_tty) tty_ldisc_flush_works(o_tty); - } tty_lock_pair(tty, o_tty); /* This will need doing differently if we need to lock */