Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[firefly-linux-kernel-4.4.55.git] / drivers / tty / tty_ldisc.c
index 5819667f5bdb02c38bcfe44dd1787c068a1d0a59..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,9 +540,6 @@ 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);
 
@@ -570,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);
 
        /*
@@ -603,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);
 }