diff options
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/n_gsm.c | 4 | ||||
-rw-r--r-- | drivers/tty/n_hdlc.c | 4 | ||||
-rw-r--r-- | drivers/tty/n_tty.c | 70 | ||||
-rw-r--r-- | drivers/tty/pty.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_mid.c | 35 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_pci.c | 3 | ||||
-rw-r--r-- | drivers/tty/serial/atmel_serial.c | 14 | ||||
-rw-r--r-- | drivers/tty/serial/samsung.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/ucc_uart.c | 3 | ||||
-rw-r--r-- | drivers/tty/tty_buffer.c | 34 | ||||
-rw-r--r-- | drivers/tty/vt/keyboard.c | 30 | ||||
-rw-r--r-- | drivers/tty/vt/vt.c | 6 |
12 files changed, 101 insertions, 110 deletions
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c3fe026d3168..9aff37186246 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2045,7 +2045,9 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm) } } spin_unlock(&gsm_mux_lock); - WARN_ON(i == MAX_MUX); + /* open failed before registering => nothing to do */ + if (i == MAX_MUX) + return; /* In theory disconnecting DLCI 0 is sufficient but for some modems this is apparently not the case. */ diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index bbc4ce66c2c1..644ddb841d9f 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -600,7 +600,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, add_wait_queue(&tty->read_wait, &wait); for (;;) { - if (test_bit(TTY_OTHER_DONE, &tty->flags)) { + if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { ret = -EIO; break; } @@ -828,7 +828,7 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, /* set bits for operations that won't block */ if (n_hdlc->rx_buf_list.head) mask |= POLLIN | POLLRDNORM; /* readable */ - if (test_bit(TTY_OTHER_DONE, &tty->flags)) + if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) mask |= POLLHUP; if (tty_hung_up_p(filp)) mask |= POLLHUP; diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index cf000b331eed..84e71bd19082 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1955,18 +1955,6 @@ static inline int input_available_p(struct tty_struct *tty, int poll) return ldata->commit_head - ldata->read_tail >= amt; } -static inline int check_other_done(struct tty_struct *tty) -{ - int done = test_bit(TTY_OTHER_DONE, &tty->flags); - if (done) { - /* paired with cmpxchg() in check_other_closed(); ensures - * read buffer head index is not stale - */ - smp_mb__after_atomic(); - } - return done; -} - /** * copy_from_read_buf - copy read data directly * @tty: terminal device @@ -2171,7 +2159,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, struct n_tty_data *ldata = tty->disc_data; unsigned char __user *b = buf; DEFINE_WAIT_FUNC(wait, woken_wake_function); - int c, done; + int c; int minimum, time; ssize_t retval = 0; long timeout; @@ -2239,32 +2227,35 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, ((minimum - (b - buf)) >= 1)) ldata->minimum_to_wake = (minimum - (b - buf)); - done = check_other_done(tty); - if (!input_available_p(tty, 0)) { - if (done) { - retval = -EIO; - break; - } - 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; - } up_read(&tty->termios_rwsem); + tty_buffer_flush_work(tty->port); + down_read(&tty->termios_rwsem); + if (!input_available_p(tty, 0)) { + if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { + retval = -EIO; + break; + } + 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; + } + up_read(&tty->termios_rwsem); - timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, - timeout); + timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, + timeout); - down_read(&tty->termios_rwsem); - continue; + down_read(&tty->termios_rwsem); + continue; + } } if (ldata->icanon && !L_EXTPROC(tty)) { @@ -2446,12 +2437,17 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, poll_wait(file, &tty->read_wait, wait); poll_wait(file, &tty->write_wait, wait); - if (check_other_done(tty)) - mask |= POLLHUP; if (input_available_p(tty, 1)) mask |= POLLIN | POLLRDNORM; + else { + tty_buffer_flush_work(tty->port); + if (input_available_p(tty, 1)) + mask |= POLLIN | POLLRDNORM; + } if (tty->packet && tty->link->ctrl_status) mask |= POLLPRI | POLLIN | POLLRDNORM; + if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) + mask |= POLLHUP; if (tty_hung_up_p(file)) mask |= POLLHUP; if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 78e983677339..7865228f664f 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -59,7 +59,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp) if (!tty->link) return; set_bit(TTY_OTHER_CLOSED, &tty->link->flags); - tty_flip_buffer_push(tty->link->port); + wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->write_wait); if (tty->driver->subtype == PTY_TYPE_MASTER) { set_bit(TTY_OTHER_CLOSED, &tty->flags); @@ -247,9 +247,7 @@ static int pty_open(struct tty_struct *tty, struct file *filp) goto out; clear_bit(TTY_IO_ERROR, &tty->flags); - /* TTY_OTHER_CLOSED must be cleared before TTY_OTHER_DONE */ clear_bit(TTY_OTHER_CLOSED, &tty->link->flags); - clear_bit(TTY_OTHER_DONE, &tty->link->flags); set_bit(TTY_THROTTLED, &tty->flags); return 0; diff --git a/drivers/tty/serial/8250/8250_mid.c b/drivers/tty/serial/8250/8250_mid.c index 88531a36b69c..ed489880e62b 100644 --- a/drivers/tty/serial/8250/8250_mid.c +++ b/drivers/tty/serial/8250/8250_mid.c @@ -14,6 +14,7 @@ #include <linux/pci.h> #include <linux/dma/hsu.h> +#include <linux/8250_pci.h> #include "8250.h" @@ -24,6 +25,7 @@ #define PCI_DEVICE_ID_INTEL_DNV_UART 0x19d8 /* Intel MID Specific registers */ +#define INTEL_MID_UART_DNV_FISR 0x08 #define INTEL_MID_UART_PS 0x30 #define INTEL_MID_UART_MUL 0x34 #define INTEL_MID_UART_DIV 0x38 @@ -31,6 +33,7 @@ struct mid8250; struct mid8250_board { + unsigned int flags; unsigned long freq; unsigned int base_baud; int (*setup)(struct mid8250 *, struct uart_port *p); @@ -88,16 +91,16 @@ static int tng_setup(struct mid8250 *mid, struct uart_port *p) static int dnv_handle_irq(struct uart_port *p) { struct mid8250 *mid = p->private_data; - int ret; - - ret = hsu_dma_irq(&mid->dma_chip, 0); - ret |= hsu_dma_irq(&mid->dma_chip, 1); - - /* For now, letting the HW generate separate interrupt for the UART */ - if (ret) - return ret; - - return serial8250_handle_irq(p, serial_port_in(p, UART_IIR)); + unsigned int fisr = serial_port_in(p, INTEL_MID_UART_DNV_FISR); + int ret = IRQ_NONE; + + if (fisr & BIT(2)) + ret |= hsu_dma_irq(&mid->dma_chip, 1); + if (fisr & BIT(1)) + ret |= hsu_dma_irq(&mid->dma_chip, 0); + if (fisr & BIT(0)) + ret |= serial8250_handle_irq(p, serial_port_in(p, UART_IIR)); + return ret; } #define DNV_DMA_CHAN_OFFSET 0x80 @@ -106,12 +109,13 @@ static int dnv_setup(struct mid8250 *mid, struct uart_port *p) { struct hsu_dma_chip *chip = &mid->dma_chip; struct pci_dev *pdev = to_pci_dev(p->dev); + unsigned int bar = FL_GET_BASE(mid->board->flags); int ret; chip->dev = &pdev->dev; chip->irq = pdev->irq; chip->regs = p->membase; - chip->length = pci_resource_len(pdev, 0); + chip->length = pci_resource_len(pdev, bar); chip->offset = DNV_DMA_CHAN_OFFSET; /* Falling back to PIO mode if DMA probing fails */ @@ -217,6 +221,7 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct uart_8250_port uart; struct mid8250 *mid; + unsigned int bar; int ret; ret = pcim_enable_device(pdev); @@ -230,6 +235,7 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) return -ENOMEM; mid->board = (struct mid8250_board *)id->driver_data; + bar = FL_GET_BASE(mid->board->flags); memset(&uart, 0, sizeof(struct uart_8250_port)); @@ -242,8 +248,8 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE; uart.port.set_termios = mid8250_set_termios; - uart.port.mapbase = pci_resource_start(pdev, 0); - uart.port.membase = pcim_iomap(pdev, 0, 0); + uart.port.mapbase = pci_resource_start(pdev, bar); + uart.port.membase = pcim_iomap(pdev, bar, 0); if (!uart.port.membase) return -ENOMEM; @@ -282,18 +288,21 @@ static void mid8250_remove(struct pci_dev *pdev) } static const struct mid8250_board pnw_board = { + .flags = FL_BASE0, .freq = 50000000, .base_baud = 115200, .setup = pnw_setup, }; static const struct mid8250_board tng_board = { + .flags = FL_BASE0, .freq = 38400000, .base_baud = 1843200, .setup = tng_setup, }; static const struct mid8250_board dnv_board = { + .flags = FL_BASE1, .freq = 133333333, .base_baud = 115200, .setup = dnv_setup, diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 7cd6f9a90542..c1d4a8fa9be8 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1401,6 +1401,9 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios, unsigned long m, n; u32 reg; + /* Gracefully handle the B0 case: fall back to B9600 */ + fuart = fuart ? fuart : 9600 * 16; + /* Get Fuart closer to Fref */ fuart *= rounddown_pow_of_two(fref / fuart); diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 94294558943c..7bbadd176c74 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -277,6 +277,13 @@ static bool atmel_use_dma_rx(struct uart_port *port) return atmel_port->use_dma_rx; } +static bool atmel_use_fifo(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + + return atmel_port->fifo_size; +} + static unsigned int atmel_get_lines_status(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); @@ -2169,7 +2176,12 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, mode |= ATMEL_US_USMODE_RS485; } else if (termios->c_cflag & CRTSCTS) { /* RS232 with hardware handshake (RTS/CTS) */ - mode |= ATMEL_US_USMODE_HWHS; + if (atmel_use_dma_rx(port) && !atmel_use_fifo(port)) { + dev_info(port->dev, "not enabling hardware flow control because DMA is used"); + termios->c_cflag &= ~CRTSCTS; + } else { + mode |= ATMEL_US_USMODE_HWHS; + } } else { /* RS232 without hadware handshake */ mode |= ATMEL_US_USMODE_NORMAL; diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index fd9c47f2f29f..c8ab5370670d 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1263,6 +1263,8 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, /* check to see if we need to change clock source */ if (ourport->baudclk != clk) { + clk_prepare_enable(clk); + s3c24xx_serial_setsource(port, clk_sel); if (!IS_ERR(ourport->baudclk)) { @@ -1270,8 +1272,6 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, ourport->baudclk = ERR_PTR(-EINVAL); } - clk_prepare_enable(clk); - ourport->baudclk = clk; ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0; } diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index 73190f5d2832..71d26c8e1b8f 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c @@ -1478,6 +1478,9 @@ static const struct of_device_id ucc_uart_match[] = { .type = "serial", .compatible = "ucc_uart", }, + { + .compatible = "fsl,t1040-ucc-uart", + }, {}, }; MODULE_DEVICE_TABLE(of, ucc_uart_match); diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 3cd31e0d4bd9..fb31eecb708d 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -37,29 +37,6 @@ #define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF) -/* - * If all tty flip buffers have been processed by flush_to_ldisc() or - * dropped by tty_buffer_flush(), check if the linked pty has been closed. - * If so, wake the reader/poll to process - */ -static inline void check_other_closed(struct tty_struct *tty) -{ - unsigned long flags, old; - - /* transition from TTY_OTHER_CLOSED => TTY_OTHER_DONE must be atomic */ - for (flags = ACCESS_ONCE(tty->flags); - test_bit(TTY_OTHER_CLOSED, &flags); - ) { - old = flags; - __set_bit(TTY_OTHER_DONE, &flags); - flags = cmpxchg(&tty->flags, old, flags); - if (old == flags) { - wake_up_interruptible(&tty->read_wait); - break; - } - } -} - /** * tty_buffer_lock_exclusive - gain exclusive access to buffer * tty_buffer_unlock_exclusive - release exclusive access @@ -254,8 +231,6 @@ void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld) if (ld && ld->ops->flush_buffer) ld->ops->flush_buffer(tty); - check_other_closed(tty); - atomic_dec(&buf->priority); mutex_unlock(&buf->lock); } @@ -505,10 +480,8 @@ static void flush_to_ldisc(struct work_struct *work) */ count = smp_load_acquire(&head->commit) - head->read; if (!count) { - if (next == NULL) { - check_other_closed(tty); + if (next == NULL) break; - } buf->head = next; tty_buffer_free(port, head); continue; @@ -597,3 +570,8 @@ bool tty_buffer_cancel_work(struct tty_port *port) { return cancel_work_sync(&port->buf.work); } + +void tty_buffer_flush_work(struct tty_port *port) +{ + flush_work(&port->buf.work); +} diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 6f0336fff501..41987a55a538 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -366,34 +366,22 @@ static void to_utf8(struct vc_data *vc, uint c) static void do_compute_shiftstate(void) { - unsigned int i, j, k, sym, val; + unsigned int k, sym, val; shift_state = 0; memset(shift_down, 0, sizeof(shift_down)); - for (i = 0; i < ARRAY_SIZE(key_down); i++) { - - if (!key_down[i]) + for_each_set_bit(k, key_down, min(NR_KEYS, KEY_CNT)) { + sym = U(key_maps[0][k]); + if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK) continue; - k = i * BITS_PER_LONG; - - for (j = 0; j < BITS_PER_LONG; j++, k++) { - - if (!test_bit(k, key_down)) - continue; + val = KVAL(sym); + if (val == KVAL(K_CAPSSHIFT)) + val = KVAL(K_SHIFT); - sym = U(key_maps[0][k]); - if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK) - continue; - - val = KVAL(sym); - if (val == KVAL(K_CAPSSHIFT)) - val = KVAL(K_SHIFT); - - shift_down[val]++; - shift_state |= (1 << val); - } + shift_down[val]++; + shift_state |= BIT(val); } } diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 4462d167900c..136ebaaa9cc0 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -750,6 +750,7 @@ static void visual_init(struct vc_data *vc, int num, int init) vc->vc_complement_mask = 0; vc->vc_can_do_color = 0; vc->vc_panic_force_write = false; + vc->vc_cur_blink_ms = DEFAULT_CURSOR_BLINK_MS; vc->vc_sw->con_init(vc, init); if (!vc->vc_complement_mask) vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; @@ -3583,9 +3584,10 @@ static int do_register_con_driver(const struct consw *csw, int first, int last) goto err; desc = csw->con_startup(); - - if (!desc) + if (!desc) { + retval = -ENODEV; goto err; + } retval = -EINVAL; |