diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-15 11:37:02 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-15 11:37:02 -0800 |
commit | a9724125ad014decf008d782e60447c811391326 (patch) | |
tree | 4fac069d155f2495907fa9c296cc5426d0eebf55 /drivers/tty | |
parent | 46f7b635569731ff81a3b72d1bcd4415b293b637 (diff) | |
parent | c09babfab7ae8c7d79a5dce9d866fbb28b82dde4 (diff) |
Merge tag 'tty-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver patches from Greg KH:
"Here's the big tty/serial driver update for 3.20-rc1. Nothing huge
here, just lots of driver updates and some core tty layer fixes as
well. All have been in linux-next with no reported issues"
* tag 'tty-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (119 commits)
serial: 8250: Fix UART_BUG_TXEN workaround
serial: driver for ETRAX FS UART
tty: remove unused variable sprop
serial: of-serial: fetch line number from DT
serial: samsung: earlycon support depends on CONFIG_SERIAL_SAMSUNG_CONSOLE
tty/serial: serial8250_set_divisor() can be static
tty/serial: Add Spreadtrum sc9836-uart driver support
Documentation: DT: Add bindings for Spreadtrum SoC Platform
serial: samsung: remove redundant interrupt enabling
tty: Remove external interface for tty_set_termios()
serial: omap: Fix RTS handling
serial: 8250_omap: Use UPSTAT_AUTORTS for RTS handling
serial: core: Rework hw-assisted flow control support
tty/serial: 8250_early: Add support for PXA UARTs
tty/serial: of_serial: add support for PXA/MMP uarts
tty/serial: of_serial: add DT alias ID handling
serial: 8250: Prevent concurrent updates to shadow registers
serial: 8250: Use canary to restart console after suspend
serial: 8250: Refactor XR17V35X divisor calculation
serial: 8250: Refactor divisor programming
...
Diffstat (limited to 'drivers/tty')
43 files changed, 4176 insertions, 1605 deletions
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index d9f85f95eb2a..b2d760055952 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -931,7 +931,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch) struct serial_state *info = tty->driver_data; unsigned long flags; - if (serial_paranoia_check(info, tty->name, "rs_send_char")) + if (serial_paranoia_check(info, tty->name, "rs_send_xchar")) return; info->x_char = ch; diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c index 3c60923b0957..342b36b9ad35 100644 --- a/drivers/tty/ehv_bytechan.c +++ b/drivers/tty/ehv_bytechan.c @@ -112,7 +112,6 @@ static void disable_tx_interrupt(struct ehv_bc_data *bc) static int find_console_handle(void) { struct device_node *np = of_stdout; - const char *sprop = NULL; const uint32_t *iprop; /* We don't care what the aliased node is actually called. We only diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index 59ed783c4bcd..2054427992e0 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -1055,7 +1055,7 @@ static int isicom_send_break(struct tty_struct *tty, int length) outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base); outw((length & 0xff) << 8 | 0x00, base); - outw((length & 0xff00), base); + outw((length & 0xff00u), base); InterruptTheCard(base); unlock_card(card); diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 4ddfa60c9222..cf6e0f2e1331 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -90,6 +90,7 @@ struct n_tty_data { /* producer-published */ size_t read_head; + size_t commit_head; size_t canon_head; size_t echo_head; size_t echo_commit; @@ -161,36 +162,11 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x, return put_user(x, ptr); } -static int receive_room(struct tty_struct *tty) -{ - struct n_tty_data *ldata = tty->disc_data; - int left; - - if (I_PARMRK(tty)) { - /* Multiply read_cnt by 3, since each byte might take up to - * three times as many spaces when PARMRK is set (depending on - * its flags, e.g. parity error). */ - left = N_TTY_BUF_SIZE - read_cnt(ldata) * 3 - 1; - } else - left = N_TTY_BUF_SIZE - read_cnt(ldata) - 1; - - /* - * If we are doing input canonicalization, and there are no - * pending newlines, let characters through without limit, so - * that erase characters will be handled. Other excess - * characters will be beeped. - */ - if (left <= 0) - left = ldata->icanon && ldata->canon_head == ldata->read_tail; - - return left; -} - /** - * n_tty_set_room - receive space + * n_tty_kick_worker - start input worker (if required) * @tty: terminal * - * Re-schedules the flip buffer work if space just became available. + * Re-schedules the flip buffer work if it may have stopped * * Caller holds exclusive termios_rwsem * or @@ -198,12 +174,12 @@ static int receive_room(struct tty_struct *tty) * holds non-exclusive termios_rwsem */ -static void n_tty_set_room(struct tty_struct *tty) +static void n_tty_kick_worker(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - /* Did this open up the receive buffer? We may need to flip */ - if (unlikely(ldata->no_room) && receive_room(tty)) { + /* Did the input worker stop? Restart it */ + if (unlikely(ldata->no_room)) { ldata->no_room = 0; WARN_RATELIMIT(tty->port->itty == NULL, @@ -224,7 +200,7 @@ static ssize_t chars_in_buffer(struct tty_struct *tty) ssize_t n = 0; if (!ldata->icanon) - n = read_cnt(ldata); + n = ldata->commit_head - ldata->read_tail; else n = ldata->canon_head - ldata->read_tail; return n; @@ -247,17 +223,20 @@ static void n_tty_write_wakeup(struct tty_struct *tty) static void n_tty_check_throttle(struct tty_struct *tty) { - if (tty->driver->type == TTY_DRIVER_TYPE_PTY) - return; + struct n_tty_data *ldata = tty->disc_data; + /* * Check the remaining room for the input canonicalization * mode. We don't want to throttle the driver if we're in * canonical mode and don't have a newline yet! */ + if (ldata->icanon && ldata->canon_head == ldata->read_tail) + return; + while (1) { int throttled; tty_set_flow_change(tty, TTY_THROTTLE_SAFE); - if (receive_room(tty) >= TTY_THRESHOLD_THROTTLE) + if (N_TTY_BUF_SIZE - read_cnt(ldata) >= TTY_THRESHOLD_THROTTLE) break; throttled = tty_throttle_safe(tty); if (!throttled) @@ -274,7 +253,7 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) return; if (!tty->count) return; - n_tty_set_room(tty); + n_tty_kick_worker(tty); n_tty_write_wakeup(tty->link); if (waitqueue_active(&tty->link->write_wait)) wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT); @@ -296,7 +275,7 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) break; if (!tty->count) break; - n_tty_set_room(tty); + n_tty_kick_worker(tty); unthrottled = tty_unthrottle_safe(tty); if (!unthrottled) break; @@ -313,10 +292,6 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) * * n_tty_receive_buf()/producer path: * caller holds non-exclusive termios_rwsem - * modifies read_head - * - * read_head is only considered 'published' if canonical mode is - * not active. */ static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) @@ -340,6 +315,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata) { ldata->read_head = ldata->canon_head = ldata->read_tail = 0; ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0; + ldata->commit_head = 0; ldata->echo_mark = 0; ldata->line_start = 0; @@ -379,7 +355,7 @@ static void n_tty_flush_buffer(struct tty_struct *tty) { down_write(&tty->termios_rwsem); reset_buffer_flags(tty->disc_data); - n_tty_set_room(tty); + n_tty_kick_worker(tty); if (tty->link) n_tty_packet_mode_flush(tty); @@ -987,10 +963,6 @@ static inline void finish_erasing(struct n_tty_data *ldata) * * n_tty_receive_buf()/producer path: * caller holds non-exclusive termios_rwsem - * modifies read_head - * - * Modifying the read_head is not considered a publish in this context - * because canonical mode is active -- only canon_head publishes */ static void eraser(unsigned char c, struct tty_struct *tty) @@ -1118,16 +1090,45 @@ static void eraser(unsigned char c, struct tty_struct *tty) * Called when a signal is being sent due to terminal input. * Called from the driver receive_buf path so serialized. * + * Performs input and output flush if !NOFLSH. In this context, the echo + * buffer is 'output'. The signal is processed first to alert any current + * readers or writers to discontinue and exit their i/o loops. + * * Locking: ctrl_lock */ static void isig(int sig, struct tty_struct *tty) { + struct n_tty_data *ldata = tty->disc_data; struct pid *tty_pgrp = tty_get_pgrp(tty); if (tty_pgrp) { kill_pgrp(tty_pgrp, sig, 1); put_pid(tty_pgrp); } + + if (!L_NOFLSH(tty)) { + up_read(&tty->termios_rwsem); + down_write(&tty->termios_rwsem); + + /* clear echo buffer */ + mutex_lock(&ldata->output_lock); + ldata->echo_head = ldata->echo_tail = 0; + ldata->echo_mark = ldata->echo_commit = 0; + mutex_unlock(&ldata->output_lock); + + /* clear output buffer */ + tty_driver_flush_buffer(tty); + + /* clear input buffer */ + reset_buffer_flags(tty->disc_data); + + /* notify pty master of flush */ + if (tty->link) + n_tty_packet_mode_flush(tty); + + up_write(&tty->termios_rwsem); + down_read(&tty->termios_rwsem); + } } /** @@ -1139,7 +1140,6 @@ static void isig(int sig, struct tty_struct *tty) * * n_tty_receive_buf()/producer path: * caller holds non-exclusive termios_rwsem - * publishes read_head via put_tty_queue() * * Note: may get exclusive termios_rwsem if flushing input buffer */ @@ -1152,13 +1152,6 @@ static void n_tty_receive_break(struct tty_struct *tty) return; if (I_BRKINT(tty)) { isig(SIGINT, tty); - if (!L_NOFLSH(tty)) { - /* flushing needs exclusive termios_rwsem */ - up_read(&tty->termios_rwsem); - n_tty_flush_buffer(tty); - tty_driver_flush_buffer(tty); - down_read(&tty->termios_rwsem); - } return; } if (I_PARMRK(tty)) { @@ -1209,7 +1202,6 @@ static void n_tty_receive_overrun(struct tty_struct *tty) * * n_tty_receive_buf()/producer path: * caller holds non-exclusive termios_rwsem - * publishes read_head via put_tty_queue() */ static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c) { @@ -1233,13 +1225,7 @@ static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c) static void n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) { - if (!L_NOFLSH(tty)) { - /* flushing needs exclusive termios_rwsem */ - up_read(&tty->termios_rwsem); - n_tty_flush_buffer(tty); - tty_driver_flush_buffer(tty); - down_read(&tty->termios_rwsem); - } + isig(signal, tty); if (I_IXON(tty)) start_tty(tty); if (L_ECHO(tty)) { @@ -1247,7 +1233,6 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) commit_echoes(tty); } else process_echoes(tty); - isig(signal, tty); return; } @@ -1263,7 +1248,6 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) * n_tty_receive_buf()/producer path: * caller holds non-exclusive termios_rwsem * publishes canon_head if canonical mode is active - * otherwise, publishes read_head via put_tty_queue() * * Returns 1 if LNEXT was received, else returns 0 */ @@ -1376,7 +1360,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) handle_newline: set_bit(ldata->read_head & (N_TTY_BUF_SIZE - 1), ldata->read_flags); put_tty_queue(c, ldata); - ldata->canon_head = ldata->read_head; + smp_store_release(&ldata->canon_head, ldata->read_head); kill_fasync(&tty->fasync, SIGIO, POLL_IN); if (waitqueue_active(&tty->read_wait)) wake_up_interruptible_poll(&tty->read_wait, POLLIN); @@ -1512,23 +1496,6 @@ n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag) n_tty_receive_char_flagged(tty, c, flag); } -/** - * n_tty_receive_buf - data receive - * @tty: terminal device - * @cp: buffer - * @fp: flag buffer - * @count: characters - * - * Called by the terminal driver when a block of characters has - * been received. This function must be called from soft contexts - * not from interrupt context. The driver is responsible for making - * calls one at a time and in order (or using flush_to_ldisc) - * - * n_tty_receive_buf()/producer path: - * claims non-exclusive termios_rwsem - * publishes read_head and canon_head - */ - static void n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) @@ -1537,16 +1504,14 @@ n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp, size_t n, head; head = ldata->read_head & (N_TTY_BUF_SIZE - 1); - n = N_TTY_BUF_SIZE - max(read_cnt(ldata), head); - n = min_t(size_t, count, n); + n = min_t(size_t, count, N_TTY_BUF_SIZE - head); memcpy(read_buf_addr(ldata, head), cp, n); ldata->read_head += n; cp += n; count -= n; head = ldata->read_head & (N_TTY_BUF_SIZE - 1); - n = N_TTY_BUF_SIZE - max(read_cnt(ldata), head); - n = min_t(size_t, count, n); + n = min_t(size_t, count, N_TTY_BUF_SIZE - head); memcpy(read_buf_addr(ldata, head), cp, n); ldata->read_head += n; } @@ -1676,32 +1641,98 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, tty->ops->flush_chars(tty); } - if ((!ldata->icanon && (read_cnt(ldata) >= ldata->minimum_to_wake)) || - L_EXTPROC(tty)) { + if (ldata->icanon && !L_EXTPROC(tty)) + return; + + /* publish read_head to consumer */ + smp_store_release(&ldata->commit_head, ldata->read_head); + + if ((read_cnt(ldata) >= ldata->minimum_to_wake) || L_EXTPROC(tty)) { kill_fasync(&tty->fasync, SIGIO, POLL_IN); if (waitqueue_active(&tty->read_wait)) wake_up_interruptible_poll(&tty->read_wait, POLLIN); } } +/** + * n_tty_receive_buf_common - process input + * @tty: device to receive input + * @cp: input chars + * @fp: flags for each char (if NULL, all chars are TTY_NORMAL) + * @count: number of input chars in @cp + * + * Called by the terminal driver when a block of characters has + * been received. This function must be called from soft contexts + * not from interrupt context. The driver is responsible for making + * calls one at a time and in order (or using flush_to_ldisc) + * + * Returns the # of input chars from @cp which were processed. + * + * In canonical mode, the maximum line length is 4096 chars (including + * the line termination char); lines longer than 4096 chars are + * truncated. After 4095 chars, input data is still processed but + * not stored. Overflow processing ensures the tty can always + * receive more input until at least one line can be read. + * + * In non-canonical mode, the read buffer will only accept 4095 chars; + * this provides the necessary space for a newline char if the input + * mode is switched to canonical. + * + * Note it is possible for the read buffer to _contain_ 4096 chars + * in non-canonical mode: the read buffer could already contain the + * maximum canon line of 4096 chars when the mode is switched to + * non-canonical. + * + * n_tty_receive_buf()/producer path: + * claims non-exclusive termios_rwsem + * publishes commit_head or canon_head + */ static int n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, char *fp, int count, int flow) { struct n_tty_data *ldata = tty->disc_data; - int room, n, rcvd = 0; + int room, n, rcvd = 0, overflow; down_read(&tty->termios_rwsem); while (1) { - room = receive_room(tty); + /* + * When PARMRK is set, each input char may take up to 3 chars + * in the read buf; reduce the buffer space avail by 3x + * + * If we are doing input canonicalization, and there are no + * pending newlines, let characters through without limit, so + * that erase characters will be handled. Other excess + * characters will be beeped. + * + * paired with store in *_copy_from_read_buf() -- guarantees + * the consumer has loaded the data in read_buf up to the new + * read_tail (so this producer will not overwrite unread data) + */ + size_t tail = smp_load_acquire(&ldata->read_tail); + + room = N_TTY_BUF_SIZE - (ldata->read_head - tail); + if (I_PARMRK(tty)) + room = (room + 2) / 3; + room--; + if (room <= 0) { + overflow = ldata->icanon && ldata->canon_head == tail; + if (overflow && room < 0) + ldata->read_head--; + room = overflow; + ldata->no_room = flow && !room; + } else + overflow = 0; + n = min(count, room); - if (!n) { - if (flow && !room) - ldata->no_room = 1; + if (!n) break; - } - __receive_buf(tty, cp, fp, n); + + /* ignore parity errors if handling overflow */ + if (!overflow || !fp || *fp != TTY_PARITY) + __receive_buf(tty, cp, fp, n); + cp += n; if (fp) fp += n; @@ -1710,7 +1741,17 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, } tty->receive_room = room; - n_tty_check_throttle(tty); + + /* Unthrottle if handling overflow on pty */ + if (tty->driver->type == TTY_DRIVER_TYPE_PTY) { + if (overflow) { + tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE); + tty_unthrottle_safe(tty); + __tty_set_flow_change(tty, 0); + } + } else + n_tty_check_throttle(tty); + up_read(&tty->termios_rwsem); return rcvd; @@ -1764,6 +1805,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) ldata->canon_head = ldata->read_head; ldata->push = 1; } + ldata->commit_head = ldata->read_head; ldata->erasing = 0; ldata->lnext = 0; } @@ -1817,7 +1859,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) else ldata->real_raw = 0; } - n_tty_set_room(tty); /* * Fix tty hang when I_IXON(tty) is cleared, but the tty * been stopped by STOP_CHAR(tty) before it. @@ -1905,7 +1946,7 @@ static inline int input_available_p(struct tty_struct *tty, int poll) if (ldata->icanon && !L_EXTPROC(tty)) return ldata->canon_head != ldata->read_tail; else - return read_cnt(ldata) >= amt; + return ldata->commit_head - ldata->read_tail >= amt; } /** @@ -1937,10 +1978,11 @@ static int copy_from_read_buf(struct tty_struct *tty, int retval; size_t n; bool is_eof; + size_t head = smp_load_acquire(&ldata->commit_head); size_t tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); retval = 0; - n = min(read_cnt(ldata), N_TTY_BUF_SIZE - tail); + n = min(head - ldata->read_tail, N_TTY_BUF_SIZE - tail); n = min(*nr, n); if (n) { retval = copy_to_user(*b, read_buf_addr(ldata, tail), n); @@ -1948,9 +1990,10 @@ static int copy_from_read_buf(struct tty_struct *tty, is_eof = n == 1 && read_buf(ldata, tail) == EOF_CHAR(tty); tty_audit_add_data(tty, read_buf_addr(ldata, tail), n, ldata->icanon); - ldata->read_tail += n; + smp_store_release(&ldata->read_tail, ldata->read_tail + n); /* Turn single EOF into zero-length read */ - if (L_EXTPROC(tty) && ldata->icanon && is_eof && !read_cnt(ldata)) + if (L_EXTPROC(tty) && ldata->icanon && is_eof && + (head == ldata->read_tail)) n = 0; *b += n; *nr -= n; @@ -1993,7 +2036,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, bool eof_push = 0; /* N.B. avoid overrun if nr == 0 */ - n = min(*nr, read_cnt(ldata)); + n = min(*nr, smp_load_acquire(&ldata->canon_head) - ldata->read_tail); if (!n) return 0; @@ -2043,8 +2086,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, if (found) clear_bit(eol, ldata->read_flags); - smp_mb__after_atomic(); - ldata->read_tail += c; + smp_store_release(&ldata->read_tail, ldata->read_tail + c); if (found) { if (!ldata->push) @@ -2130,6 +2172,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, ssize_t retval = 0; long timeout; int packet; + size_t tail; c = job_control(tty, file); if (c < 0) @@ -2166,6 +2209,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, } packet = tty->packet; + tail = ldata->read_tail; add_wait_queue(&tty->read_wait, &wait); while (nr) { @@ -2208,7 +2252,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, retval = -ERESTARTSYS; break; } - n_tty_set_room(tty); up_read(&tty->termios_rwsem); timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, @@ -2253,7 +2296,8 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, if (time) timeout = time; } - n_tty_set_room(tty); + if (tail != ldata->read_tail) + n_tty_kick_worker(tty); up_read(&tty->termios_rwsem); remove_wait_queue(&tty->read_wait, &wait); diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index a9d256d6e909..e72ee629cead 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -88,19 +88,6 @@ static void pty_unthrottle(struct tty_struct *tty) } /** - * pty_space - report space left for writing - * @to: tty we are writing into - * - * Limit the buffer space used by ptys to 8k. - */ - -static int pty_space(struct tty_struct *to) -{ - int n = tty_buffer_space_avail(to->port); - return min(n, 8192); -} - -/** * pty_write - write to a pty * @tty: the tty we write from * @buf: kernel buffer of data @@ -141,7 +128,7 @@ static int pty_write_room(struct tty_struct *tty) { if (tty->stopped) return 0; - return pty_space(tty->link); + return tty_buffer_space_avail(tty->link->port); } /** @@ -210,6 +197,9 @@ static int pty_signal(struct tty_struct *tty, int sig) { struct pid *pgrp; + if (sig != SIGINT && sig != SIGQUIT && sig != SIGTSTP) + return -EINVAL; + if (tty->link) { pgrp = tty_get_pgrp(tty->link); if (pgrp) @@ -222,10 +212,16 @@ static int pty_signal(struct tty_struct *tty, int sig) static void pty_flush_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; + struct tty_ldisc *ld; if (!to) return; - /* tty_buffer_flush(to); FIXME */ + + ld = tty_ldisc_ref(to); + tty_buffer_flush(to, ld); + if (ld) + tty_ldisc_deref(ld); + if (to->packet) { spin_lock_irq(&tty->ctrl_lock); tty->ctrl_status |= TIOCPKT_FLUSHWRITE; @@ -399,6 +395,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, goto err_put_module; tty_set_lock_subclass(o_tty); + lockdep_set_subclass(&o_tty->termios_rwsem, TTY_LOCK_SLAVE); if (legacy) { /* We always use new tty termios data so we can do this @@ -429,10 +426,14 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, o_tty->link = tty; tty_port_init(ports[0]); tty_port_init(ports[1]); + tty_buffer_set_limit(ports[0], 8192); + tty_buffer_set_limit(ports[1], 8192); o_tty->port = ports[0]; tty->port = ports[1]; o_tty->port->itty = o_tty; + tty_buffer_set_lock_subclass(o_tty->port); + tty_driver_kref_get(driver); tty->count++; o_tty->count++; diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 383c4c796637..c8dd8dc31086 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1390,7 +1390,7 @@ static void rp_unthrottle(struct tty_struct *tty) tty->ldisc.chars_in_buffer(tty)); #endif - if (rocket_paranoia_check(info, "rp_throttle")) + if (rocket_paranoia_check(info, "rp_unthrottle")) return; if (I_IXOFF(tty)) @@ -1458,7 +1458,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) orig_jiffies = jiffies; #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT - printk(KERN_INFO "In RP_wait_until_sent(%d) (jiff=%lu)...\n", timeout, + printk(KERN_INFO "In %s(%d) (jiff=%lu)...\n", __func__, timeout, jiffies); printk(KERN_INFO "cps=%d...\n", info->cps); #endif diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 11c66856ba2f..e3b9570a1eff 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -329,6 +329,17 @@ static const struct serial8250_config uart_config[] = { .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, +/* tx_loadsz is set to 63-bytes instead of 64-bytes to implement +workaround of errata A-008006 which states that tx_loadsz should be +configured less than Maximum supported fifo bytes */ + [PORT_16550A_FSL64] = { + .name = "16550A_FSL64", + .fifo_size = 64, |