|
@@ -529,34 +529,21 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
|
|
|
|
|
|
tty_lock(tty);
|
|
|
retval = tty_ldisc_lock(tty, 5 * HZ);
|
|
|
- if (retval) {
|
|
|
- tty_ldisc_put(new_ldisc);
|
|
|
- tty_unlock(tty);
|
|
|
- return retval;
|
|
|
- }
|
|
|
+ if (retval)
|
|
|
+ goto err;
|
|
|
|
|
|
- /*
|
|
|
- * Check the no-op case
|
|
|
- */
|
|
|
+ /* Check the no-op case */
|
|
|
+ if (tty->ldisc->ops->num == ldisc)
|
|
|
+ goto out;
|
|
|
|
|
|
- if (tty->ldisc->ops->num == ldisc) {
|
|
|
- tty_ldisc_unlock(tty);
|
|
|
- tty_ldisc_put(new_ldisc);
|
|
|
- tty_unlock(tty);
|
|
|
- return 0;
|
|
|
+ if (test_bit(TTY_HUPPED, &tty->flags)) {
|
|
|
+ /* We were raced by hangup */
|
|
|
+ retval = -EIO;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
old_ldisc = tty->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_unlock(tty);
|
|
|
- tty_ldisc_put(new_ldisc);
|
|
|
- tty_unlock(tty);
|
|
|
- return -EIO;
|
|
|
- }
|
|
|
-
|
|
|
/* Shutdown the old discipline. */
|
|
|
tty_ldisc_close(tty, old_ldisc);
|
|
|
|
|
@@ -582,18 +569,15 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
|
|
|
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);
|
|
|
-
|
|
|
- /*
|
|
|
- * Allow ldisc referencing to occur again
|
|
|
- */
|
|
|
+ new_ldisc = old_ldisc;
|
|
|
+out:
|
|
|
tty_ldisc_unlock(tty);
|
|
|
|
|
|
/* Restart the work queue in case no characters kick it off. Safe if
|
|
|
already running */
|
|
|
tty_buffer_restart_work(tty->port);
|
|
|
-
|
|
|
+err:
|
|
|
+ tty_ldisc_put(new_ldisc); /* drop the extra reference */
|
|
|
tty_unlock(tty);
|
|
|
return retval;
|
|
|
}
|