diff options
Diffstat (limited to 'drivers')
40 files changed, 623 insertions, 904 deletions
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 45df4bf914f8..22c27652e46a 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -1349,7 +1349,7 @@ static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty) /* TODO:disable interrupts instead of reset to preserve signal states */ reset_device(info); - if (!tty || tty->termios.c_cflag & HUPCL) { + if (!tty || C_HUPCL(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); set_signals(info); } @@ -1390,7 +1390,7 @@ static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty) port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI); get_signals(info); - if (info->netcount || (tty && (tty->termios.c_cflag & CREAD))) + if (info->netcount || (tty && C_CREAD(tty))) rx_start(info); spin_unlock_irqrestore(&info->lock, flags); @@ -1733,7 +1733,7 @@ static void mgslpc_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) mgslpc_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock, flags); info->serial_signals &= ~SerialSignal_RTS; set_signals(info); @@ -1762,7 +1762,7 @@ static void mgslpc_unthrottle(struct tty_struct * tty) mgslpc_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock, flags); info->serial_signals |= SerialSignal_RTS; set_signals(info); @@ -2306,8 +2306,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term mgslpc_change_params(info, tty); /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); spin_lock_irqsave(&info->lock, flags); set_signals(info); @@ -2315,21 +2314,17 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->serial_signals |= SerialSignal_RTS; - } spin_lock_irqsave(&info->lock, flags); set_signals(info); spin_unlock_irqrestore(&info->lock, flags); } /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + if (old_termios->c_cflag & CRTSCTS && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; tx_release(tty); } diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 2175225af742..947d5c978b8f 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1572,7 +1572,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) #endif return; } - port->flags |= ASYNC_CLOSING; + info->closing = 1; tty->closing = 1; /* @@ -1603,6 +1603,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) info->ncarrier = 0; tty_port_close_end(port, tty); + info->closing = 0; #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close normal exit\n"); #endif @@ -2236,7 +2237,7 @@ isdn_tty_at_cout(char *msg, modem_info *info) l = strlen(msg); spin_lock_irqsave(&info->readlock, flags); - if (port->flags & ASYNC_CLOSING) { + if (info->closing) { spin_unlock_irqrestore(&info->readlock, flags); return; } @@ -2386,13 +2387,12 @@ isdn_tty_modem_result(int code, modem_info *info) case RESULT_NO_CARRIER: #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n", - (info->port.flags & ASYNC_CLOSING), - (!info->port.tty)); + info->closing, !info->port.tty); #endif m->mdmreg[REG_RINGCNT] = 0; del_timer(&info->nc_timer); info->ncarrier = 0; - if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty)) + if (info->closing || !info->port.tty) return; #ifdef CONFIG_ISDN_AUDIO @@ -2525,7 +2525,7 @@ isdn_tty_modem_result(int code, modem_info *info) } } if (code == RESULT_NO_CARRIER) { - if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty)) + if (info->closing || (!info->port.tty)) return; if (info->port.flags & ASYNC_CHECK_CD) diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index d2de5925b73e..5415056f9aa5 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c @@ -493,7 +493,7 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) if (status & UART_MSR_DCTS) { port->icount.cts++; tty = tty_port_tty_get(&port->port); - if (tty && (tty->termios.c_cflag & CRTSCTS)) { + if (tty && C_CRTSCTS(tty)) { int cts = (status & UART_MSR_CTS); if (tty->hw_stopped) { if (cts) { @@ -648,10 +648,10 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) sdio_uart_change_speed(port, &tty->termios, NULL); - if (tty->termios.c_cflag & CBAUD) + if (C_BAUD(tty)) sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) tty->hw_stopped = 1; @@ -833,7 +833,7 @@ static void sdio_uart_throttle(struct tty_struct *tty) { struct sdio_uart_port *port = tty->driver_data; - if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS)) + if (!I_IXOFF(tty) && !C_CRTSCTS(tty)) return; if (sdio_uart_claim_func(port) != 0) @@ -844,7 +844,7 @@ static void sdio_uart_throttle(struct tty_struct *tty) sdio_uart_start_tx(port); } - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) sdio_uart_clear_mctrl(port, TIOCM_RTS); sdio_uart_irq(port->func); @@ -855,7 +855,7 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) { struct sdio_uart_port *port = tty->driver_data; - if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS)) + if (!I_IXOFF(tty) && !C_CRTSCTS(tty)) return; if (sdio_uart_claim_func(port) != 0) @@ -870,7 +870,7 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) } } - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) sdio_uart_set_mctrl(port, TIOCM_RTS); sdio_uart_irq(port->func); diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 7d82bbcb12df..e7e078b3c7e6 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -643,7 +643,6 @@ static void raw3215_shutdown(struct raw3215_info *raw) if ((raw->flags & RAW3215_WORKING) || raw->queued_write != NULL || raw->queued_read != NULL) { - raw->port.flags |= ASYNC_CLOSING; add_wait_queue(&raw->empty_wait, &wait); set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); @@ -651,7 +650,7 @@ static void raw3215_shutdown(struct raw3215_info *raw) spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); remove_wait_queue(&raw->empty_wait, &wait); set_current_state(TASK_RUNNING); - raw->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING); + raw->port.flags &= ~ASYNC_INITIALIZED; } spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); } diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index bad355100825..294c1c83aa4d 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -1530,7 +1530,7 @@ static void dgap_input(struct channel_t *ch) if ((bd->state != BOARD_READY) || !tp || (tp->magic != TTY_MAGIC) || !(ch->ch_tun.un_flags & UN_ISOPEN) || - !(tp->termios.c_cflag & CREAD) || + !C_CREAD(tp) || (ch->ch_tun.un_flags & UN_CLOSING)) { writew(head, &bs->rx_tail); writeb(1, &bs->idata); @@ -1665,9 +1665,7 @@ static void dgap_input(struct channel_t *ch) } static void dgap_write_wakeup(struct board_t *bd, struct channel_t *ch, - struct un_t *un, u32 mask, - unsigned long *irq_flags1, - unsigned long *irq_flags2) + struct un_t *un, u32 mask) { if (!(un->un_flags & mask)) return; @@ -1677,17 +1675,7 @@ static void dgap_write_wakeup(struct board_t *bd, struct channel_t *ch, if (!(un->un_flags & UN_ISOPEN)) return; - if ((un->un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - un->un_tty->ldisc->ops->write_wakeup) { - spin_unlock_irqrestore(&ch->ch_lock, *irq_flags2); - spin_unlock_irqrestore(&bd->bd_lock, *irq_flags1); - - (un->un_tty->ldisc->ops->write_wakeup)(un->un_tty); - - spin_lock_irqsave(&bd->bd_lock, *irq_flags1); - spin_lock_irqsave(&ch->ch_lock, *irq_flags2); - } - wake_up_interruptible(&un->un_tty->write_wait); + tty_wakeup(un->un_tty); wake_up_interruptible(&un->un_flags_wait); } @@ -1952,10 +1940,8 @@ static int dgap_event(struct board_t *bd) * Process Transmit low. */ if (reason & IFTLW) { - dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_LOW, - &lock_flags, &lock_flags2); - dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_LOW, - &lock_flags, &lock_flags2); + dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_LOW); + dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_LOW); if (ch->ch_flags & CH_WLOW) { ch->ch_flags &= ~CH_WLOW; wake_up_interruptible(&ch->ch_flags_wait); @@ -1966,10 +1952,8 @@ static int dgap_event(struct board_t *bd) * Process Transmit empty. */ if (reason & IFTEM) { - dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_EMPTY, - &lock_flags, &lock_flags2); - dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_EMPTY, - &lock_flags, &lock_flags2); + dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_EMPTY); + dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_EMPTY); if (ch->ch_flags & CH_WEMPTY) { ch->ch_flags &= ~CH_WEMPTY; wake_up_interruptible(&ch->ch_flags_wait); @@ -3171,8 +3155,6 @@ static void dgap_tty_flush_buffer(struct tty_struct *tty) spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - if (waitqueue_active(&tty->write_wait)) - wake_up_interruptible(&tty->write_wait); tty_wakeup(tty); } @@ -4969,10 +4951,6 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, ch->ch_pun.un_flags &= ~(UN_LOW | UN_EMPTY); wake_up_interruptible(&ch->ch_pun.un_flags_wait); } - if (waitqueue_active(&tty->write_wait)) - wake_up_interruptible(&tty->write_wait); - - /* Can't hold any locks when calling tty_wakeup! */ spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); tty_wakeup(tty); diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index b79eab084c02..8b1ba65a6984 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -541,7 +541,7 @@ void dgnc_input(struct channel_t *ch) */ if (!tp || (tp->magic != TTY_MAGIC) || !(ch->ch_tun.un_flags & UN_ISOPEN) || - !(tp->termios.c_cflag & CREAD) || + !C_CREAD(tp) || (ch->ch_tun.un_flags & UN_CLOSING)) { ch->ch_r_head = tail; @@ -933,14 +933,7 @@ void dgnc_wakeup_writes(struct channel_t *ch) } if (ch->ch_tun.un_flags & UN_ISOPEN) { - if ((ch->ch_tun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - ch->ch_tun.un_tty->ldisc->ops->write_wakeup) { - spin_unlock_irqrestore(&ch->ch_lock, flags); - ch->ch_tun.un_tty->ldisc->ops->write_wakeup(ch->ch_tun.un_tty); - spin_lock_irqsave(&ch->ch_lock, flags); - } - - wake_up_interruptible(&ch->ch_tun.un_tty->write_wait); + tty_wakeup(ch->ch_tun.un_tty); /* * If unit is set to wait until empty, check to make sure @@ -975,14 +968,7 @@ void dgnc_wakeup_writes(struct channel_t *ch) } if (ch->ch_pun.un_flags & UN_ISOPEN) { - if ((ch->ch_pun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - ch->ch_pun.un_tty->ldisc->ops->write_wakeup) { - spin_unlock_irqrestore(&ch->ch_lock, flags); - ch->ch_pun.un_tty->ldisc->ops->write_wakeup(ch->ch_pun.un_tty); - spin_lock_irqsave(&ch->ch_lock, flags); - } - - wake_up_interruptible(&ch->ch_pun.un_tty->write_wait); + tty_wakeup(ch->ch_pun.un_tty); /* * If unit is set to wait until empty, check to make sure diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 2caaf5a2516d..eacf4c9f3b29 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -639,7 +639,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) custom.adkcon = AC_UARTBRK; mb(); - if (tty->termios.c_cflag & HUPCL) + if (C_HUPCL(tty)) info->MCR &= ~(SER_DTR|SER_RTS); rtsdtr_ctrl(info->MCR); @@ -965,8 +965,7 @@ static void rs_throttle(struct tty_struct * tty) struct serial_state *info = tty->driver_data; unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE - printk("throttle %s: %d....\n", tty_name(tty), - tty->ldisc.chars_in_buffer(tty)); + printk("throttle %s ....\n", tty_name(tty)); #endif if (serial_paranoia_check(info, tty->name, "rs_throttle")) @@ -975,7 +974,7 @@ static void rs_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) rs_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) info->MCR &= ~SER_RTS; local_irq_save(flags); @@ -988,8 +987,7 @@ static void rs_unthrottle(struct tty_struct * tty) struct serial_state *info = tty->driver_data; unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE - printk("unthrottle %s: %d....\n", tty_name(tty), - tty->ldisc.chars_in_buffer(tty)); + printk("unthrottle %s ....\n", tty_name(tty)); #endif if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) @@ -1001,7 +999,7 @@ static void rs_unthrottle(struct tty_struct * tty) else rs_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) info->MCR |= SER_RTS; local_irq_save(flags); rtsdtr_ctrl(info->MCR); @@ -1334,8 +1332,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_speed(tty, info, old_termios); /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && - !(cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) { info->MCR &= ~(SER_DTR|SER_RTS); local_irq_save(flags); rtsdtr_ctrl(info->MCR); @@ -1343,21 +1340,17 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - (cflag & CBAUD)) { + if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { info->MCR |= SER_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->MCR |= SER_RTS; - } local_irq_save(flags); rtsdtr_ctrl(info->MCR); local_irq_restore(flags); } /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; rs_start(tty); } @@ -1369,8 +1362,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * XXX It's not clear whether the current behavior is correct * or not. Hence, this may change..... */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios.c_cflag & CLOCAL)) + if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty)) wake_up_interruptible(&info->open_wait); #endif } diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index abbed201dc74..d67e542bab1c 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -1440,7 +1440,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) info->port.xmit_buf = NULL; free_page((unsigned long)temp); } - if (tty->termios.c_cflag & HUPCL) + if (C_HUPCL(tty)) cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR); cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR); @@ -1469,7 +1469,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) free_page((unsigned long)temp); } - if (tty->termios.c_cflag & HUPCL) + if (C_HUPCL(tty)) tty_port_lower_dtr_rts(&info->port); set_bit(TTY_IO_ERROR, &tty->flags); @@ -2795,8 +2795,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) cy_set_line_char(info, tty); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; cy_start(tty); } @@ -2807,8 +2806,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * XXX It's not clear whether the current behavior is correct * or not. Hence, this may change..... */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios.c_cflag & CLOCAL)) + if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty)) wake_up_interruptible(&info->port.open_wait); #endif } /* cy_set_termios */ @@ -2852,8 +2850,8 @@ static void cy_throttle(struct tty_struct *tty) unsigned long flags; #ifdef CY_DEBUG_THROTTLE - printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty), - tty->ldisc.chars_in_buffer(tty), info->line); + printk(KERN_DEBUG "cyc:throttle %s ...ttyC%d\n", tty_name(tty), + info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_throttle")) @@ -2868,7 +2866,7 @@ static void cy_throttle(struct tty_struct *tty) info->throttle = 1; } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { if (!cy_is_Z(card)) { spin_lock_irqsave(&card->card_lock, flags); cyy_change_rts_dtr(info, 0, TIOCM_RTS); @@ -2891,8 +2889,8 @@ static void cy_unthrottle(struct tty_struct *tty) unsigned long flags; #ifdef CY_DEBUG_THROTTLE - printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n", - tty_name(tty), tty_chars_in_buffer(tty), info->line); + printk(KERN_DEBUG "cyc:unthrottle %s ...ttyC%d\n", + tty_name(tty), info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) @@ -2905,7 +2903,7 @@ static void cy_unthrottle(struct tty_struct *tty) cy_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { card = info->card; if (!cy_is_Z(card)) { spin_lock_irqsave(&card->card_lock, flags); diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index 99875949bfb7..8bf67630018b 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -1204,8 +1204,7 @@ static void isicom_set_termios(struct tty_struct *tty, isicom_config_port(tty); spin_unlock_irqrestore(&port->card->card_lock, flags); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; isicom_start(tty); } diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 4c4a23674569..9a0791e523b5 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -254,6 +254,7 @@ struct mxser_port { int xmit_head; int xmit_tail; int xmit_cnt; + int closing; struct ktermios normal_termios; @@ -1081,6 +1082,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) return; if (tty_port_close_start(port, tty, filp) == 0) return; + info->closing = 1; mutex_lock(&port->mutex); mxser_close_port(port); mxser_flush_buffer(tty); @@ -1091,6 +1093,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) mxser_shutdown_port(port); clear_bit(ASYNCB_INITIALIZED, &port->flags); mutex_unlock(&port->mutex); + info->closing = 0; /* Right now the tty_port set is done outside of the close_end helper as we don't yet have everyone using refcounts */ tty_port_close_end(port, tty); @@ -1864,7 +1867,7 @@ static void mxser_stoprx(struct tty_struct *tty) } } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { info->MCR &= ~UART_MCR_RTS; outb(info->MCR, info->ioaddr + UART_MCR); } @@ -1901,7 +1904,7 @@ static void mxser_unthrottle(struct tty_struct *tty) } } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { info->MCR |= UART_MCR_RTS; outb(info->MCR, info->ioaddr + UART_MCR); } @@ -1949,15 +1952,13 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi mxser_change_speed(tty, old_termios); spin_unlock_irqrestore(&info->slock, flags); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; mxser_start(tty); } /* Handle sw stopped */ - if ((old_termios->c_iflag & IXON) && - !(tty->termios.c_iflag & IXON)) { + if ((old_termios->c_iflag & IXON) && !I_IXON(tty)) { tty->stopped = 0; if (info->board->chip_flag) { @@ -2255,10 +2256,8 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) break; iir &= MOXA_MUST_IIR_MASK; tty = tty_port_tty_get(&port->port); - if (!tty || - (port->port.flags & ASYNC_CLOSING) || - !(port->port.flags & - ASYNC_INITIALIZED)) { + if (!tty || port->closing || + !(port->port.flags & ASYNC_INITIALIZED)) { status = inb(port->ioaddr + UART_LSR); outb(0x27, port->ioaddr + UART_FCR); inb(port->ioaddr + UART_MSR); diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c3fe026d3168..c01620780f5b 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1066,7 +1066,7 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, /* Carrier drop -> hangup */ if (tty) { if ((mlines & TIOCM_CD) == 0 && (dlci->modem_rx & TIOCM_CD)) - if (!(tty->termios.c_cflag & CLOCAL)) + if (!C_CLOCAL(tty)) tty_hangup(tty); } if (brk & 0x01) @@ -2304,21 +2304,6 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, } /** - * gsmld_chars_in_buffer - report available bytes - * @tty: tty device - * - * Report the number of characters buffered to be delivered to user - * at this instant in time. - * - * Locking: gsm lock - */ - -static ssize_t gsmld_chars_in_buffer(struct tty_struct *tty) -{ - return 0; -} - -/** * gsmld_flush_buffer - clean input queue * @tty: terminal device * @@ -2830,7 +2815,6 @@ static struct tty_ldisc_ops tty_ldisc_packet = { .open = gsmld_open, .close = gsmld_close, .flush_buffer = gsmld_flush_buffer, - .chars_in_buffer = gsmld_chars_in_buffer, .read = gsmld_read, .write = gsmld_write, .ioctl = gsmld_ioctl, @@ -3132,7 +3116,7 @@ static void gsmtty_throttle(struct tty_struct *tty) struct gsm_dlci *dlci = tty->driver_data; if (dlci->state == DLCI_CLOSED) return; - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) dlci->modem_tx &= ~TIOCM_DTR; dlci->throttled = 1; /* Send an MSC with DTR cleared */ @@ -3144,7 +3128,7 @@ static void gsmtty_unthrottle(struct tty_struct *tty) struct gsm_dlci *dlci = tty->driver_data; if (dlci->state == DLCI_CLOSED) return; - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) dlci->modem_tx |= TIOCM_DTR; dlci->throttled = 0; /* Send an MSC with DTR set */ diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index b280abaad91b..fb76a7d80e7e 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -113,8 +113,6 @@ struct n_tty_data { DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE); unsigned char echo_buf[N_TTY_BUF_SIZE]; - int minimum_to_wake; - /* consumer-published */ size_t read_tail; size_t line_start; @@ -153,15 +151,6 @@ static inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i) return &ldata->echo_buf[i & (N_TTY_BUF_SIZE - 1)]; } -static inline int tty_put_user(struct tty_struct *tty, unsigned char x, - unsigned char __user *ptr) -{ - struct n_tty_data *ldata = tty->disc_data; - - tty_audit_add_data(tty, &x, 1, ldata->icanon); - return put_user(x, ptr); -} - static int tty_copy_to_user(struct tty_struct *tty, void __user *to, size_t tail, size_t n) { @@ -171,7 +160,7 @@ static int tty_copy_to_user(struct tty_struct *tty, void __user *to, int uncopied; if (n > size) { - tty_audit_add_data(tty, from, size, ldata->icanon); + tty_audit_add_data(tty, from, size); uncopied = copy_to_user(to, from, size); if (uncopied) return uncopied; @@ -180,7 +169,7 @@ static int tty_copy_to_user(struct tty_struct *tty, void __user *to, from = ldata->read_buf; } - tty_audit_add_data(tty, from, n, ldata->icanon); + tty_audit_add_data(tty, from, n); return copy_to_user(to, from, n); } @@ -239,8 +228,8 @@ static ssize_t chars_in_buffer(struct tty_struct *tty) static void n_tty_write_wakeup(struct tty_struct *tty) { - if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) - kill_fasync(&tty->fasync, SIGIO, POLL_OUT); + clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + kill_fasync(&tty->fasync, SIGIO, POLL_OUT); } static void n_tty_check_throttle(struct tty_struct *tty) @@ -272,8 +261,6 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) if (tty->driver->type == TTY_DRIVER_TYPE_PTY) { if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) return; - if (!tty->count) - return; n_tty_kick_worker(tty); tty_wakeup(tty->link); return; @@ -292,8 +279,6 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE); if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) break; - if (!tty->count) - break; n_tty_kick_worker(tty); unthrottled = tty_unthrottle_safe(tty); if (!unthrottled) @@ -381,28 +366,6 @@ static void n_tty_flush_buffer(struct tty_struct *tty) } /** - * n_tty_chars_in_buffer - report available bytes - * @tty: tty device - * - * Report the number of characters buffered to be delivered to user - * at this instant in time. - * - * Locking: exclusive termios_rwsem - */ - -static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) -{ - ssize_t n; - - WARN_ONCE(1, "%s is deprecated and scheduled for removal.", __func__); - - down_write(&tty->termios_rwsem); - n = chars_in_buffer(tty); - up_write(&tty->termios_rwsem); - return n; -} - -/** * is_utf8_continuation - utf8 multibyte check * @c: byte to check * @@ -1561,8 +1524,6 @@ n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, flag = *fp++; if (likely(flag == TTY_NORMAL)) n_tty_receive_char_closing(tty, *cp++); - else - n_tty_receive_char_flagged(tty, *cp++, flag); } } @@ -1664,7 +1625,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, /* 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)) { + if (read_cnt(ldata)) { kill_fasync(&tty->fasync, SIGIO, POLL_IN); wake_up_interruptible_poll(&tty->read_wait, POLLIN); } @@ -1785,12 +1746,6 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, return n_tty_receive_buf_common(tty, cp, fp, count, 1); } -int is_ignored(int sig) -{ - return (sigismember(¤t->blocked, sig) || - current->sighand->action[sig-1].sa.sa_handler == SIG_IGN); -} - /** * n_tty_set_termios - termios data changed * @tty: terminal @@ -1937,7 +1892,6 @@ static int n_tty_open(struct tty_struct *tty) reset_buffer_flags(tty->disc_data); ldata->column = 0; ldata->canon_column = 0; - ldata->minimum_to_wake = 1; ldata->num_overrun = 0; ldata->no_room = 0; ldata->lnext = 0; @@ -2015,7 +1969,7 @@ static int copy_from_read_buf(struct tty_struct *tty, retval = copy_to_user(*b, from, n); n -= retval; is_eof = n == 1 && *from == EOF_CHAR(tty); - tty_audit_add_data(tty, from, n, ldata->icanon); + tty_audit_add_data(tty, from, 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 && @@ -2109,7 +2063,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, ldata->line_start = ldata->read_tail; else ldata->push = 0; - tty_audit_push(tty); + tty_audit_push(); } return 0; } @@ -2200,14 +2154,9 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, minimum = MIN_CHAR(tty); if (minimum) { time = (HZ / 10) * TIME_CHAR(tty); - if (time) - ldata->minimum_to_wake = 1; - else if (!waitqueue_active(&tty->read_wait) || - (ldata->minimum_to_wake > minimum)) - ldata->minimum_to_wake = minimum; } else { timeout = (HZ / 10) * TIME_CHAR(tty); - ldata->minimum_to_wake = minimum = 1; + minimum = 1; } } @@ -2225,19 +2174,15 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, cs = tty->link->ctrl_status; tty->link->ctrl_status = 0; spin_unlock_irq(&tty->link->ctrl_lock); - if (tty_put_user(tty, cs, b++)) { + if (put_user(cs, b)) { retval = -EFAULT; - b--; break; } + b++; nr--; break; } - if (((minimum - (b - buf)) < ldata->minimum_to_wake) && - ((minimum - (b - buf)) >= 1)) - ldata->minimum_to_wake = (minimum - (b - buf)); - done = check_other_done(tty); if (!input_available_p(tty, 0)) { @@ -2275,11 +2220,11 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, /* Deal with packet mode. */ if (packet && b == buf) { - if (tty_put_user(tty, TIOCPKT_DATA, b++)) { + if (put_user(TIOCPKT_DATA, b)) { retval = -EFAULT; - b--; break; } + b++; nr--; } @@ -2303,9 +2248,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, up_read(&tty->termios_rwsem); remove_wait_queue(&tty->read_wait, &wait); - if (!waitqueue_active(&tty->read_wait)) - ldata->minimum_to_wake = minimum; - mutex_unlock(&ldata->atomic_read_lock); if (b - buf) @@ -2417,7 +2359,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, } break_out: remove_wait_queue(&tty->write_wait, &wait); - if (b - buf != nr && tty->fasync) + if (nr && tty->fasync) set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); up_read(&tty->termios_rwsem); return (b - buf) ? b - buf : retval; @@ -2440,7 +2382,6 @@ break_out: static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, poll_table *wait) { - struct n_tty_data *ldata = tty->disc_data; unsigned int mask = 0; poll_wait(file, &tty->read_wait, wait); @@ -2453,12 +2394,6 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, mask |= POLLPRI | POLLIN | POLLRDNORM; if (tty_hung_up_p(file)) mask |= POLLHUP; - if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { - if (MIN_CHAR(tty) && !TIME_CHAR(tty)) - ldata->minimum_to_wake = MIN_CHAR(tty); - else - ldata->minimum_to_wake = 1; - } if (tty->ops->write && !tty_is_writelocked(tty) && tty_chars_in_buffer(tty) < WAKEUP_CHARS && tty_write_room(tty) > 0) @@ -2507,25 +2442,12 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, } } -static void n_tty_fasync(struct tty_struct *tty, int on) -{ - struct n_tty_data *ldata = tty->disc_data; - - if (!waitqueue_active(&tty->read_wait)) { - if (on) - ldata->minimum_to_wake = 1; - else if (!tty->fasync) - ldata->minimum_to_wake = N_TTY_BUF_SIZE; - } -} - -struct tty_ldisc_ops tty_ldisc_N_TTY = { +static struct tty_ldisc_ops n_tty_ops = { .magic = TTY_LDISC_MAGIC, .name = "n_tty", .open = n_tty_open, .close = n_tty_close, .flush_buffer = n_tty_flush_buffer, - .chars_in_buffer = n_tty_chars_in_buffer, .read = n_tty_read, .write = n_tty_write, .ioctl = n_tty_ioctl, @@ -2533,7 +2455,6 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { .poll = n_tty_poll, .receive_buf = n_tty_receive_buf, .write_wakeup = n_tty_write_wakeup, - .fasync = n_tty_fasync, .receive_buf2 = n_tty_receive_buf2, }; @@ -2541,14 +2462,18 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { * n_tty_inherit_ops - inherit N_TTY methods * @ops: struct tty_ldisc_ops where to save N_TTY methods * - * Enables a 'subclass' line discipline to 'inherit' N_TTY - * methods. + * Enables a 'subclass' line discipline to 'inherit' N_TTY methods. */ void n_tty_inherit_ops(struct tty_ldisc_ops *ops) { - *ops = tty_ldisc_N_TTY; + *ops = n_tty_ops; ops->owner = NULL; ops->refcount = ops->flags = 0; } EXPORT_SYMBOL_GPL(n_tty_inherit_ops); + +void __init n_tty_init(void) +{ + tty_register_ldisc(N_TTY, &n_tty_ops); +} diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index b3110040164a..78170e7aa3a3 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -263,8 +263,7 @@ static void pty_set_termios(struct tty_struct *tty, { /* See if packet mode change of state. */ if (tty->link && tty->link->packet) { - int extproc = (old_termios->c_lflag & EXTPROC) | - (tty->termios.c_lflag & EXTPROC); + int extproc = (old_termios->c_lflag & EXTPROC) | L_EXTPROC(tty); int old_flow = ((old_termios->c_iflag & IXON) && (old_termios->c_cc[VSTOP] == '\023') && (old_termios->c_cc[VSTART] == '\021')); @@ -406,13 +405,8 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, if (legacy) { /* We always use new tty termios data so we can do this the easy way .. */ - retval = tty_init_termios(tty); - if (retval) - goto err_deinit_tty; - - retval = tty_init_termios(o_tty); - if (retval) - goto err_free_termios; + tty_init_termios(tty); + tty_init_termios(o_tty); driver->other->ttys[idx] = o_tty; driver->ttys[idx] = tty; @@ -444,12 +438,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, tty->count++; o_tty->count++; return 0; -err_free_termios: - if (legacy) - tty_free_termios(tty); -err_deinit_tty: - deinitialize_tty_struct(o_tty); - free_tty_struct(o_tty); + err_put_module: module_put(driver->other->owner); err: @@ -666,20 +655,13 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver, return tty; } -/* We have no need to install and remove our tty objects as devpts does all - the work for us */ - static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) { return pty_common_install(driver, tty, false); } -static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) -{ -} - /* this is called once with whichever end is closed last */ -static void pty_unix98_shutdown(struct tty_struct *tty) +static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) { devpts_kill_index(tty->driver_data, tty->index); } @@ -697,7 +679,6 @@ static const struct tty_operations ptm_unix98_ops = { .unthrottle = pty_unthrottle, .ioctl = pty_unix98_ioctl, .resize = pty_resize, - .shutdown = pty_unix98_shutdown, .cleanup = pty_cleanup }; @@ -715,7 +696,6 @@ static const struct tty_operations pty_unix98_ops = { .set_termios = pty_set_termios, .start = pty_start, .stop = pty_stop, - .shutdown = pty_unix98_shutdown, .cleanup = pty_cleanup, }; diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 802eac7e561b..0b802cdd70d0 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -643,7 +643,6 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) info->chan = chan; tty_port_init(&info->port); info->port.ops = &rocket_port_ops; - init_completion(&info->close_wait); info->flags &= ~ROCKET_MODE_MASK; switch (pc104[board][line]) { case 422: @@ -960,7 +959,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) tty->alt_speed = 460800; configure_r_port(tty, info, NULL); - if (tty->termios.c_cflag & CBAUD) { + if (C_BAUD(tty)) { sSetDTR(cp); sSetRTS(cp); } @@ -1043,13 +1042,12 @@ static void rp_close(struct tty_struct *tty, struct file *filp) } } spin_lock_irq(&port->lock); - info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); + info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_NORMAL_ACTIVE); tty->closing = 0; spin_unlock_irq(&port->lock); mutex_unlock(&port->mutex); tty_port_tty_set(port, NULL); - complete_all(&info->close_wait); atomic_dec(&rp_num_ports_open); #ifdef ROCKET_DEBUG_OPEN @@ -1086,18 +1084,18 @@ static void rp_set_termios(struct tty_struct *tty, cp = &info->channel; /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { sClrDTR(cp); sClrRTS(cp); } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && (tty->termios.c_cflag & CBAUD)) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { sSetRTS(cp); sSetDTR(cp); } - if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios.c_cflag & CRTSCTS)) + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) rp_start(tty); } @@ -1360,8 +1358,7 @@ static void rp_throttle(struct tty_struct *tty) struct r_port *info = tty->driver_data; #ifdef ROCKET_DEBUG_THROTTLE - printk(KERN_INFO "throttle %s: %d....\n", tty->name, - tty->ldisc.chars_in_buffer(tty)); + printk(KERN_INFO "throttle %s ....\n", tty->name); #endif if (rocket_paranoia_check(info, "rp_throttle")) @@ -1377,8 +1374,7 @@ static void rp_unthrottle(struct tty_struct *tty) { struct r_port *info = tty->driver_data; #ifdef ROCKET_DEBUG_THROTTLE - printk(KERN_INFO "unthrottle %s: %d....\n", tty->name, - tty->ldisc.chars_in_buffer(tty)); + printk(KERN_INFO "unthrottle %s ....\n", tty->name); #endif if (rocket_paranoia_check(info, "rp_unthrottle")) diff --git a/drivers/tty/rocket_int.h b/drivers/tty/rocket_int.h index 67e0f1e778a2..ef1e1be6b26d 100644 --- a/drivers/tty/rocket_int.h +++ b/drivers/tty/rocket_int.h @@ -1144,7 +1144,6 @@ struct r_port { int read_status_mask; int cps; - struct completion close_wait; /* Not yet matching the core */ spinlock_t slock; struct mutex write_mtx; }; diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index 0982c1a44187..9587ed1242fe 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -976,10 +976,8 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_speed(info, tty); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) rs_start(tty); - } /* @@ -1030,7 +1028,6 @@ static void rs_close(struct tty_struct *tty, struct file *filp) local_irq_restore(flags); return; } - port->flags |= ASYNC_CLOSING; /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. @@ -1054,23 +1051,13 @@ static void rs_close(struct tty_struct *tty, struct file *filp) tty_ldisc_flush(tty); tty->closing = 0; tty_port_tty_set(&info->tport, NULL); -#warning "This is not and has never been valid so fix it" -#if 0 - if (tty->ldisc.num != ldiscs[N_TTY].num) { - if (tty->ldisc.close) - (tty->ldisc.close)(tty); - tty->ldisc = ldiscs[N_TTY]; - tty->termios.c_line = N_TTY; - if (tty->ldisc.open) - (tty->ldisc.open)(tty); - } -#endif + if (port->blocked_open) { if (port->close_delay) msleep_interruptible(jiffies_to_msecs(port->close_delay)); wake_up_interruptible(&port->open_wait); } - port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + port->flags &= ~ASYNC_NORMAL_ACTIVE; local_irq_restore(flags); } diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index c9720a97a977..8031e428894f 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -597,6 +597,7 @@ static void univ8250_console_write(struct console *co, const char *s, static int univ8250_console_setup(struct console *co, char *options) { struct uart_port *port; + int retval; /* * Check whether an invalid uart number has been specified, and @@ -609,7 +610,10 @@ static int univ8250_console_setup(struct console *co, char *options) /* link port to console */ port->cons = co; - return serial8250_console_setup(port, options, false); + retval = serial8250_console_setup(port, options, false); + if (retval != 0) + port->cons = NULL; + return retval; } /** diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 8d262bce97e4..0bd3c6baa300 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1412,81 +1412,85 @@ static void serial8250_enable_ms(struct uart_port *port) serial8250_rpm_put(up); } +static void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr) +{ + struct uart_port *port = &up->port; + unsigned char ch; + char flag = TTY_NORMAL; + + if (likely(lsr & UART_LSR_DR)) + ch = serial_in(up, UART_RX); + else + /* + * Intel 82571 has a Serial Over Lan device that will + * set UART_LSR_BI without setting UART_LSR_DR when + * it receives a break. To avoid reading from the + * receive buffer without UART_LSR_DR bit set, we + * just force the read character to be 0 + */ + ch = 0; + + port->icount.rx++; + + lsr |= up->lsr_saved_flags; + up->lsr_saved_flags = 0; + + if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { + if (lsr & UART_LSR_BI) { + lsr &= ~(UART_LSR_FE | UART_LSR_PE); + port->icount.brk++; + /* + * We do the SysRQ and SAK checking + * here because otherwise the break + * may get masked by ignore_status_mask + * or read_status_mask. + */ + if (uart_handle_break(port)) + return; + } else if (lsr & UART_LSR_PE) + port->icount.parity++; + else if (lsr & UART_LSR_FE) + port->icount.frame++; + if (lsr & UART_LSR_OE) + port->icount.overrun++; + + /* + * Mask off conditions which should be ignored. + */ + lsr &= port->read_status_mask; + + if (lsr & UART_LSR_BI) { + DEBUG_INTR("handling break...."); + flag = TTY_BREAK; + } else if (lsr & UART_LSR_PE) + flag = TTY_PARITY; + else if (lsr & UART_LSR_FE) + flag = TTY_FRAME; + } + if (uart_handle_sysrq_char(port, ch)) + return; + + uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); +} + /* * serial8250_rx_chars: processes according to the passed in LSR * value, and returns the remaining LSR bits not handled * by this Rx routine. */ -unsigned char -serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) +unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) { struct uart_port *port = &up->port; - unsigned char ch; int max_count = 256; - char flag; do { - if (likely(lsr & UART_LSR_DR)) - ch = serial_in(up, UART_RX); - else - /* - * Intel 82571 has a Serial Over Lan device that will - * set UART_LSR_BI without setting UART_LSR_DR when - * it receives a break. To avoid reading from the - * receive buffer without UART_LSR_DR bit set, we - * just force the read character to be 0 - */ - ch = 0; - - flag = TTY_NORMAL; - port->icount.rx++; - - lsr |= up->lsr_saved_flags; - up->lsr_saved_flags = 0; - - if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { - if (lsr & UART_LSR_BI) { - lsr &= ~(UART_LSR_FE | UART_LSR_PE); - port->icount.brk++; - /* - * We do the SysRQ and SAK checking - * here because otherwise the break - * may get masked by ignore_status_mask - * or read_status_mask. - */ - if (uart_handle_break(port)) - goto ignore_char; - } else if (lsr & UART_LSR_PE) - port->icount.parity++; - else if (lsr & UART_LSR_FE) - port->icount.frame++; - if (lsr & UART_LSR_OE) - port->icount.overrun++; - - /* - * Mask off conditions which should be ignored. - */ - lsr &= port->read_status_mask; - - if (lsr & UART_LSR_BI) { - DEBUG_INTR("handling break...."); - flag = TTY_BREAK; - } else if (lsr & UART_LSR_PE) - flag = TTY_PARITY; - else if (lsr & UART_LSR_FE) - flag = TTY_FRAME; - } - if (uart_handle_sysrq_char(port, ch)) - goto ignore_char; - - uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); - -ignore_char: + serial8250_read_char(up, lsr); + if (--max_count == 0) + break; lsr = serial_in(up, UART_LSR); - } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0)); - spin_unlock(&port->lock); + } while (lsr & (UART_LSR_DR | UART_LSR_BI)); + tty_flip_buffer_push(&port->state->port); - spin_lock(&port->lock); return lsr; } EXPORT_SYMBOL_GPL(serial8250_rx_chars); @@ -1519,11 +1523,9 @@ void serial8250_tx_chars(struct uart_8250_port *up) port->icount.tx++; if (uart_circ_empty(xmit)) break; - if (up->capabilities & UART_CAP_HFIFO) { - if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) != - BOTH_EMPTY) - break; - } + if ((up->capabilities & UART_CAP_HFIFO) && + (serial_in(up, UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY) + break; } while (--count > 0); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) @@ -2084,8 +2086,12 @@ void serial8250_do_shutdown(struct uart_port *port) /* * Disable interrupts from this port */ + spin_lock_irqsave(&port->lock, flags); up->ier = 0; serial_port_out(port, UART_IER, 0); + spin_unlock_irqrestore(&port->lock, flags); + + synchronize_irq(port->irq); if (up->dma) serial8250_release_dma(up); @@ -2745,8 +2751,7 @@ serial8250_verify_port(struct uart_port *port, struct serial_struct *ser) return 0; } -static const char * -serial8250_type(struct uart_port *port) +static const char *serial8250_type(struct uart_port *port) { int type = port->type; diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index f13f2ebd215b..c0172bf54a9b 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -1413,9 +1413,8 @@ rs_stop(struct tty_struct *tty) xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop); - if (tty->termios.c_iflag & IXON ) { + if (I_IXON(tty)) xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); - } *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; local_irq_restore(flags); @@ -1436,9 +1435,8 @@ rs_start(struct tty_struct *tty) info->xmit.tail,SERIAL_XMIT_SIZE))); xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); - if (tty->termios.c_iflag & IXON ) { + if (I_IXON(tty)) xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); - } *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; if (!info->uses_dma_out && @@ -2968,7 +2966,7 @@ static int rs_raw_write(struct tty_struct *tty, local_save_flags(flags); DFLOW(DEBUG_LOG(info->line, "write count %i ", count)); - DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty))); + DFLOW(DEBUG_LOG(info->line, "ldisc\n")); /* The local_irq_disable/restore_flags pairs below are needed @@ -3161,13 +3159,12 @@ rs_throttle(struct tty_struct * tty) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; #ifdef SERIAL_DEBUG_THROTTLE - printk("throttle %s: %lu....\n", tty_name(tty), - (unsigned long)tty->ldisc.chars_in_buffer(tty)); + printk("throttle %s ....\n", tty_name(tty)); #endif - DFLOW(DEBUG_LOG(info->line,"rs_throttle %lu\n", tty->ldisc.chars_in_buffer(tty))); + DFLOW(DEBUG_LOG(info->line,"rs_throttle\n")); /* Do RTS before XOFF since XOFF might take some time */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { /* Turn off RTS line */ e100_rts(info, 0); } @@ -3181,13 +3178,12 @@ rs_unthrottle(struct tty_struct * tty) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; #ifdef SERIAL_DEBUG_THROTTLE - printk("unthrottle %s: %lu....\n", tty_name(tty), - (unsigned long)tty->ldisc.chars_in_buffer(tty)); + printk("unthrottle %s ....\n", tty_name(tty)); #endif - DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc %d\n", tty->ldisc.chars_in_buffer(tty))); + DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc\n")); DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count)); /* Do RTS before XOFF since XOFF might take some time */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { /* Assert RTS line */ e100_rts(info, 1); } @@ -3555,8 +3551,7 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_speed(info); /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) rs_start(tty); } @@ -3615,7 +3610,6 @@ rs_close(struct tty_struct *tty, struct file * filp) local_irq_restore(flags); return; } - info->port.flags |= ASYNC_CLOSING; /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. @@ -3654,7 +3648,7 @@ rs_close(struct tty_struct *tty, struct file * filp) schedule_timeout_interruptible(info->port.close_delay); wake_up_interruptible(&info->port.open_wait); } - info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + info->port.flags &= ~ASYNC_NORMAL_ACTIVE; local_irq_restore(flags); /* port closed */ @@ -3767,9 +3761,8 @@ block_til_ready(struct tty_struct *tty, struct file * filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) { - do_clocal = 1; - } + if (C_CLOCAL(tty)) + do_clocal = 1; /* * Block waiting for the carrier detect and the line to become diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c index 524e86ab3cae..00cac10ae75a 100644 --- a/drivers/tty/serial/jsm/jsm_tty.c +++ b/drivers/tty/serial/jsm/jsm_tty.c @@ -569,8 +569,7 @@ void jsm_input(struct jsm_channel *ch) *If the device is not open, or CREAD is off, flush *input data and return immediately. */ - if (!tp || - !(tp->termios.c_cflag & CREAD) ) { + if (!tp || !C_CREAD(tp)) { jsm_dbg(READ, &ch->ch_bd->pci_dev, "input. dropping %d bytes on port %d...\n", diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index b1f54ab1818c..85829f8568e7 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -171,14 +171,12 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, */ uart_change_speed(tty, state, NULL); - if (init_hw) { - /* - * Setup the RTS and DTR signals once the - * port is open and ready to respond. - */ - if (tty->termios.c_cflag & CBAUD) - uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); - } + /* + * Setup the RTS and DTR signals once the + * port is open and ready to respond. + */ + if (init_hw && C_BAUD(tty)) + uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); } /* @@ -240,7 +238,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) if (uart_console(uport) && tty) uport->cons->cflag = tty->termios.c_cflag; - if (!tty || (tty->termios.c_cflag & HUPCL)) + if (!tty || C_HUPCL(tty)) uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); uart_port_shutdown(port); @@ -485,12 +483,15 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, spin_unlock_irq(&uport->lock); } -static inline int __uart_put_char(struct uart_port *port, - struct circ_buf *circ, unsigned char c) +static int uart_put_char(struct tty_struct *tty, unsigned char c) { + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->uart_port; + struct circ_buf *circ; unsigned long flags; int ret = 0; + circ = &state->xmit; if (!circ->buf) return 0; @@ -504,13 +505,6 @@ static inline int __uart_put_char(struct uart_port *port, return ret; } -static int uart_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct uart_state *state = tty->driver_data; - - return __uart_put_char(state->uart_port, &state->xmit, ch); -} - static void uart_flush_chars(struct tty_struct *tty) { uart_start(tty); @@ -639,7 +633,7 @@ static void uart_throttle(struct tty_struct *tty) if (I_IXOFF(tty)) mask |= UPSTAT_AUTOXOFF; - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) mask |= UPSTAT_AUTORTS; if (port->status & mask) { @@ -647,11 +641,11 @@ static void uart_throttle(struct tty_struct *tty) mask &= ~port->status; } - if (mask & UPSTAT_AUTOXOFF) - uart_send_xchar(tty, STOP_CHAR(tty)); - if (mask & UPSTAT_AUTORTS) uart_clear_mctrl(port, TIOCM_RTS); + + if (mask & UPSTAT_AUTOXOFF) + uart_send_xchar(tty, STOP_CHAR(tty)); } static void uart_unthrottle(struct tty_struct *tty) @@ -662,7 +656,7 @@ static void uart_unthrottle(struct tty_struct *tty) if (I_IXOFF(tty)) mask |= UPSTAT_AUTOXOFF; - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) mask |= UPSTAT_AUTORTS; if (port->status & mask) { @@ -670,21 +664,25 @@ static void uart_unthrottle(struct tty_struct *tty) mask &= ~port->status; } - if (mask & UPSTAT_AUTOXOFF) - uart_send_xchar(tty, START_CHAR(tty)); - if (mask & UPSTAT_AUTORTS) uart_set_mctrl(port, TIOCM_RTS); + + if (mask & UPSTAT_AUTOXOFF) + uart_send_xchar(tty, START_CHAR(tty)); } -static void do_uart_get_info(struct tty_port *port, - struct serial_struct *retinfo) +static void uart_get_info(struct tty_port *port, struct serial_struct *retinfo) { struct uart_state *state = container_of(port, struct uart_state, port); struct uart_port *uport = state->uart_port; memset(retinfo, 0, sizeof(*retinfo)); + /* + * Ensure the state we copy is consistent and no hardware changes + * occur as we go + */ + mutex_lock(&port->mutex); retinfo->type = uport->type; retinfo->line = uport->line; retinfo->port = uport->iobase; @@ -703,15 +701,6 @@ static void do_uart_get_info(struct tty_port *port, retinfo->io_type = uport->iotype; retinfo->iomem_reg_shift = uport->regshift; retinfo->iomem_base = (void *)(unsigned long)uport->mapbase; -} - -static void uart_get_info(struct tty_port *port, - struct serial_struct *retinfo) -{ - /* Ensure the state we copy is consistent and no hardware changes - occur as we go */ - mutex_lock(&port->mutex); - do_uart_get_info(port, retinfo); mutex_unlock(&port->mutex); } @@ -719,6 +708,7 @@ static int uart_get_info_user(struct tty_port *port, struct serial_struct __user *retinfo) { struct serial_struct tmp; + uart_get_info(port, &tmp); if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) @@ -1391,8 +1381,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) uport = state->uart_port; port = &state->port; - - pr_debug("uart_close(%d) called\n", uport ? uport->line : -1); + pr_debug("uart_close(%d) called\n", tty->index); if (!port->count || tty_port_close_start(port, tty, filp) == 0) return; @@ -1434,7 +1423,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp) * Wake up anyone trying to open this port. */ clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); - clear_bit(ASYNCB_CLOSING, &port->flags); spin_unlock_irq(&port->lock); wake_up_interruptible(&port->open_wait); @@ -1510,7 +1498,7 @@ static void uart_hangup(struct tty_struct *tty) struct tty_port *port = &state->port; unsigned long flags; - pr_debug("uart_hangup(%d)\n", state->uart_port->line); + pr_debug("uart_hangup(%d)\n", tty->index); mutex_lock(&port->mutex); if (port->flags & ASYNC_NORMAL_ACTIVE) { @@ -1591,7 +1579,7 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) */ static int uart_open(struct tty_struct *tty, struct file *filp) { - struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state; + struct uart_driver *drv = tty->driver->driver_state; int retval, line = tty->index; struct uart_state *state = drv->state + line; struct tty_port *port = &state->port; @@ -1633,15 +1621,12 @@ static int uart_open(struct tty_struct *tty, struct file *filp) /* * If we succeeded, wait until the port is ready. */ +err_unlock: mutex_unlock(&port->mutex); if (retval == 0) retval = tty_port_block_til_ready(port, tty, filp); - end: return retval; -err_unlock: - mutex_unlock(&port->mutex); - goto end; } static const char *uart_type(struct uart_port *port) @@ -1700,17 +1685,13 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i) seq_printf(m, " tx:%d rx:%d", uport->icount.tx, uport->icount.rx); if (uport->icount.frame) - seq_printf(m, " fe:%d", - uport->icount.frame); + seq_printf(m, " fe:%d", uport->icount.frame); if (uport->icount.parity) - seq_printf(m, " pe:%d", - uport->icount.parity); + seq_printf(m, " pe:%d", uport->icount.parity); if (uport->icount.brk) - seq_printf(m, " brk:%d", - uport->icount.brk); + seq_printf(m, " brk:%d", uport->icount.brk); if (uport->icount.overrun) - seq_printf(m, " oe:%d", - uport->icount.overrun); + seq_printf(m, " oe:%d", uport->icount.overrun); #define INFOBIT(bit, str) \ if (uport->mctrl & (bit)) \ @@ -1745,8 +1726,7 @@ static int uart_proc_show(struct seq_file *m, void *v) struct uart_driver *drv = ttydrv->driver_state; int i; - seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n", - "", "", ""); + seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n", "", "", ""); for (i = 0; i < drv->nr; i++) uart_line_info(m, drv, i); return 0; diff --git a/drivers/tty/serial/serial_ks8695.c b/drivers/tty/serial/serial_ks8695.c index b4decf8787de..57f152394af5 100644 --- a/drivers/tty/serial/serial_ks8695.c +++ b/drivers/tty/serial/serial_ks8695.c @@ -554,7 +554,7 @@ static struct uart_port ks8695uart_ports[SERIAL_KS8695_NR] = { .uartclk = KS8695_CLOCK_RATE * 16, .fifosize = 16, .ops = &ks8695uart_pops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, } }; diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 6188059fd523..f5476e270734 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -2363,7 +2363,7 @@ static void mgsl_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) mgsl_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->irq_spinlock,flags); info->serial_signals &= ~SerialSignal_RTS; usc_set_serial_signals(info); @@ -2397,7 +2397,7 @@ static void mgsl_unthrottle(struct tty_struct * tty) mgsl_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->irq_spinlock,flags); info->serial_signals |= SerialSignal_RTS; usc_set_serial_signals(info); @@ -3039,30 +3039,25 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio mgsl_change_params(info); /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); spin_lock_irqsave(&info->irq_spinlock,flags); usc_set_serial_signals(info); spin_unlock_irqrestore(&info->irq_spinlock,flags); } - + /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->serial_signals |= SerialSignal_RTS; - } spin_lock_irqsave(&info->irq_spinlock,flags); usc_set_serial_signals(info); spin_unlock_irqrestore(&info->irq_spinlock,flags); } - + /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + if (old_termios->c_cflag & CRTSCTS && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; mgsl_start(tty); } @@ -3281,7 +3276,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) + if (C_CLOCAL(tty)) do_clocal = true; /* Wait for carrier detect and the line to become diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index 5505ea842179..c0a2f5a1b1c2 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -774,8 +774,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_params(info); /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { info->signals &= ~(SerialSignal_RTS | SerialSignal_DTR); spin_lock_irqsave(&info->lock,flags); set_signals(info); @@ -783,21 +782,17 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { info->signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->signals |= SerialSignal_RTS; - } spin_lock_irqsave(&info->lock,flags); set_signals(info); spin_unlock_irqrestore(&info->lock,flags); } /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; tx_release(tty); } @@ -1362,7 +1357,7 @@ static void throttle(struct tty_struct * tty) DBGINFO(("%s throttle\n", info->device_name)); if (I_IXOFF(tty)) send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->signals &= ~SerialSignal_RTS; set_signals(info); @@ -1387,7 +1382,7 @@ static void unthrottle(struct tty_struct * tty) else send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->signals |= SerialSignal_RTS; set_signals(info); @@ -3280,7 +3275,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) + if (C_CLOCAL(tty)) do_clocal = true; /* Wait for carrier detect and the line to become diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index fb00a06dfa4b..4b314b63a2ed 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -871,8 +871,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_params(info); /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); spin_lock_irqsave(&info->lock,flags); set_signals(info); @@ -880,21 +879,17 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->serial_signals |= SerialSignal_RTS; - } spin_lock_irqsave(&info->lock,flags); set_signals(info); spin_unlock_irqrestore(&info->lock,flags); } /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + if (old_termios->c_cflag & CRTSCTS && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; tx_release(tty); } @@ -1472,7 +1467,7 @@ static void throttle(struct tty_struct * tty) if (I_IXOFF(tty)) send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->serial_signals &= ~SerialSignal_RTS; set_signals(info); @@ -1501,7 +1496,7 @@ static void unthrottle(struct tty_struct * tty) send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->serial_signals |= SerialSignal_RTS; set_signals(info); @@ -3297,7 +3292,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) + if (C_CLOCAL(tty)) do_clocal = true; /* Wait for carrier detect and the line to become diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 3d245cd3d8e6..66d53fcf4da0 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -14,16 +14,23 @@ #include <linux/tty.h> struct tty_audit_buf { - atomic_t count; struct mutex mutex; /* Protects all data below */ - int major, minor; /* The TTY which the data is from */ + dev_t dev; /* The TTY which the data is from */ unsigned icanon:1; size_t valid; unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */ }; -static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor, - unsigned icanon) +static struct tty_audit_buf *tty_audit_buf_ref(void) +{ + struct tty_audit_buf *buf; + + buf = current->signal->tty_audit_buf; + WARN_ON(buf == ERR_PTR(-ESRCH)); + return buf; +} + +static struct tty_audit_buf *tty_audit_buf_alloc(void) { struct tty_audit_buf *buf; @@ -33,11 +40,9 @@ static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor, buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL); if (!buf->data) goto err_buf; - atomic_set(&buf->count, 1); mutex_init(&buf->mutex); - buf->major = major; - buf->minor = minor; - buf->icanon = icanon; + buf->dev = MKDEV(0, 0); + buf->icanon = 0; buf->valid = 0; return buf; @@ -54,13 +59,7 @@ static void tty_audit_buf_free(struct tty_audit_buf *buf) kfree(buf); } -static void tty_audit_buf_put(struct tty_audit_buf *buf) -{ - if (atomic_dec_and_test(&buf->count)) - tty_audit_buf_free(buf); -} - -static void tty_audit_log(const char *description, int major, int minor, +static void tty_audit_log(const char *description, dev_t dev, unsigned char *data, size_t size) { struct audit_buffer *ab; @@ -76,7 +75,7 @@ static void tty_audit_log(const char *description, int major, int minor, audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d" " minor=%d comm=", description, pid, uid, - loginuid, sessionid, major, minor); + loginuid, sessionid, MAJOR(dev), MINOR(dev)); get_task_comm(name, tsk); audit_log_untrustedstring(ab, name); audit_log_format(ab, " data="); @@ -99,7 +98,7 @@ static void tty_audit_buf_push(struct tty_audit_buf *buf) buf->valid = 0; return; } - tty_audit_log("tty", buf->major, buf->minor, buf->data, buf->valid); + tty_audit_log("tty", buf->dev, buf->data, buf->valid); buf->valid = 0; } @@ -108,21 +107,20 @@ static void tty_audit_buf_push(struct tty_audit_buf *buf) * * Make sure all buffered data is written out and deallocate the buffer. * Only needs to be called if current->signal->tty_audit_buf != %NULL. + * + * The process is single-threaded at this point; no other threads share + * current->signal. */ void tty_audit_exit(void) { struct tty_audit_buf *buf; - buf = current->signal->tty_audit_buf; - current->signal->tty_audit_buf = NULL; + buf = xchg(¤t->signal->tty_audit_buf, ERR_PTR(-ESRCH)); if (!buf) return; - mutex_lock(&buf->mutex); tty_audit_buf_push(buf); - mutex_unlock(&buf->mutex); - - tty_audit_buf_put(buf); + tty_audit_buf_free(buf); } /** @@ -133,7 +131,6 @@ void tty_audit_exit(void) void tty_audit_fork(struct signal_struct *sig) { sig->audit_tty = current->signal->audit_tty; - sig->audit_tty_log_passwd = current->signal->audit_tty_log_passwd; } /** @@ -141,123 +138,68 @@ void tty_audit_fork(struct signal_struct *sig) */ void tty_audit_tiocsti(struct tty_struct *tty, char ch) { - struct tty_audit_buf *buf; - int major, minor, should_audit; - unsigned long flags; + dev_t dev; - spin_lock_irqsave(¤t->sighand->siglock, flags); - should_audit = current->signal->audit_tty; - buf = current->signal->tty_audit_buf; - if (buf) - atomic_inc(&buf->count); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - - major = tty->driver->major; - minor = tty->driver->minor_start + tty->index; - if (buf) { - mutex_lock(&buf->mutex); - if (buf->major == major && buf->minor == minor) - tty_audit_buf_push(buf); - mutex_unlock(&buf->mutex); - tty_audit_buf_put(buf); - } + dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; + if (tty_audit_push()) + return; - if (should_audit && audit_enabled) { + if (audit_enabled) { kuid_t auid; unsigned int sessionid; auid = audit_get_loginuid(current); sessionid = audit_get_sessionid(current); - tty_audit_log("ioctl=TIOCSTI", major, minor, &ch, 1); + tty_audit_log("ioctl=TIOCSTI", dev, &ch, 1); } } /** - * tty_audit_push_current - Flush current's pending audit data + * tty_audit_push - Flush current's pending audit data * - * Try to lock sighand and get a reference to the tty audit buffer if available. - * Flush the buffer or return an appropriate error code. + * Returns 0 if success, -EPERM if tty audit is disabled */ -int tty_audit_push_current(void) +int tty_audit_push(void) { - struct tty_audit_buf *buf = ERR_PTR(-EPERM); - struct task_struct *tsk = current; - unsigned long flags; + struct tty_audit_buf *buf; - if (!lock_task_sighand(tsk, &flags)) - return -ESRCH; + if (~current->signal->audit_tty & AUDIT_TTY_ENABLE) + return -EPERM; - if (tsk->signal->audit_tty) { - buf = tsk->signal->tty_audit_buf; - if (buf) - atomic_inc(&buf->count); + buf = tty_audit_buf_ref(); + if (!IS_ERR_OR_NULL(buf)) { + mutex_lock(&buf->mutex); + tty_audit_buf_push(buf); + mutex_unlock(&buf->mutex); } - unlock_task_sighand(tsk, &flags); - - /* - * Return 0 when signal->audit_tty set - * but tsk->signal->tty_audit_buf == NULL. - */ - if (!buf || IS_ERR(buf)) - return PTR_ERR(buf); - - mutex_lock(&buf->mutex); - tty_audit_buf_push(buf); - mutex_unlock(&buf->mutex); - - tty_audit_buf_put(buf); return 0; } /** * tty_audit_buf_get - Get an audit buffer. * - * Get an audit buffer for @tty, allocate it if necessary. Return %NULL - * if TTY auditing is disabled or out of memory. Otherwise, return a new - * reference to the buffer. + * Get an audit buffer, allocate it if necessary. Return %NULL + * if out of memory or ERR_PTR(-ESRCH) if tty_audit_exit() has already + * occurred. Otherwise, return a new reference to the buffer. */ -static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, - unsigned icanon) +static struct tty_audit_buf *tty_audit_buf_get(void) { - struct tty_audit_buf *buf, *buf2; - unsigned long flags; - - buf = NULL; - buf2 = NULL; - spin_lock_irqsave(¤t->sighand->siglock, flags); - if (likely(!current->signal->audit_tty)) - goto out; - buf = current->signal->tty_audit_buf; - if (buf) { - atomic_inc(&buf->count); - goto out; - } - spin_unlock_irqrestore(¤t->sighand->siglock, flags); + struct tty_audit_buf *buf; - buf2 = tty_audit_buf_alloc(tty->driver->major, - tty->driver->minor_start + tty->index, - icanon); - if (buf2 == NULL) { + buf = tty_audit_buf_ref(); + if (buf) + return buf; + + buf = tty_audit_buf_alloc(); + if (buf == NULL) { audit_log_lost("out of memory in TTY auditing"); return NULL; } - spin_lock_irqsave(¤t->sighand->siglock, flags); - if (!current->signal->audit_tty) - goto out; - buf = current->signal->tty_audit_buf; - if (!buf) { - current->signal->tty_audit_buf = buf2; - buf = buf2; - buf2 = NULL; - } - atomic_inc(&buf->count); - /* Fall through */ - out: - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - if (buf2) - tty_audit_buf_free(buf2); - return buf; + /* Race to use this buffer, free it if another wins */ + if (cmpxchg(¤t->signal->tty_audit_buf, NULL, buf) != NULL) + tty_audit_buf_free(buf); + return tty_audit_buf_ref(); } /** @@ -265,39 +207,36 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, * * Audit @data of @size from @tty, if necessary. */ -void tty_audit_add_data(struct tty_struct *tty, const void *data, - size_t size, unsigned icanon) +void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) { struct tty_audit_buf *buf; - int major, minor; - int audit_log_tty_passwd; - unsigned long flags; + unsigned int icanon = !!L_ICANON(tty); + unsigned int audit_tty; + dev_t dev; - if (unlikely(size == 0)) + audit_tty = READ_ONCE(current->signal->audit_tty); + if (~audit_tty & AUDIT_TTY_ENABLE) return; - spin_lock_irqsave(¤t->sighand->siglock, flags); - audit_log_tty_passwd = current->signal->audit_tty_log_passwd; - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - if (!audit_log_tty_passwd && icanon && !L_ECHO(tty)) + if (unlikely(size == 0)) return; if (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_MASTER) return; - buf = tty_audit_buf_get(tty, icanon); - if (!buf) + if ((~audit_tty & AUDIT_TTY_LOG_PASSWD) && icanon && !L_ECHO(tty)) + return; + + buf = tty_audit_buf_get(); + if (IS_ERR_OR_NULL(buf)) return; mutex_lock(&buf->mutex); - major = tty->driver->major; - minor = tty->driver->minor_start + tty->index; - if (buf->major != major || buf->minor != minor - || buf->icanon != icanon) { + dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; + if (buf->dev != dev || buf->icanon != icanon) { tty_audit_buf_push(buf); - buf->major = major; - buf->minor = minor; + buf->dev = dev; buf->icanon = icanon; } do { @@ -314,38 +253,4 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, tty_audit_buf_push(buf); } while (size != 0); mutex_unlock(&buf->mutex); - tty_audit_buf_put(buf); -} - -/** - * tty_audit_push - Push buffered data out - * - * Make sure no audit data is pending for @tty on the current process. - */ -void tty_audit_push(struct tty_struct *tty) -{ - struct tty_audit_buf *buf; - unsigned long flags; - - spin_lock_irqsave(¤t->sighand->siglock, flags); - if (likely(!current->signal->audit_tty)) { - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - return; - } - buf = current->signal->tty_audit_buf; - if (buf) - atomic_inc(&buf->count); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - - if (buf) { - int major, minor; - - major = tty->driver->major; - minor = tty->driver->minor_start + tty->index; - mutex_lock(&buf->mutex); - if (buf->major == major && buf->minor == minor) - tty_audit_buf_push(buf); - mutex_unlock(&buf->mutex); - tty_audit_buf_put(buf); - } } diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 3cd31e0d4bd9..a946e49a2626 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -435,25 +435,42 @@ int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, } EXPORT_SYMBOL_GPL(tty_prepare_flip_string); +/** + * tty_ldisc_receive_buf - forward data to line discipline + * @ld: line discipline to process input + * @p: char buffer + * @f: TTY_* flags buffer + * @count: number of bytes to process + * + * Callers other than flush_to_ldisc() need to exclude the kworker + * from concurrent use of the line discipline, see paste_selection(). + * + * Returns the number of bytes not processed + */ +int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, + char *f, int count) +{ + if (ld->ops->receive_buf2) + count = ld->ops->receive_buf2(ld->tty, p, f, count); + else { + count = min_t(int, count, ld->tty->receive_room); + if (count && ld->ops->receive_buf) + ld->ops->receive_buf(ld->tty, p, f, count); + } + return count; +} +EXPORT_SYMBOL_GPL(tty_ldisc_receive_buf); static int -receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) +receive_buf(struct tty_ldisc *ld, struct tty_buffer *head, int count) { - struct tty_ldisc *disc = tty->ldisc; unsigned char *p = char_buf_ptr(head, head->read); char *f = NULL; if (~head->flags & TTYB_NORMAL) f = flag_buf_ptr(head, head->read); - if (disc->ops->receive_buf2) - count = disc->ops->receive_buf2(tty, p, f, count); - else { - count = min_t(int, count, tty->receive_room); - if (count && disc->ops->receive_buf) - disc->ops->receive_buf(tty, p, f, count); - } - return count; + return tty_ldisc_receive_buf(ld, p, f, count); } /** @@ -514,7 +531,7 @@ static void flush_to_ldisc(struct work_struct *work) continue; } - count = receive_buf(tty, head, count); + count = receive_buf(disc, head, count); if (!count) break; head->read += count; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 5cec01c75691..8d26ed79bb4c 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -123,7 +123,8 @@ struct ktermios tty_std_termios = { /* for the benefit of tty drivers */ ECHOCTL | ECHOKE | IEXTEN, .c_cc = INIT_C_CC, .c_ispeed = 38400, - .c_ospeed = 38400 + .c_ospeed = 38400, + /* .c_line = N_TTY, */ }; EXPORT_SYMBOL(tty_std_termios); @@ -134,13 +135,8 @@ EXPORT_SYMBOL(tty_std_termios); LIST_HEAD(tty_drivers); /* linked list of tty drivers */ -/* Mutex to protect creating and releasing a tty. This is shared with - vt.c for deeply disgusting hack reasons */ +/* Mutex to protect creating and releasing a tty */ DEFINE_MUTEX(tty_mutex); -EXPORT_SYMBOL(tty_mutex); - -/* Spinlock to protect the tty->tty_files list */ -DEFINE_SPINLOCK(tty_files_lock); static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); @@ -168,10 +164,9 @@ static void release_tty(struct tty_struct *tty, int idx); * Locking: none. Must be called after tty is definitely unused */ -void free_tty_struct(struct tty_struct *tty) +static void free_tty_struct(struct tty_struct *tty) { - if (!tty) - return; + tty_ldisc_deinit(tty); put_device(tty->dev); kfree(tty->write_buf); tty->magic = 0xDEADDEAD; @@ -204,9 +199,9 @@ void tty_add_file(struct tty_struct *tty, struct file *file) priv->tty = tty; priv->file = file; - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_add(&priv->list, &tty->tty_files); - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); } /** @@ -227,10 +222,11 @@ void tty_free_file(struct file *file) static void tty_del_file(struct file *file) { struct tty_file_private *priv = file->private_data; + struct tty_struct *tty = priv->tty; - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_del(&priv->list); - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); tty_free_file(file); } @@ -288,11 +284,11 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) struct list_head *p; int count = 0; - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_for_each(p, &tty->tty_files) { count++; } - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); if (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_SLAVE && tty->link && tty->link->count) @@ -383,6 +379,12 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) EXPORT_SYMBOL_GPL(tty_find_polling_driver); #endif +static int is_ignored(int sig) +{ + return (sigismember(¤t->blocked, sig) || + current->sighand->action[sig-1].sa.sa_handler == SIG_IGN); +} + /** * tty_check_change - check for POSIX terminal changes * @tty: tty to check @@ -466,6 +468,11 @@ static long hung_up_tty_compat_ioctl(struct file *file, return cmd == TIOCSPGRP ? -ENOTTY : -EIO; } +static int hung_up_tty_fasync(int fd, struct file *file, int on) +{ + return -ENOTTY; +} + static const struct file_operations tty_fops = { .llseek = no_llseek, .read = tty_read, @@ -498,6 +505,7 @@ static const struct file_operations hung_up_tty_fops = { .unlocked_ioctl = hung_up_tty_ioctl, .compat_ioctl = hung_up_tty_compat_ioctl, .release = tty_release, + .fasync = hung_up_tty_fasync, }; static DEFINE_SPINLOCK(redirect_lock); @@ -709,7 +717,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) workqueue with the lock held */ check_tty_count(tty, "tty_hangup"); - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); /* This breaks for file handles being sent over AF_UNIX sockets ? */ list_for_each_entry(priv, &tty->tty_files, list) { filp = priv->file; @@ -721,14 +729,14 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) __tty_fasync(-1, filp, 0); /* can't block */ filp->f_op = &hung_up_tty_fops; } - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); refs = tty_signal_session_leader(tty, exit_session); /* Account for the p->signal references we killed */ while (refs--) tty_kref_put(tty); - tty_ldisc_hangup(tty); + tty_ldisc_hangup(tty, cons_filp != NULL); spin_lock_irq(&tty->ctrl_lock); clear_bit(TTY_THROTTLED, &tty->flags); @@ -753,10 +761,9 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) } else if (tty->ops->hangup) tty->ops->hangup(tty); /* - * We don't want to have driver/ldisc interactions beyond - * the ones we did here. The driver layer expects no - * calls after ->hangup() from the ldisc side. However we - * can't yet guarantee all that. + * We don't want to have driver/ldisc interactions beyond the ones + * we did here. The driver layer expects no calls after ->hangup() + * from the ldisc side, which is now guaranteed. */ set_bit(TTY_HUPPED, &tty->flags); tty_unlock(tty); @@ -1069,6 +1076,8 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, /* We want to wait for the line discipline to sort out in this situation */ ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_read(file, buf, count, ppos); if (ld->ops->read) i = ld->ops->read(tty, file, buf, count); else @@ -1243,6 +1252,8 @@ static ssize_t tty_write(struct file *file, const char __user *buf, if (tty->ops->write_room == NULL) tty_err(tty, "missing write_room method\n"); ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_write(file, buf, count, ppos); if (!ld->ops->write) ret = -EIO; else @@ -1378,7 +1389,7 @@ static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver, * the tty_mutex currently so we can be relaxed about ordering. */ -int tty_init_termios(struct tty_struct *tty) +void tty_init_termios(struct tty_struct *tty) { struct ktermios *tp; int idx = tty->index; @@ -1388,24 +1399,21 @@ int tty_init_termios(struct tty_struct *tty) else { /* Check for lazy saved data */ tp = tty->driver->termios[idx]; - if (tp != NULL) + if (tp != NULL) { tty->termios = *tp; - else + tty->termios.c_line = tty->driver->init_termios.c_line; + } else tty->termios = tty->driver->init_termios; } /* Compatibility until drivers always set this */ tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios); tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios); - return 0; } EXPORT_SYMBOL_GPL(tty_init_termios); int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty) { - int ret = tty_init_termios(tty); - if (ret) - return ret; - + tty_init_termios(tty); tty_driver_kref_get(driver); tty->count++; driver->ttys[tty->index] = tty; @@ -1442,7 +1450,7 @@ static int tty_driver_install_tty(struct tty_driver *driver, * * Locking: tty_mutex for now */ -void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty) +static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty) { if (driver->ops->remove) driver->ops->remove(driver, tty); @@ -1475,7 +1483,8 @@ static int tty_reopen(struct tty_struct *tty) tty->count++; - WARN_ON(!tty->ldisc); + if (!tty->ldisc) + return tty_ldisc_reinit(tty, tty->termios.c_line); return 0; } @@ -1529,7 +1538,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) tty_lock(tty); retval = tty_driver_install_tty(driver, tty); if (retval < 0) - goto err_deinit_tty; + goto err_free_tty; if (!tty->port) tty->port = driver->ports[idx]; @@ -1551,9 +1560,8 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) /* Return the tty locked so that it cannot vanish under the caller */ return tty; -err_deinit_tty: +err_free_tty: tty_unlock(tty); - deinitialize_tty_struct(tty); free_tty_struct(tty); err_module_put: module_put(driver->owner); @@ -1568,7 +1576,7 @@ err_release_tty: return ERR_PTR(retval); } -void tty_free_termios(struct tty_struct *tty) +static void tty_free_termios(struct tty_struct *tty) { struct ktermios *tp; int idx = tty->index; @@ -1587,7 +1595,6 @@ void tty_free_termios(struct tty_struct *tty) } *tp = tty->termios; } -EXPORT_SYMBOL(tty_free_termios); /** * tty_flush_works - flush all works of a tty/pty pair @@ -1634,9 +1641,9 @@ static void release_one_tty(struct work_struct *work) tty_driver_kref_put(driver); module_put(owner); - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_del_init(&tty->tty_files); - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); put_pid(tty->pgrp); put_pid(tty->session); @@ -1967,7 +1974,7 @@ static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp) * Locking: tty_mutex protects get_tty_driver */ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, - int *noctty, int *index) + int *index) { struct tty_driver *driver; @@ -1977,7 +1984,6 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, extern struct tty_driver *console_driver; driver = tty_driver_kref_get(console_driver); *index = fg_console; - *noctty = 1; break; } #endif @@ -1988,7 +1994,6 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, if (driver) { /* Don't let /dev/console block */ filp->f_flags |= O_NONBLOCK; - *noctty = 1; break; } } @@ -2004,6 +2009,69 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, } /** + * tty_open_by_driver - open a tty device + * @device: dev_t of device to open + * @inode: inode of device file + * @filp: file pointer to tty + * + * Performs the driver lookup, checks for a reopen, or otherwise + * performs the first-time tty initialization. + * + * Returns the locked initialized or re-opened &tty_struct + * + * Claims the global tty_mutex to serialize: + * - concurrent first-time tty initialization + * - concurrent tty driver removal w/ lookup + * - concurrent tty removal from driver table + */ +static struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode, + struct file *filp) +{ + struct tty_struct *tty; + struct tty_driver *driver = NULL; + int index = -1; + int retval; + + mutex_lock(&tty_mutex); + driver = tty_lookup_driver(device, filp, &index); + if (IS_ERR(driver)) { + mutex_unlock(&tty_mutex); + return ERR_CAST(driver); + } + + /* check whether we're reopening an existing tty */ + tty = tty_driver_lookup_tty(driver, inode, index); + if (IS_ERR(tty)) { + mutex_unlock(&tty_mutex); + goto out; + } + + if (tty) { + mutex_unlock(&tty_mutex); + retval = tty_lock_interruptible(tty); + if (retval) { + if (retval == -EINTR) + retval = -ERESTARTSYS; + tty = ERR_PTR(retval); + goto out; + } + /* safe to drop the kref from tty_driver_lookup_tty() */ + tty_kref_put(tty); + retval = tty_reopen(tty); + if (retval < 0) { + tty_unlock(tty); + tty = ERR_PTR(retval); + } + } else { /* Returns with the tty_lock held for now */ + tty = tty_init_dev(driver, index); + mutex_unlock(&tty_mutex); + } +out: + tty_driver_kref_put(driver); + return tty; +} + +/** * tty_open - open a tty device * @inode: inode of device file * @filp: file pointer to tty @@ -2031,8 +2099,6 @@ static int tty_open(struct inode *inode, struct file *filp) { struct tty_struct *tty; int noctty, retval; - struct tty_driver *driver = NULL; - int index; dev_t device = inode->i_rdev; unsigned saved_flags = filp->f_flags; @@ -2043,54 +2109,15 @@ retry_open: if (retval) return -ENOMEM; - noctty = filp->f_flags & O_NOCTTY; - index = -1; - retval = 0; - tty = tty_open_current_tty(device, filp); - if (!tty) { - mutex_lock(&tty_mutex); - driver = tty_lookup_driver(device, filp, &noctty, &index); - if (IS_ERR(driver)) { - retval = PTR_ERR(driver); - goto err_unlock; - } - - /* check whether we're reopening an existing tty */ - tty = tty_driver_lookup_tty(driver, inode, index); - if (IS_ERR(tty)) { - retval = PTR_ERR(tty); - goto err_unlock; - } - - if (tty) { - mutex_unlock(&tty_mutex); - retval = tty_lock_interruptible(tty); - if (retval) { - if (retval == -EINTR) - retval = -ERESTARTSYS; - goto err_unref; - } - /* safe to drop the kref from tty_driver_lookup_tty() */ - tty_kref_put(tty); - retval = tty_reopen(tty); - if (retval < 0) { - tty_unlock(tty); - tty = ERR_PTR(retval); - } - } else { /* Returns with the tty_lock held for now */ - tty = tty_init_dev(driver, index); - mutex_unlock(&tty_mutex); - } - - tty_driver_kref_put(driver); - } + if (!tty) + tty = tty_open_by_driver(device, inode, filp); if (IS_ERR(tty)) { + tty_free_file(filp); retval = PTR_ERR(tty); if (retval != -EAGAIN || signal_pending(current)) - goto err_file; - tty_free_file(filp); + return retval; schedule(); goto retry_open; } @@ -2098,10 +2125,6 @@ retry_open: tty_add_file(tty, filp); check_tty_count(tty, __func__); - if (tty->driver->type == TTY_DRIVER_TYPE_PTY && - tty->driver->subtype == PTY_TYPE_MASTER) - noctty = 1; - tty_debug_hangup(tty, "opening (count=%d)\n", tty->count); if (tty->ops->open) @@ -2134,6 +2157,12 @@ retry_open: read_lock(&tasklist_lock); spin_lock_irq(¤t->sighand->siglock); + noctty = (filp->f_flags & O_NOCTTY) || + device == MKDEV(TTY_MAJOR, 0) || + device == MKDEV(TTYAUX_MAJOR, 1) || + (tty->driver->type == TTY_DRIVER_TYPE_PTY && + tty->driver->subtype == PTY_TYPE_MASTER); + if (!noctty && current->signal->leader && !current->signal->tty && @@ -2159,15 +2188,6 @@ retry_open: read_unlock(&tasklist_lock); tty_unlock(tty); return 0; -err_unlock: - mutex_unlock(&tty_mutex); -err_unref: - /* after locks to avoid deadlock */ - if (!IS_ERR_OR_NULL(driver)) - tty_driver_kref_put(driver); -err_file: - tty_free_file(filp); - return retval; } @@ -2194,6 +2214,8 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) return 0; ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_poll(filp, wait); if (ld->ops->poll) ret = ld->ops->poll(tty, filp, wait); tty_ldisc_deref(ld); @@ -2203,7 +2225,6 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) static int __tty_fasync(int fd, struct file *filp, int on) { struct tty_struct *tty = file_tty(filp); - struct tty_ldisc *ldisc; unsigned long flags; int retval = 0; @@ -2214,13 +2235,6 @@ static int __tty_fasync(int fd, struct file *filp, int on) if (retval <= 0) goto out; - ldisc = tty_ldisc_ref(tty); - if (ldisc) { - if (ldisc->ops->fasync) - ldisc->ops->fasync(tty, on); - tty_ldisc_deref(ldisc); - } - if (on) { enum pid_type type; struct pid *pid; @@ -2246,10 +2260,11 @@ out: static int tty_fasync(int fd, struct file *filp, int on) { struct tty_struct *tty = file_tty(filp); - int retval; + int retval = -ENOTTY; tty_lock(tty); - retval = __tty_fasync(fd, filp, on); + if (!tty_hung_up_p(filp)) + retval = __tty_fasync(fd, filp, on); tty_unlock(tty); return retval; @@ -2283,6 +2298,8 @@ static int tiocsti(struct tty_struct *tty, char __user *p) return -EFAULT; tty_audit_tiocsti(tty, ch); ld = tty_ldisc_ref_wait(tty); + if (!ld) + return -EIO; ld->ops->receive_buf(tty, &ch, &mbz, 1); tty_ldisc_deref(ld); return 0; @@ -2647,13 +2664,13 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _ static int tiocsetd(struct tty_struct *tty, int __user *p) { - int ldisc; + int disc; int ret; - if (get_user(ldisc, p)) + if (get_user(disc, p)) return -EFAULT; - ret = tty_set_ldisc(tty, ldisc); + ret = tty_set_ldisc(tty, disc); return ret; } @@ -2675,6 +2692,8 @@ static int tiocgetd(struct tty_struct *tty, int __user *p) int ret; ld = tty_ldisc_ref_wait(tty); + if (!ld) + return -EIO; ret = put_user(ld->ops->num, p); tty_ldisc_deref(ld); return ret; @@ -2972,6 +2991,8 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return retval; } ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_ioctl(file, cmd, arg); retval = -EINVAL; if (ld->ops->ioctl) { retval = ld->ops->ioctl(tty, file, cmd, arg); @@ -3000,6 +3021,8 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, } ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_compat_ioctl(file, cmd, arg); if (ld->ops->compat_ioctl) retval = ld->ops->compat_ioctl(tty, file, cmd, arg); else @@ -3150,6 +3173,7 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) mutex_init(&tty->atomic_write_lock); spin_lock_init(&tty->ctrl_lock); spin_lock_init(&tty->flow_lock); + spin_lock_init(&tty->files_lock); INIT_LIST_HEAD(&tty->tty_files); INIT_WORK(&tty->SAK_work, do_SAK_work); @@ -3163,20 +3187,6 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) } /** - * deinitialize_tty_struct - * @tty: tty to deinitialize - * - * This subroutine deinitializes a tty structure that has been newly - * allocated but tty_release cannot be called on that yet. - * - * Locking: none - tty in question must not be exposed at this point - */ -void deinitialize_tty_struct(struct tty_struct *tty) -{ - tty_ldisc_deinit(tty); -} - -/** * tty_put_char - write one character to a tty * @tty: tty * @ch: character @@ -3570,7 +3580,7 @@ void __init console_init(void) initcall_t *call; /* Setup the default TTY line discipline. */ - tty_ldisc_begin(); + n_tty_init(); /* * set up the console device so that later boot sequences can diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 0ea351388724..23bf5bb1d8bf 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -719,16 +719,16 @@ static int get_sgflags(struct tty_struct *tty) { int flags = 0; - if (!(tty->termios.c_lflag & ICANON)) { - if (tty->termios.c_lflag & ISIG) + if (!L_ICANON(tty)) { + if (L_ISIG(tty)) flags |= 0x02; /* cbreak */ else flags |= 0x20; /* raw */ } - if (tty->termios.c_lflag & ECHO) + if (L_ECHO(tty)) flags |= 0x08; /* echo */ - if (tty->termios.c_oflag & OPOST) - if (tty->termios.c_oflag & ONLCR) + if (O_OPOST(tty)) + if (O_ONLCR(tty)) flags |= 0x10; /* crmod */ return flags; } @@ -908,7 +908,7 @@ static int tty_change_softcar(struct tty_struct *tty, int arg) tty->termios.c_cflag |= bit; if (tty->ops->set_termios) tty->ops->set_termios(tty, &old); - if ((tty->termios.c_cflag & CLOCAL) != bit) + if (C_CLOCAL(tty) != bit) ret = -EINVAL; up_write(&tty->termios_rwsem); return ret; diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index a054d03c22e7..68947f6de5ad 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -140,9 +140,16 @@ static void put_ldops(struct tty_ldisc_ops *ldops) * @disc: ldisc number * * Takes a reference to a line discipline. Deals with refcounts and - * module locking counts. Returns NULL if the discipline is not available. - * Returns a pointer to the discipline and bumps the ref count if it is - * available + * module locking counts. + * + * Returns: -EINVAL if the discipline index is not [N_TTY..NR_LDISCS] or + * if the discipline is not registered + * -EAGAIN if request_module() failed to load or register the + * the discipline + * -ENOMEM if allocation failure + * + * Otherwise, returns a pointer to the discipline and bumps the + * ref count * * Locking: * takes tty_ldiscs_lock to guard against ldisc races @@ -250,19 +257,23 @@ const struct file_operations tty_ldiscs_proc_fops = { * reference to it. If the line discipline is in flux then * wait patiently until it changes. * + * Returns: NULL if the tty has been hungup and not re-opened with + * a new file descriptor, otherwise valid ldisc reference + * * Note: Must not be called from an IRQ/timer context. The caller * must also be careful not to hold other locks that will deadlock * against a discipline change, such as an existing ldisc reference * (which we check for) * - * Note: only callable from a file_operations routine (which - * guarantees tty->ldisc != NULL when the lock is acquired). + * Note: a file_operations routine (read/poll/write) should use this + * function to wait for any ldisc lifetime events to finish. */ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) { ldsem_down_read(&tty->ldisc_sem, MAX_SCHEDULE_TIMEOUT); - WARN_ON(!tty->ldisc); + if (!tty->ldisc) + ldsem_up_read(&tty->ldisc_sem); return tty->ldisc; } EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); @@ -304,13 +315,13 @@ void tty_ldisc_deref(struct tty_ldisc *ld) EXPORT_SYMBOL_GPL(tty_ldisc_deref); -static inline int __lockfunc +static inline int __tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) { return ldsem_down_write(&tty->ldisc_sem, timeout); } -static inline int __lockfunc +static inline int __tty_ldisc_lock_nested(struct tty_struct *tty, unsigned long timeout) { return ldsem_down_write_nested(&tty->ldisc_sem, @@ -322,8 +333,7 @@ static inline void __tty_ldisc_unlock(struct tty_struct *tty) ldsem_up_write(&tty->ldisc_sem); } -static int __lockfunc -tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) +static int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) { int ret; @@ -340,7 +350,7 @@ static void tty_ldisc_unlock(struct tty_struct *tty) __tty_ldisc_unlock(tty); } -static int __lockfunc +static int tty_ldisc_lock_pair_timeout(struct tty_struct *tty, struct tty_struct *tty2, unsigned long timeout) { @@ -376,14 +386,13 @@ tty_ldisc_lock_pair_timeout(struct tty_struct *tty, struct tty_struct *tty2, return 0; } -static void __lockfunc -tty_ldisc_lock_pair(struct tty_struct *tty, struct tty_struct *tty2) +static void tty_ldisc_lock_pair(struct tty_struct *tty, struct tty_struct *tty2) { tty_ldisc_lock_pair_timeout(tty, tty2, MAX_SCHEDULE_TIMEOUT); } -static void __lockfunc tty_ldisc_unlock_pair(struct tty_struct *tty, - struct tty_struct *tty2) +static void tty_ldisc_unlock_pair(struct tty_struct *tty, + struct tty_struct *tty2) { __tty_ldisc_unlock(tty); if (tty2) @@ -411,7 +420,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); /** * tty_set_termios_ldisc - set ldisc field * @tty: tty structure - * @num: line discipline number + * @disc: line discipline number * * This is probably overkill for real world processors but * they are not on hot paths so a little discipline won't do @@ -424,10 +433,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); * Locking: takes termios_rwsem */ -static void tty_set_termios_ldisc(struct tty_struct *tty, int num) +static void tty_set_termios_ldisc(struct tty_struct *tty, int disc) { down_write(&tty->termios_rwsem); - tty->termios.c_line = num; + tty->termios.c_line = disc; up_write(&tty->termios_rwsem); tty->disc_data = NULL; @@ -455,7 +464,7 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) if (ret) clear_bit(TTY_LDISC_OPEN, &tty->flags); - tty_ldisc_debug(tty, "%p: opened\n", tty->ldisc); + tty_ldisc_debug(tty, "%p: opened\n", ld); return ret; } return 0; @@ -476,7 +485,7 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) clear_bit(TTY_LDISC_OPEN, &tty->flags); if (ld->ops->close) ld->ops->close(tty); - tty_ldisc_debug(tty, "%p: closed\n", tty->ldisc); + tty_ldisc_debug(tty, "%p: closed\n", ld); } /** @@ -525,12 +534,12 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) * the close of one side of a tty/pty pair, and eventually hangup. */ -int tty_set_ldisc(struct tty_struct *tty, int ldisc) +int tty_set_ldisc(struct tty_struct *tty, int disc) { int retval; struct tty_ldisc *old_ldisc, *new_ldisc; - new_ldisc = tty_ldisc_get(tty, ldisc); + new_ldisc = tty_ldisc_get(tty, disc); if (IS_ERR(new_ldisc)) return PTR_ERR(new_ldisc); @@ -539,8 +548,13 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (retval) goto err; + if (!tty->ldisc) { + retval = -EIO; + goto out; + } + /* Check the no-op case */ - if (tty->ldisc->ops->num == ldisc) + if (tty->ldisc->ops->num == disc) goto out; if (test_bit(TTY_HUPPED, &tty->flags)) { @@ -556,7 +570,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) /* Now set up the new line discipline. */ tty->ldisc = new_ldisc; - tty_set_termios_ldisc(tty, ldisc); + tty_set_termios_ldisc(tty, disc); retval = tty_ldisc_open(tty, new_ldisc); if (retval < 0) { @@ -590,6 +604,25 @@ err: } /** + * tty_ldisc_kill - teardown ldisc + * @tty: tty being released + * + * Perform final close of the ldisc and reset tty->ldisc + */ +static void tty_ldisc_kill(struct tty_struct *tty) +{ + if (!tty->ldisc) + return; + /* + * Now kill off the ldisc + */ + tty_ldisc_close(tty, tty->ldisc); + tty_ldisc_put(tty->ldisc); + /* Force an oops if we mess this up */ + tty->ldisc = NULL; +} + +/** * tty_reset_termios - reset terminal state * @tty: tty to reset * @@ -609,28 +642,44 @@ static void tty_reset_termios(struct tty_struct *tty) /** * tty_ldisc_reinit - reinitialise the tty ldisc * @tty: tty to reinit - * @ldisc: line discipline to reinitialize + * @disc: line discipline to reinitialize + * + * Completely reinitialize the line discipline state, by closing the + * current instance, if there is one, and opening a new instance. If + * an error occurs opening the new non-N_TTY instance, the instance + * is dropped and tty->ldisc reset to NULL. The caller can then retry + * with N_TTY instead. * - * Switch the tty to a line discipline and leave the ldisc - * state closed + * Returns 0 if successful, otherwise error code < 0 */ -static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) +int tty_ldisc_reinit(struct tty_struct *tty, int disc) { - struct tty_ldisc *ld = tty_ldisc_get(tty, ldisc); + struct tty_ldisc *ld; + int retval; - if (IS_ERR(ld)) - return -1; + ld = tty_ldisc_get(tty, disc); + if (IS_ERR(ld)) { + BUG_ON(disc == N_TTY); + return PTR_ERR(ld); + } - tty_ldisc_close(tty, tty->ldisc); - tty_ldisc_put(tty->ldisc); - /* - * Switch the line discipline back - */ - tty->ldisc = ld; - tty_set_termios_ldisc(tty, ldisc); + if (tty->ldisc) { + tty_ldisc_close(tty, tty->ldisc); + tty_ldisc_put(tty->ldisc); + } - return 0; + /* switch the line discipline */ + tty->ldisc = ld; + tty_set_termios_ldisc(tty, disc); + retval = tty_ldisc_open(tty, tty->ldisc); + if (retval) { + if (!WARN_ON(disc == N_TTY)) { + tty_ldisc_put(tty->ldisc); + tty->ldisc = NULL; + } + } + return retval; } /** @@ -648,13 +697,11 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) * tty itself so we must be careful about locking rules. */ -void tty_ldisc_hangup(struct tty_struct *tty) +void tty_ldisc_hangup(struct tty_struct *tty, bool reinit) { struct tty_ldisc *ld; - int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS; - int err = 0; - tty_ldisc_debug(tty, "%p: closing\n", tty->ldisc); + tty_ldisc_debug(tty, "%p: hangup\n", tty->ldisc); ld = tty_ldisc_ref(tty); if (ld != NULL) { @@ -680,31 +727,17 @@ void tty_ldisc_hangup(struct tty_struct *tty) */ tty_ldisc_lock(tty, MAX_SCHEDULE_TIMEOUT); - if (tty->ldisc) { - - /* At this point we have a halted ldisc; we want to close it and - reopen a new ldisc. We could defer the reopen to the next - open but it means auditing a lot of other paths so this is - a FIXME */ - if (reset == 0) { + if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) + tty_reset_termios(tty); - if (!tty_ldisc_reinit(tty, tty->termios.c_line)) - err = tty_ldisc_open(tty, tty->ldisc); - else - err = 1; - } - /* If the re-open fails or we reset then go to N_TTY. The - N_TTY open cannot fail */ - if (reset || err) { - BUG_ON(tty_ldisc_reinit(tty, N_TTY)); - WARN_ON(tty_ldisc_open(tty, tty->ldisc)); - } + if (tty->ldisc) { + if (reinit) { + if (tty_ldisc_reinit(tty, tty->termios.c_line) < 0) + tty_ldisc_reinit(tty, N_TTY); + } else + tty_ldisc_kill(tty); } tty_ldisc_unlock(tty); - if (reset) - tty_reset_termios(tty); - - tty_ldisc_debug(tty, "%p: re-opened\n", tty->ldisc); } /** @@ -719,44 +752,26 @@ void tty_ldisc_hangup(struct tty_struct *tty) int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) { - struct tty_ldisc *ld = tty->ldisc; - int retval; - - retval = tty_ldisc_open(tty, ld); + int retval = tty_ldisc_open(tty, tty->ldisc); if (retval) return retval; if (o_tty) { retval = tty_ldisc_open(o_tty, o_tty->ldisc); if (retval) { - tty_ldisc_close(tty, ld); + tty_ldisc_close(tty, tty->ldisc); return retval; } } return 0; } -static void tty_ldisc_kill(struct tty_struct *tty) -{ - /* - * Now kill off the ldisc - */ - tty_ldisc_close(tty, tty->ldisc); - tty_ldisc_put(tty->ldisc); - /* Force an oops if we mess this up */ - tty->ldisc = NULL; - - /* Ensure the next open requests the N_TTY ldisc */ - tty_set_termios_ldisc(tty, N_TTY); -} - /** * tty_ldisc_release - release line discipline * @tty: tty being shut down (or one end of pty pair) * * Called during the final close of a tty or a pty pair in order to shut - * down the line discpline layer. On exit, each ldisc assigned is N_TTY and - * each ldisc has not been opened. + * down the line discpline layer. On exit, each tty's ldisc is NULL. */ void tty_ldisc_release(struct tty_struct *tty) @@ -797,7 +812,7 @@ void tty_ldisc_init(struct tty_struct *tty) } /** - * tty_ldisc_init - ldisc cleanup for new tty + * tty_ldisc_deinit - ldisc cleanup for new tty * @tty: tty that was allocated recently * * The tty structure must not becompletely set up (tty_ldisc_setup) when @@ -805,12 +820,7 @@ void tty_ldisc_init(struct tty_struct *tty) */ void tty_ldisc_deinit(struct tty_struct *tty) { - tty_ldisc_put(tty->ldisc); + if (tty->ldisc) + tty_ldisc_put(tty->ldisc); tty->ldisc = NULL; } - -void tty_ldisc_begin(void) -{ - /* Setup the default TTY line discipline. */ - (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY); -} diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index d2f3c4cd697f..75351e4b77df 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c @@ -10,7 +10,7 @@ * Getting the big tty mutex. */ -void __lockfunc tty_lock(struct tty_struct *tty) +void tty_lock(struct tty_struct *tty) { if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty)) return; @@ -27,7 +27,7 @@ int tty_lock_interruptible(struct tty_struct *tty) return mutex_lock_interruptible(&tty->legacy_mutex); } -void __lockfunc tty_unlock(struct tty_struct *tty) +void tty_unlock(struct tty_struct *tty) { if (WARN(tty->magic != TTY_MAGIC, "U Bad %p\n", tty)) return; @@ -36,13 +36,13 @@ void __lockfunc tty_unlock(struct tty_struct *tty) } EXPORT_SYMBOL(tty_unlock); -void __lockfunc tty_lock_slave(struct tty_struct *tty) +void tty_lock_slave(struct tty_struct *tty) { if (tty && tty != tty->link) tty_lock(tty); } -void __lockfunc tty_unlock_slave(struct tty_struct *tty) +void tty_unlock_slave(struct tty_struct *tty) { if (tty && tty != tty->link) tty_unlock(tty); diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 846ed481c24f..dbcca30a54b1 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -370,7 +370,7 @@ int tty_port_block_til_ready(struct tty_port *port, } if (filp->f_flags & O_NONBLOCK) { /* Indicate we are open */ - if (tty->termios.c_cflag & CBAUD) + if (C_BAUD(tty)) tty_port_raise_dtr_rts(port); port->flags |= ASYNC_NORMAL_ACTIVE; return 0; @@ -476,7 +476,6 @@ int tty_port_close_start(struct tty_port *port, spin_unlock_irqrestore(&port->lock, flags); return 0; } - set_bit(ASYNCB_CLOSING, &port->flags); spin_unlock_irqrestore(&port->lock, flags); tty->closing = 1; @@ -510,14 +509,12 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) if (port->blocked_open) { spin_unlock_irqrestore(&port->lock, flags); - if (port->close_delay) { - msleep_interruptible( - jiffies_to_msecs(port->close_delay)); - } + if (port->close_delay) + msleep_interruptible(jiffies_to_msecs(port->close_delay)); spin_lock_irqsave(&port->lock, flags); wake_up_interruptible(&port->open_wait); } - port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); + port->flags &= ~ASYNC_NORMAL_ACTIVE; spin_unlock_irqrestore(&port->lock, flags); } EXPORT_SYMBOL(tty_port_close_end); diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 381a2b13682c..4dd9dd2270a0 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -347,6 +347,8 @@ int paste_selection(struct tty_struct *tty) console_unlock(); ld = tty_ldisc_ref_wait(tty); + if (!ld) + return -EIO; /* ldisc was hung up */ tty_buffer_lock_exclusive(&vc->port); add_wait_queue(&vc->paste_wait, &wait); diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 3806e7014199..a66b01bb1fa1 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -147,10 +147,7 @@ static int usb_console_setup(struct console *co, char *options) kref_get(&tty->driver->kref); __module_get(tty->driver->owner); tty->ops = &usb_console_fake_tty_ops; - if (tty_init_termios(tty)) { - retval = -ENOMEM; - goto put_tty; - } + tty_init_termios(tty); tty_port_tty_set(&port->port, tty); } @@ -185,7 +182,6 @@ static int usb_console_setup(struct console *co, char *options) fail: tty_port_tty_set(&port->port, NULL); - put_tty: tty_kref_put(tty); reset_open_count: port->port.count = 0; diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 01bf53392819..b283eb8b86d6 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -1165,8 +1165,7 @@ static void cypress_read_int_callback(struct urb *urb) /* hangup, as defined in acm.c... this might be a bad place for it * though */ - if (tty && !(tty->termios.c_cflag & CLOCAL) && - !(priv->current_status & UART_CD)) { + if (tty && !C_CLOCAL(tty) && !(priv->current_status & UART_CD)) { dev_dbg(dev, "%s - calling hangup\n", __func__); tty_hangup(tty); goto continue_read; diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 12b0e67473ba..010a42a92688 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -695,11 +695,11 @@ static void digi_set_termios(struct tty_struct *tty, arg = -1; /* reassert DTR and (maybe) RTS on transition from B0 */ - if ((old_cflag&CBAUD) == B0) { + if ((old_cflag & CBAUD) == B0) { /* don't set RTS if using hardware flow control */ /* and throttling input */ modem_signals = TIOCM_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) modem_signals |= TIOCM_RTS; digi_set_modem_signals(port, modem_signals, 1); @@ -1491,8 +1491,8 @@ static int digi_read_oob_callback(struct urb *urb) rts = 0; if (tty) - rts = tty->termios.c_cflag & CRTSCTS; - + rts = C_CRTSCTS(tty); + if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) { spin_lock(&priv->dp_port_lock); /* convert from digi flags to termiox flags */ diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index f49327d20ee8..f3007ecdd1b4 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -1398,7 +1398,7 @@ static void edge_throttle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { edge_port->shadowMCR &= ~MCR_RTS; status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); @@ -1435,7 +1435,7 @@ static void edge_unthrottle(struct tty_struct *tty) return; } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { edge_port->shadowMCR |= MCR_RTS; send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index fd707d6a10e2..4446b8d70ac2 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -428,7 +428,7 @@ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port) * either. */ spin_lock_irqsave(&priv->lock, flags); - if (tty && (tty->termios.c_cflag & CBAUD)) + if (tty && C_BAUD(tty)) priv->control_state = TIOCM_DTR | TIOCM_RTS; else priv->control_state = 0; diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 78b4f64c6b00..2eddbe538cda 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1308,7 +1308,7 @@ static void mos7720_throttle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { mos7720_port->shadowMCR &= ~UART_MCR_RTS; write_mos_reg(port->serial, port->port_number, MOS7720_MCR, mos7720_port->shadowMCR); @@ -1338,7 +1338,7 @@ static void mos7720_unthrottle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { mos7720_port->shadowMCR |= UART_MCR_RTS; write_mos_reg(port->serial, port->port_number, MOS7720_MCR, mos7720_port->shadowMCR); diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 2c69bfcdacc6..02ea975754f5 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1425,7 +1425,7 @@ static void mos7840_throttle(struct tty_struct *tty) return; } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { mos7840_port->shadowMCR &= ~MCR_RTS; status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mos7840_port->shadowMCR); @@ -1466,7 +1466,7 @@ static void mos7840_unthrottle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { mos7840_port->shadowMCR |= MCR_RTS; status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mos7840_port->shadowMCR); |