diff options
Diffstat (limited to 'drivers/tty/n_tty.c')
-rw-r--r-- | drivers/tty/n_tty.c | 201 |
1 files changed, 68 insertions, 133 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 9686c5d10571..0ec93f1a61f5 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -342,10 +342,10 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty) { unsigned long flags; - if (tty->link->packet) { - spin_lock_irqsave(&tty->ctrl_lock, flags); - tty->ctrl_status |= TIOCPKT_FLUSHREAD; - spin_unlock_irqrestore(&tty->ctrl_lock, flags); + if (tty->link->ctrl.packet) { + spin_lock_irqsave(&tty->ctrl.lock, flags); + tty->ctrl.pktstatus |= TIOCPKT_FLUSHREAD; + spin_unlock_irqrestore(&tty->ctrl.lock, flags); wake_up_interruptible(&tty->link->read_wait); } } @@ -361,7 +361,7 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty) * Holds termios_rwsem to exclude producer/consumer while * buffer indices are reset. * - * Locking: ctrl_lock, exclusive termios_rwsem + * Locking: ctrl.lock, exclusive termios_rwsem */ static void n_tty_flush_buffer(struct tty_struct *tty) @@ -1103,7 +1103,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) * 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 + * Locking: ctrl.lock */ static void __isig(int sig, struct tty_struct *tty) @@ -1245,7 +1245,6 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) commit_echoes(tty); } else process_echoes(tty); - return; } /** @@ -1260,12 +1259,8 @@ 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 - * - * Returns 1 if LNEXT was received, else returns 0 */ - -static int -n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) +static void n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; @@ -1273,35 +1268,35 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) if (c == START_CHAR(tty)) { start_tty(tty); process_echoes(tty); - return 0; + return; } if (c == STOP_CHAR(tty)) { stop_tty(tty); - return 0; + return; } } if (L_ISIG(tty)) { if (c == INTR_CHAR(tty)) { n_tty_receive_signal_char(tty, SIGINT, c); - return 0; + return; } else if (c == QUIT_CHAR(tty)) { n_tty_receive_signal_char(tty, SIGQUIT, c); - return 0; + return; } else if (c == SUSP_CHAR(tty)) { n_tty_receive_signal_char(tty, SIGTSTP, c); - return 0; + return; } } - if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { + if (tty->flow.stopped && !tty->flow.tco_stopped && I_IXON(tty) && I_IXANY(tty)) { start_tty(tty); process_echoes(tty); } if (c == '\r') { if (I_IGNCR(tty)) - return 0; + return; if (I_ICRNL(tty)) c = '\n'; } else if (c == '\n' && I_INLCR(tty)) @@ -1312,7 +1307,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) { eraser(c, tty); commit_echoes(tty); - return 0; + return; } if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) { ldata->lnext = 1; @@ -1324,7 +1319,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) commit_echoes(tty); } } - return 1; + return; } if (c == REPRINT_CHAR(tty) && L_ECHO(tty) && L_IEXTEN(tty)) { size_t tail = ldata->canon_head; @@ -1337,7 +1332,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) tail++; } commit_echoes(tty); - return 0; + return; } if (c == '\n') { if (L_ECHO(tty) || L_ECHONL(tty)) { @@ -1375,7 +1370,7 @@ handle_newline: smp_store_release(&ldata->canon_head, ldata->read_head); kill_fasync(&tty->fasync, SIGIO, POLL_IN); wake_up_interruptible_poll(&tty->read_wait, EPOLLIN); - return 0; + return; } } @@ -1397,15 +1392,13 @@ handle_newline: put_tty_queue(c, ldata); put_tty_queue(c, ldata); - return 0; } -static inline void -n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) +static void n_tty_receive_char(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; - if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { + if (tty->flow.stopped && !tty->flow.tco_stopped && I_IXON(tty) && I_IXANY(tty)) { start_tty(tty); process_echoes(tty); } @@ -1423,31 +1416,6 @@ n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) put_tty_queue(c, ldata); } -static void n_tty_receive_char(struct tty_struct *tty, unsigned char c) -{ - n_tty_receive_char_inline(tty, c); -} - -static inline void -n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) -{ - struct n_tty_data *ldata = tty->disc_data; - - if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { - start_tty(tty); - process_echoes(tty); - } - if (L_ECHO(tty)) { - finish_erasing(ldata); - /* Record the column of first canon char. */ - if (ldata->canon_head == ldata->read_head) - echo_set_canon_col(ldata); - echo_char(c, tty); - commit_echoes(tty); - } - put_tty_queue(c, ldata); -} - static void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c) { if (I_ISTRIP(tty)) @@ -1459,7 +1427,7 @@ static void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c) if (c == STOP_CHAR(tty)) stop_tty(tty); else if (c == START_CHAR(tty) || - (tty->stopped && !tty->flow_stopped && I_IXANY(tty) && + (tty->flow.stopped && !tty->flow.tco_stopped && I_IXANY(tty) && c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty))) { start_tty(tty); @@ -1506,7 +1474,7 @@ n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag) static void n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; size_t n, head; @@ -1526,7 +1494,7 @@ n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp, static void n_tty_receive_buf_raw(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; char flag = TTY_NORMAL; @@ -1543,7 +1511,7 @@ n_tty_receive_buf_raw(struct tty_struct *tty, const unsigned char *cp, static void n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { char flag = TTY_NORMAL; @@ -1555,68 +1523,46 @@ n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, } } -static void -n_tty_receive_buf_standard(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) +static void n_tty_receive_buf_standard(struct tty_struct *tty, + const unsigned char *cp, const char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; char flag = TTY_NORMAL; while (count--) { + unsigned char c = *cp++; + if (fp) flag = *fp++; - if (likely(flag == TTY_NORMAL)) { - unsigned char c = *cp++; - - if (I_ISTRIP(tty)) - c &= 0x7f; - if (I_IUCLC(tty) && L_IEXTEN(tty)) - c = tolower(c); - if (L_EXTPROC(tty)) { - put_tty_queue(c, ldata); - continue; - } - if (!test_bit(c, ldata->char_map)) - n_tty_receive_char_inline(tty, c); - else if (n_tty_receive_char_special(tty, c) && count) { - if (fp) - flag = *fp++; - n_tty_receive_char_lnext(tty, *cp++, flag); - count--; - } - } else - n_tty_receive_char_flagged(tty, *cp++, flag); - } -} -static void -n_tty_receive_buf_fast(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) -{ - struct n_tty_data *ldata = tty->disc_data; - char flag = TTY_NORMAL; + if (ldata->lnext) { + n_tty_receive_char_lnext(tty, c, flag); + continue; + } - while (count--) { - if (fp) - flag = *fp++; - if (likely(flag == TTY_NORMAL)) { - unsigned char c = *cp++; - - if (!test_bit(c, ldata->char_map)) - n_tty_receive_char_fast(tty, c); - else if (n_tty_receive_char_special(tty, c) && count) { - if (fp) - flag = *fp++; - n_tty_receive_char_lnext(tty, *cp++, flag); - count--; - } - } else - n_tty_receive_char_flagged(tty, *cp++, flag); + if (unlikely(flag != TTY_NORMAL)) { + n_tty_receive_char_flagged(tty, c, flag); + continue; + } + + if (I_ISTRIP(tty)) + c &= 0x7f; + if (I_IUCLC(tty) && L_IEXTEN(tty)) + c = tolower(c); + if (L_EXTPROC(tty)) { + put_tty_queue(c, ldata); + continue; + } + + if (test_bit(c, ldata->char_map)) + n_tty_receive_char_special(tty, c); + else + n_tty_receive_char(tty, c); } } static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; bool preops = I_ISTRIP(tty) || (I_IUCLC(tty) && L_IEXTEN(tty)); @@ -1628,19 +1574,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, else if (tty->closing && !L_EXTPROC(tty)) n_tty_receive_buf_closing(tty, cp, fp, count); else { - if (ldata->lnext) { - char flag = TTY_NORMAL; - - if (fp) - flag = *fp++; - n_tty_receive_char_lnext(tty, *cp++, flag); - count--; - } - - if (!preops && !I_PARMRK(tty)) - n_tty_receive_buf_fast(tty, cp, fp, count); - else - n_tty_receive_buf_standard(tty, cp, fp, count); + n_tty_receive_buf_standard(tty, cp, fp, count); flush_echoes(tty); if (tty->ops->flush_chars) @@ -1695,7 +1629,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, */ static int n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count, int flow) + const char *fp, int count, int flow) { struct n_tty_data *ldata = tty->disc_data; int room, n, rcvd = 0, overflow; @@ -1764,13 +1698,13 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, } static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { n_tty_receive_buf_common(tty, cp, fp, count, 0); } static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { return n_tty_receive_buf_common(tty, cp, fp, count, 1); } @@ -1863,7 +1797,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) * Fix tty hang when I_IXON(tty) is cleared, but the tty * been stopped by STOP_CHAR(tty) before it. */ - if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) { + if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow.tco_stopped) { start_tty(tty); process_echoes(tty); } @@ -2091,7 +2025,7 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty, * * Locking: redirected write test is safe * current->signal->tty check is safe - * ctrl_lock to safely reference tty->pgrp + * ctrl.lock to safely reference tty->ctrl.pgrp */ static int job_control(struct tty_struct *tty, struct file *file) @@ -2138,7 +2072,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, int minimum, time; ssize_t retval = 0; long timeout; - int packet; + bool packet; size_t tail; /* @@ -2194,20 +2128,20 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, } } - packet = tty->packet; + packet = tty->ctrl.packet; tail = ldata->read_tail; add_wait_queue(&tty->read_wait, &wait); while (nr) { /* First test for status change. */ - if (packet && tty->link->ctrl_status) { + if (packet && tty->link->ctrl.pktstatus) { unsigned char cs; if (kb != kbuf) break; - spin_lock_irq(&tty->link->ctrl_lock); - cs = tty->link->ctrl_status; - tty->link->ctrl_status = 0; - spin_unlock_irq(&tty->link->ctrl_lock); + spin_lock_irq(&tty->link->ctrl.lock); + cs = tty->link->ctrl.pktstatus; + tty->link->ctrl.pktstatus = 0; + spin_unlock_irq(&tty->link->ctrl.lock); *kb++ = cs; nr--; break; @@ -2434,7 +2368,7 @@ static __poll_t n_tty_poll(struct tty_struct *tty, struct file *file, if (input_available_p(tty, 1)) mask |= EPOLLIN | EPOLLRDNORM; } - if (tty->packet && tty->link->ctrl_status) + if (tty->ctrl.packet && tty->link->ctrl.pktstatus) mask |= EPOLLPRI | EPOLLIN | EPOLLRDNORM; if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) mask |= EPOLLHUP; @@ -2490,6 +2424,7 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, static struct tty_ldisc_ops n_tty_ops = { .owner = THIS_MODULE, + .num = N_TTY, .name = "n_tty", .open = n_tty_open, .close = n_tty_close, @@ -2515,11 +2450,11 @@ void n_tty_inherit_ops(struct tty_ldisc_ops *ops) { *ops = n_tty_ops; ops->owner = NULL; - ops->refcount = ops->flags = 0; + ops->flags = 0; } EXPORT_SYMBOL_GPL(n_tty_inherit_ops); void __init n_tty_init(void) { - tty_register_ldisc(N_TTY, &n_tty_ops); + tty_register_ldisc(&n_tty_ops); } |