static DEFINE_SPINLOCK(tty_ldisc_lock);
 static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
+static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_idle);
 /* Line disc dispatch table */
 static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
 
                return;
        }
        local_irq_restore(flags);
+       wake_up(&tty_ldisc_idle);
 }
 
 /**
        return cancel_delayed_work_sync(&tty->buf.work);
 }
 
+/**
+ *     tty_ldisc_wait_idle     -       wait for the ldisc to become idle
+ *     @tty: tty to wait for
+ *
+ *     Wait for the line discipline to become idle. The discipline must
+ *     have been halted for this to guarantee it remains idle.
+ */
+static int tty_ldisc_wait_idle(struct tty_struct *tty)
+{
+       int ret;
+       ret = wait_event_interruptible_timeout(tty_ldisc_idle,
+                       atomic_read(&tty->ldisc->users) == 1, 5 * HZ);
+       if (ret < 0)
+               return ret;
+       return ret > 0 ? 0 : -EBUSY;
+}
+
 /**
  *     tty_set_ldisc           -       set line discipline
  *     @tty: the terminal to set
 
        flush_scheduled_work();
 
+       retval = tty_ldisc_wait_idle(tty);
+
        tty_lock();
        mutex_lock(&tty->ldisc_mutex);
+
+       /* handle wait idle failure locked */
+       if (retval) {
+               tty_ldisc_put(new_ldisc);
+               goto enable;
+       }
+
        if (test_bit(TTY_HUPPED, &tty->flags)) {
                /* We were raced by the hangup method. It will have stomped
                   the ldisc data and closed the ldisc down */
 
        tty_ldisc_put(o_ldisc);
 
+enable:
        /*
         *      Allow ldisc referencing to occur again
         */