Merge tag 'xfs-for-linus-v3.12-rc1' of git://oss.sgi.com/xfs/xfs
[firefly-linux-kernel-4.4.55.git] / drivers / tty / tty_ldisc.c
index 31bd45a2d16b4338923870da8a2af81c808e174f..6458e11e8e9d656daef35b0a5aaddc21dcfd1804 100644 (file)
@@ -415,14 +415,14 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
  *     they are not on hot paths so a little discipline won't do
  *     any harm.
  *
- *     Locking: takes termios_mutex
+ *     Locking: takes termios_rwsem
  */
 
 static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
 {
-       mutex_lock(&tty->termios_mutex);
+       down_write(&tty->termios_rwsem);
        tty->termios.c_line = num;
-       mutex_unlock(&tty->termios_mutex);
+       up_write(&tty->termios_rwsem);
 }
 
 /**
@@ -540,16 +540,11 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
                return 0;
        }
 
-       /* FIXME: why 'shutoff' input if the ldisc is locked? */
-       tty->receive_room = 0;
-
        old_ldisc = tty->ldisc;
        tty_lock(tty);
 
-       /* FIXME: for testing only */
-       WARN_ON(test_bit(TTY_HUPPED, &tty->flags));
-
-       if (test_bit(TTY_HUPPING, &tty->flags)) {
+       if (test_bit(TTY_HUPPING, &tty->flags) ||
+           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);
@@ -572,13 +567,15 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
                tty_ldisc_restore(tty, old_ldisc);
        }
 
-       /* At this point we hold a reference to the new ldisc and a
-          a reference to the old ldisc. If we ended up flipping back
-          to the existing ldisc we have two references to it */
-
        if (tty->ldisc->ops->num != old_ldisc->ops->num && tty->ops->set_ldisc)
                tty->ops->set_ldisc(tty);
 
+       /* At this point we hold a reference to the new ldisc and a
+          reference to the old ldisc, or we hold two references to
+          the old ldisc (if it was restored as part of error cleanup
+          above). In either case, releasing a single reference from
+          the old ldisc is correct. */
+
        tty_ldisc_put(old_ldisc);
 
        /*
@@ -605,11 +602,11 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 
 static void tty_reset_termios(struct tty_struct *tty)
 {
-       mutex_lock(&tty->termios_mutex);
+       down_write(&tty->termios_rwsem);
        tty->termios = tty->driver->init_termios;
        tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios);
        tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios);
-       mutex_unlock(&tty->termios_mutex);
+       up_write(&tty->termios_rwsem);
 }