Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[firefly-linux-kernel-4.4.55.git] / drivers / tty / tty_ldisc.c
index 1dbe27824220266e1dd23b71bab7f6edadae32d1..3737f55272d2c1184463edc3714f89fb2724730e 100644 (file)
@@ -393,33 +393,21 @@ static void __lockfunc tty_ldisc_unlock_pair(struct tty_struct *tty,
                __tty_ldisc_unlock(tty2);
 }
 
-static void __lockfunc tty_ldisc_enable_pair(struct tty_struct *tty,
-                                            struct tty_struct *tty2)
-{
-       clear_bit(TTY_LDISC_HALTED, &tty->flags);
-       if (tty2)
-               clear_bit(TTY_LDISC_HALTED, &tty2->flags);
-
-       tty_ldisc_unlock_pair(tty, tty2);
-}
-
 /**
  *     tty_ldisc_flush -       flush line discipline queue
  *     @tty: tty
  *
- *     Flush the line discipline queue (if any) for this tty. If there
- *     is no line discipline active this is a no-op.
+ *     Flush the line discipline queue (if any) and the tty flip buffers
+ *     for this tty.
  */
 
 void tty_ldisc_flush(struct tty_struct *tty)
 {
        struct tty_ldisc *ld = tty_ldisc_ref(tty);
-       if (ld) {
-               if (ld->ops->flush_buffer)
-                       ld->ops->flush_buffer(tty);
+
+       tty_buffer_flush(tty, ld);
+       if (ld)
                tty_ldisc_deref(ld);
-       }
-       tty_buffer_flush(tty);
 }
 EXPORT_SYMBOL_GPL(tty_ldisc_flush);
 
@@ -535,14 +523,13 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 {
        int retval;
        struct tty_ldisc *old_ldisc, *new_ldisc;
-       struct tty_struct *o_tty = tty->link;
 
        new_ldisc = tty_ldisc_get(tty, ldisc);
        if (IS_ERR(new_ldisc))
                return PTR_ERR(new_ldisc);
 
        tty_lock(tty);
-       retval = tty_ldisc_lock_pair_timeout(tty, o_tty, 5 * HZ);
+       retval = tty_ldisc_lock(tty, 5 * HZ);
        if (retval) {
                tty_ldisc_put(new_ldisc);
                tty_unlock(tty);
@@ -554,7 +541,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
         */
 
        if (tty->ldisc->ops->num == ldisc) {
-               tty_ldisc_enable_pair(tty, o_tty);
+               tty_ldisc_unlock(tty);
                tty_ldisc_put(new_ldisc);
                tty_unlock(tty);
                return 0;
@@ -565,7 +552,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
        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_enable_pair(tty, o_tty);
+               tty_ldisc_unlock(tty);
                tty_ldisc_put(new_ldisc);
                tty_unlock(tty);
                return -EIO;
@@ -585,8 +572,11 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
                tty_ldisc_restore(tty, old_ldisc);
        }
 
-       if (tty->ldisc->ops->num != old_ldisc->ops->num && tty->ops->set_ldisc)
+       if (tty->ldisc->ops->num != old_ldisc->ops->num && tty->ops->set_ldisc) {
+               down_read(&tty->termios_rwsem);
                tty->ops->set_ldisc(tty);
+               up_read(&tty->termios_rwsem);
+       }
 
        /* At this point we hold a reference to the new ldisc and a
           reference to the old ldisc, or we hold two references to
@@ -599,13 +589,11 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
        /*
         *      Allow ldisc referencing to occur again
         */
-       tty_ldisc_enable_pair(tty, o_tty);
+       tty_ldisc_unlock(tty);
 
        /* Restart the work queue in case no characters kick it off. Safe if
           already running */
        schedule_work(&tty->port->buf.work);
-       if (o_tty)
-               schedule_work(&o_tty->port->buf.work);
 
        tty_unlock(tty);
        return retval;