diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-14 15:23:32 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-14 15:23:32 -0800 |
commit | 37da7bbbe84fe9e8862940d3f9194fd27dce59bb (patch) | |
tree | 6c3fae910b4cfd4e2f9a1fdc035400cd4df78be3 /drivers/tty | |
parent | e7cf773d431a63a2417902696fcc9e0ebdc83bbe (diff) | |
parent | dd63af108f0814f0b589659f4e55a7a5af3b7e53 (diff) |
Merge tag 'tty-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH:
"Here's the big tty/serial driver update for 3.19-rc1.
There are a number of TTY core changes/fixes in here from Peter Hurley
that have all been teted in linux-next for a long time now. There are
also the normal serial driver updates as well, full details in the
changelog below"
* tag 'tty-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (219 commits)
serial: pxa: hold port.lock when reporting modem line changes
tty-hvsi_lib: Deletion of an unnecessary check before the function call "tty_kref_put"
tty: Deletion of unnecessary checks before two function calls
n_tty: Fix read_buf race condition, increment read_head after pushing data
serial: of-serial: add PM suspend/resume support
Revert "serial: of-serial: add PM suspend/resume support"
Revert "serial: of-serial: fix up PM ops on no_console_suspend and port type"
serial: 8250: don't attempt a trylock if in sysrq
serial: core: Add big-endian iotype
serial: samsung: use port->fifosize instead of hardcoded values
serial: samsung: prefer to use fifosize from driver data
serial: samsung: fix style problems
serial: samsung: wait for transfer completion before clock disable
serial: icom: fix error return code
serial: tegra: clean up tty-flag assignments
serial: Fix io address assign flow with Fintek PCI-to-UART Product
serial: mxs-auart: fix tx_empty against shift register
serial: mxs-auart: fix gpio change detection on interrupt
serial: mxs-auart: Fix mxs_auart_set_ldisc()
serial: 8250_dw: Use 64-bit access for OCTEON.
...
Diffstat (limited to 'drivers/tty')
80 files changed, 4536 insertions, 1475 deletions
diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c index 4f485e88f60c..9d29d7e4b28c 100644 --- a/drivers/tty/ehv_bytechan.c +++ b/drivers/tty/ehv_bytechan.c @@ -309,8 +309,8 @@ static int __init ehv_bc_console_init(void) * handle for udbg. */ if (stdout_bc != CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE) - pr_warning("ehv-bc: udbg handle %u is not the stdout handle\n", - CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE); + pr_warn("ehv-bc: udbg handle %u is not the stdout handle\n", + CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE); #endif /* add_preferred_console() must be called before register_console(), diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c index 09495f515fa9..967b2c2b7cf1 100644 --- a/drivers/tty/goldfish.c +++ b/drivers/tty/goldfish.c @@ -155,9 +155,9 @@ static struct tty_driver *goldfish_tty_console_device(struct console *c, static int goldfish_tty_console_setup(struct console *co, char *options) { - if ((unsigned)co->index > goldfish_tty_line_count) + if ((unsigned)co->index >= goldfish_tty_line_count) return -ENODEV; - if (goldfish_ttys[co->index].base == 0) + if (!goldfish_ttys[co->index].base) return -ENODEV; return 0; } @@ -317,7 +317,7 @@ static int goldfish_tty_remove(struct platform_device *pdev) unregister_console(&qtty->console); tty_unregister_device(goldfish_tty_driver, pdev->id); iounmap(qtty->base); - qtty->base = 0; + qtty->base = NULL; free_irq(qtty->irq, pdev); goldfish_tty_current_line_count--; if (goldfish_tty_current_line_count == 0) diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index 81e939e90c4c..81ff7e1bfb1a 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c @@ -1575,7 +1575,7 @@ static int __init hvcs_module_init(void) */ rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan); if (rc) - pr_warning(KERN_ERR "HVCS: Failed to create rescan file (err %d)\n", rc); + pr_warning("HVCS: Failed to create rescan file (err %d)\n", rc); return 0; } diff --git a/drivers/tty/hvc/hvsi_lib.c b/drivers/tty/hvc/hvsi_lib.c index 7ae6c293e518..a270f04588d7 100644 --- a/drivers/tty/hvc/hvsi_lib.c +++ b/drivers/tty/hvc/hvsi_lib.c @@ -405,8 +405,7 @@ void hvsilib_close(struct hvsi_priv *pv, struct hvc_struct *hp) hvsi_send_close(pv); } - if (pv->tty) - tty_kref_put(pv->tty); + tty_kref_put(pv->tty); pv->tty = NULL; } diff --git a/drivers/tty/ipwireless/hardware.c b/drivers/tty/ipwireless/hardware.c index 2c14842541dd..5c77e1eac4ee 100644 --- a/drivers/tty/ipwireless/hardware.c +++ b/drivers/tty/ipwireless/hardware.c @@ -378,9 +378,9 @@ static void swap_packet_bitfield_to_le(unsigned char *data) /* * transform bits from aa.bbb.ccc to ccc.bbb.aa */ - ret |= tmp & 0xc0 >> 6; - ret |= tmp & 0x38 >> 1; - ret |= tmp & 0x07 << 5; + ret |= (tmp & 0xc0) >> 6; + ret |= (tmp & 0x38) >> 1; + ret |= (tmp & 0x07) << 5; *data = ret & 0xff; #endif } @@ -393,9 +393,9 @@ static void swap_packet_bitfield_from_le(unsigned char *data) /* * transform bits from ccc.bbb.aa to aa.bbb.ccc */ - ret |= tmp & 0xe0 >> 5; - ret |= tmp & 0x1c << 1; - ret |= tmp & 0x03 << 6; + ret |= (tmp & 0xe0) >> 5; + ret |= (tmp & 0x1c) << 1; + ret |= (tmp & 0x03) << 6; *data = ret & 0xff; #endif } diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index 858291ca889c..59ed783c4bcd 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -249,7 +249,7 @@ static int lock_card(struct isi_board *card) spin_unlock_irqrestore(&card->card_lock, card->flags); msleep(10); } - pr_warning("Failed to lock Card (0x%lx)\n", card->base); + pr_warn("Failed to lock Card (0x%lx)\n", card->base); return 0; /* Failed to acquire the card! */ } @@ -378,13 +378,13 @@ static inline int __isicom_paranoia_check(struct isi_port const *port, char *name, const char *routine) { if (!port) { - pr_warning("Warning: bad isicom magic for dev %s in %s.\n", - name, routine); + pr_warn("Warning: bad isicom magic for dev %s in %s\n", + name, routine); return 1; } if (port->magic != ISICOM_MAGIC) { - pr_warning("Warning: NULL isicom port for dev %s in %s.\n", - name, routine); + pr_warn("Warning: NULL isicom port for dev %s in %s\n", + name, routine); return 1; } @@ -546,8 +546,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) byte_count = header & 0xff; if (channel + 1 > card->port_count) { - pr_warning("%s(0x%lx): %d(channel) > port_count.\n", - __func__, base, channel+1); + pr_warn("%s(0x%lx): %d(channel) > port_count\n", + __func__, base, channel + 1); outw(0x0000, base+0x04); /* enable interrupts */ spin_unlock(&card->card_lock); return IRQ_HANDLED; diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 26f097f60b10..d2b496750d59 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -321,7 +321,8 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) { - *read_buf_addr(ldata, ldata->read_head++) = c; + *read_buf_addr(ldata, ldata->read_head) = c; + ldata->read_head++; } /** @@ -351,13 +352,13 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty) { unsigned long flags; - spin_lock_irqsave(&tty->ctrl_lock, flags); if (tty->link->packet) { + spin_lock_irqsave(&tty->ctrl_lock, flags); tty->ctrl_status |= TIOCPKT_FLUSHREAD; + spin_unlock_irqrestore(&tty->ctrl_lock, flags); if (waitqueue_active(&tty->link->read_wait)) wake_up_interruptible(&tty->link->read_wait); } - spin_unlock_irqrestore(&tty->ctrl_lock, flags); } /** @@ -2128,7 +2129,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, int minimum, time; ssize_t retval = 0; long timeout; - unsigned long flags; int packet; c = job_control(tty, file); @@ -2174,10 +2174,10 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, unsigned char cs; if (b != buf) break; - spin_lock_irqsave(&tty->link->ctrl_lock, flags); + spin_lock_irq(&tty->link->ctrl_lock); cs = tty->link->ctrl_status; tty->link->ctrl_status = 0; - spin_unlock_irqrestore(&tty->link->ctrl_lock, flags); + spin_unlock_irq(&tty->link->ctrl_lock); if (tty_put_user(tty, cs, b++)) { retval = -EFAULT; b--; @@ -2193,45 +2193,29 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, if (!input_available_p(tty, 0)) { if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { - up_read(&tty->termios_rwsem); - tty_flush_to_ldisc(tty); - down_read(&tty->termios_rwsem); - if (!input_available_p(tty, 0)) { - retval = -EIO; - break; - } - } else { - if (tty_hung_up_p(file)) - break; - if (!timeout) - break; - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - n_tty_set_room(tty); - up_read(&tty->termios_rwsem); - - timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, - timeout); - - down_read(&tty->termios_rwsem); - continue; + retval = -EIO; + break; } - } - - /* Deal with packet mode. */ - if (packet && b == buf) { - if (tty_put_user(tty, TIOCPKT_DATA, b++)) { - retval = -EFAULT; - b--; + if (tty_hung_up_p(file)) + break; + if (!timeout) + break; + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; break; } - nr--; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + n_tty_set_room(tty); + up_read(&tty->termios_rwsem); + + timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, + timeout); + + down_read(&tty->termios_rwsem); + continue; } if (ldata->icanon && !L_EXTPROC(tty)) { @@ -2243,8 +2227,17 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, break; } else { int uncopied; - /* The copy function takes the read lock and handles - locking internally for this case */ + + /* Deal with packet mode. */ + if (packet && b == buf) { + if (tty_put_user(tty, TIOCPKT_DATA, b++)) { + retval = -EFAULT; + b--; + break; + } + nr--; + } + uncopied = copy_from_read_buf(tty, &b, &nr); uncopied += copy_from_read_buf(tty, &b, &nr); if (uncopied) { diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 7c4447a5c0f4..a9d256d6e909 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -47,10 +47,13 @@ static void pty_close(struct tty_struct *tty, struct file *filp) set_bit(TTY_IO_ERROR, &tty->flags); wake_up_interruptible(&tty->read_wait); wake_up_interruptible(&tty->write_wait); + spin_lock_irq(&tty->ctrl_lock); tty->packet = 0; + spin_unlock_irq(&tty->ctrl_lock); /* Review - krefs on tty_link ?? */ if (!tty->link) return; + tty_flush_to_ldisc(tty->link); set_bit(TTY_OTHER_CLOSED, &tty->link->flags); wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->write_wait); @@ -64,9 +67,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp) mutex_unlock(&devpts_mutex); } #endif - tty_unlock(tty); tty_vhangup(tty->link); - tty_lock(tty); } } @@ -178,21 +179,21 @@ static int pty_get_lock(struct tty_struct *tty, int __user *arg) /* Set the packet mode on a pty */ static int pty_set_pktmode(struct tty_struct *tty, int __user *arg) { - unsigned long flags; int pktmode; if (get_user(pktmode, arg)) return -EFAULT; - spin_lock_irqsave(&tty->ctrl_lock, flags); + spin_lock_irq(&tty->ctrl_lock); if (pktmode) { if (!tty->packet) { - tty->packet = 1; tty->link->ctrl_status = 0; + smp_mb(); + tty->packet = 1; } } else tty->packet = 0; - spin_unlock_irqrestore(&tty->ctrl_lock, flags); + spin_unlock_irq(&tty->ctrl_lock); return 0; } @@ -207,15 +208,12 @@ static int pty_get_pktmode(struct tty_struct *tty, int __user *arg) /* Send a signal to the slave */ static int pty_signal(struct tty_struct *tty, int sig) { - unsigned long flags; struct pid *pgrp; if (tty->link) { - spin_lock_irqsave(&tty->link->ctrl_lock, flags); - pgrp = get_pid(tty->link->pgrp); - spin_unlock_irqrestore(&tty->link->ctrl_lock, flags); - - kill_pgrp(pgrp, sig, 1); + pgrp = tty_get_pgrp(tty->link); + if (pgrp) + kill_pgrp(pgrp, sig, 1); put_pid(pgrp); } return 0; @@ -224,16 +222,15 @@ static int pty_signal(struct tty_struct *tty, int sig) static void pty_flush_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; - unsigned long flags; if (!to) return; /* tty_buffer_flush(to); FIXME */ if (to->packet) { - spin_lock_irqsave(&tty->ctrl_lock, flags); + spin_lock_irq(&tty->ctrl_lock); tty->ctrl_status |= TIOCPKT_FLUSHWRITE; wake_up_interruptible(&to->read_wait); - spin_unlock_irqrestore(&tty->ctrl_lock, flags); + spin_unlock_irq(&tty->ctrl_lock); } } @@ -262,6 +259,32 @@ out: static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { + /* 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 old_flow = ((old_termios->c_iflag & IXON) && + (old_termios->c_cc[VSTOP] == '\023') && + (old_termios->c_cc[VSTART] == '\021')); + int new_flow = (I_IXON(tty) && + STOP_CHAR(tty) == '\023' && + START_CHAR(tty) == '\021'); + if ((old_flow != new_flow) || extproc) { + spin_lock_irq(&tty->ctrl_lock); + if (old_flow != new_flow) { + tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); + if (new_flow) + tty->ctrl_status |= TIOCPKT_DOSTOP; + else + tty->ctrl_status |= TIOCPKT_NOSTOP; + } + if (extproc) + tty->ctrl_status |= TIOCPKT_IOCTL; + spin_unlock_irq(&tty->ctrl_lock); + wake_up_interruptible(&tty->link->read_wait); + } + } + tty->termios.c_cflag &= ~(CSIZE | PARENB); tty->termios.c_cflag |= (CS8 | CREAD); } @@ -278,7 +301,6 @@ static void pty_set_termios(struct tty_struct *tty, static int pty_resize(struct tty_struct *tty, struct winsize *ws) { struct pid *pgrp, *rpgrp; - unsigned long flags; struct tty_struct *pty = tty->link; /* For a PTY we need to lock the tty side */ @@ -286,17 +308,9 @@ static int pty_resize(struct tty_struct *tty, struct winsize *ws) if (!memcmp(ws, &tty->winsize, sizeof(*ws))) goto done; - /* Get the PID values and reference them so we can - avoid holding the tty ctrl lock while sending signals. - We need to lock these individually however. */ - - spin_lock_irqsave(&tty->ctrl_lock, flags); - pgrp = get_pid(tty->pgrp); - spin_unlock_irqrestore(&tty->ctrl_lock, flags); - - spin_lock_irqsave(&pty->ctrl_lock, flags); - rpgrp = get_pid(pty->pgrp); - spin_unlock_irqrestore(&pty->ctrl_lock, flags); + /* Signal the foreground process group of both ptys */ + pgrp = tty_get_pgrp(tty); + rpgrp = tty_get_pg |