diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-13 19:02:05 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-13 19:02:05 +0100 |
commit | 67ad058d97b8cff441211b791d97e5f776b81210 (patch) | |
tree | 4ee85611b11fe91a8a8eb1f7561484e7abb2f85a /drivers/tty/tty_ldisc.c | |
parent | Merge tag 'usb-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/greg... (diff) | |
parent | drivers/tty/serial: delete unused MODULE_DEVICE_TABLE from atmel_serial.c (diff) | |
download | linux-67ad058d97b8cff441211b791d97e5f776b81210.tar.xz linux-67ad058d97b8cff441211b791d97e5f776b81210.zip |
Merge tag 'tty-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial updates from Greg KH:
"Here is the big serial/tty driver update for 4.5-rc1.
Lots of driver updates and some tty core changes. All of these have
been in linux-next and the details are in the shortlog"
* tag 'tty-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (127 commits)
drivers/tty/serial: delete unused MODULE_DEVICE_TABLE from atmel_serial.c
serial: sh-sci: Remove cpufreq notifier to fix crash/deadlock
serial: 8250: of: Fix the driver and actually compile the 8250_of
tty: amba-pl011: use iotype instead of access_32b to track 32-bit I/O
tty: amba-pl011: fix earlycon register offsets
serial: sh-sci: Drop the sci_fck clock fallback
sh: sh7734: Correct SCIF type for BRG
sh: Remove sci_ick clock alias
sh: Rename sci_ick and sci_fck clock to fck
serial: sh-sci: Add support for optional BRG on (H)SCIF
serial: sh-sci: Add support for optional external (H)SCK input
serial: sh-sci: Prepare for multiple sampling clock sources
serial: sh-sci: Correct SCIF type on R-Car for BRG
serial: sh-sci: Correct SCIF type on RZ/A1H
serial: sh-sci: Replace struct sci_port_info by type/regtype encoding
serial: sh-sci: Add BRG register definitions
serial: sh-sci: Take into account sampling rate for max baud rate
serial: sh-sci: Merge sci_scbrr_calc() and sci_baud_calc_hscif()
serial: sh-sci: Avoid calculating the receive margin for HSCIF
serial: sh-sci: Improve bit rate error calculation for HSCIF
...
Diffstat (limited to 'drivers/tty/tty_ldisc.c')
-rw-r--r-- | drivers/tty/tty_ldisc.c | 51 |
1 files changed, 21 insertions, 30 deletions
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 629e3c865072..a054d03c22e7 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -185,7 +185,7 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) * * Complement of tty_ldisc_get(). */ -static inline void tty_ldisc_put(struct tty_ldisc *ld) +static void tty_ldisc_put(struct tty_ldisc *ld) { if (WARN_ON_ONCE(!ld)) return; @@ -417,6 +417,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); * they are not on hot paths so a little discipline won't do * any harm. * + * The line discipline-related tty_struct fields are reset to + * prevent the ldisc driver from re-using stale information for + * the new ldisc instance. + * * Locking: takes termios_rwsem */ @@ -425,6 +429,9 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) down_write(&tty->termios_rwsem); tty->termios.c_line = num; up_write(&tty->termios_rwsem); + + tty->disc_data = NULL; + tty->receive_room = 0; } /** @@ -529,34 +536,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 +576,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; } |