From 3b19e032295647b7be2aa3be62510db4aaeda759 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 27 Jun 2015 09:21:32 -0400 Subject: [PATCH 01/10] n_tty: signal and flush atomically When handling signalling char, claim the termios write lock before signalling waiting readers and writers to prevent further i/o before flushing the echo and output buffers. This prevents a userspace signal handler which may output from racing the terminal flush. Reference: Bugzilla #99351 ("Output truncated in ssh session after...") Fixes: commit d2b6f44779d3 ("n_tty: Fix signal handling flushes") Reported-by: Filipe Brandenburger Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index c9c27f69e101..ee8bfacf2071 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1108,19 +1108,29 @@ static void eraser(unsigned char c, struct tty_struct *tty) * Locking: ctrl_lock */ -static void isig(int sig, struct tty_struct *tty) +static void __isig(int sig, struct tty_struct *tty) { - struct n_tty_data *ldata = tty->disc_data; struct pid *tty_pgrp = tty_get_pgrp(tty); if (tty_pgrp) { kill_pgrp(tty_pgrp, sig, 1); put_pid(tty_pgrp); } +} - if (!L_NOFLSH(tty)) { +static void isig(int sig, struct tty_struct *tty) +{ + struct n_tty_data *ldata = tty->disc_data; + + if (L_NOFLSH(tty)) { + /* signal only */ + __isig(sig, tty); + + } else { /* signal and flush */ up_read(&tty->termios_rwsem); down_write(&tty->termios_rwsem); + __isig(sig, tty); + /* clear echo buffer */ mutex_lock(&ldata->output_lock); ldata->echo_head = ldata->echo_tail = 0; From 97a60eac33f663d2150ee1b3c69253d87ba53dff Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 9 Jul 2015 22:21:41 +0900 Subject: [PATCH 02/10] serial: amba-pl011: Fix devm_ioremap_resource return value check Value returned by devm_ioremap_resource() was checked for non-NULL but devm_ioremap_resource() returns IOMEM_ERR_PTR, not NULL. In case of error this could lead to dereference of ERR_PTR. Signed-off-by: Krzysztof Kozlowski Cc: Fixes: 3873e2d7f63a ("drivers: PL011: refactor pl011_probe()") Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 50cf5b10ceed..fd27e986b1dd 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2310,8 +2310,8 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, void __iomem *base; base = devm_ioremap_resource(dev, mmiobase); - if (!base) - return -ENOMEM; + if (IS_ERR(base)) + return PTR_ERR(base); index = pl011_probe_dt_alias(index, dev); From 08b33249d89700ba555d4ab5cc88714192b8ee46 Mon Sep 17 00:00:00 2001 From: Dongxing Zhang Date: Wed, 10 Jun 2015 15:21:10 +0800 Subject: [PATCH 03/10] tty/vt: Fix the memory leak in visual_init If vc->vc_uni_pagedir_loc is not NULL, its refcount needs to be decreased before vc_uni_pagedir_loc is re-assigned. unreferenced object 0xffff88002cdd13b0 (size 512): comm "setfont", pid 503, jiffies 4294896503 (age 722.828s) hex dump (first 32 bytes): 40 92 61 2b 00 88 ff ff 00 00 00 00 00 00 00 00 @.a+............ 00 00 00 00 00 00 00 00 a0 ad 61 2b 00 88 ff ff ..........a+.... backtrace: [] kmemleak_alloc+0x4e/0xb0 [] kmem_cache_alloc_trace+0x1c8/0x240 [] con_do_clear_unimap.isra.2+0x83/0xe0 [] con_clear_unimap+0x22/0x40 [] vt_ioctl+0xeb8/0x1170 [] tty_ioctl+0x208/0xca0 [] do_vfs_ioctl+0x2f8/0x510 [] SyS_ioctl+0x81/0xa0 [] system_call_fastpath+0x16/0x75 [] 0xffffffffffffffff unreferenced object 0xffff88002b619240 (size 256): comm "setfont", pid 503, jiffies 4294896503 (age 722.828s) hex dump (first 32 bytes): 90 bc 84 d5 00 88 ff ff 58 85 84 d5 00 88 ff ff ........X....... 88 ac 84 d5 00 88 ff ff e0 b1 84 d5 00 88 ff ff ................ backtrace: [] kmemleak_alloc+0x4e/0xb0 [] kmem_cache_alloc_trace+0x1c8/0x240 [] con_insert_unipair+0x86/0x170 [] con_set_unimap+0x1b7/0x280 [] vt_ioctl+0xe65/0x1170 [] tty_ioctl+0x208/0xca0 [] do_vfs_ioctl+0x2f8/0x510 [] SyS_ioctl+0x81/0xa0 [] system_call_fastpath+0x16/0x75 [] 0xffffffffffffffff Signed-off-by: Dongxing Zhang Signed-off-by: Xiaoming Wang Reviewed-by: Peter Hurley Tested-by: Konstantin Khlebnikov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 8fe52989b380..4462d167900c 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -742,6 +742,8 @@ static void visual_init(struct vc_data *vc, int num, int init) __module_get(vc->vc_sw->owner); vc->vc_num = num; vc->vc_display_fg = &master_display_fg; + if (vc->vc_uni_pagedir_loc) + con_free_unimap(vc); vc->vc_uni_pagedir_loc = &vc->vc_uni_pagedir; vc->vc_uni_pagedir = NULL; vc->vc_hi_font_mask = 0; From d8c2c0d89205a3538c5fd77dc9d4767ee6bebc70 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 28 Jun 2015 09:45:08 +0800 Subject: [PATCH 04/10] serial: etraxfs-uart: Fix release etraxfs_uart_ports In probe, we use dev_id as array index of etraxfs_uart_ports and store the index in port->line. So etraxfs_uart_ports[port->line] should be released when unload the module. Signed-off-by: Axel Lin Acked-by: Niklas Cassel Acked-by: Jesper Nilsson Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/etraxfs-uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/etraxfs-uart.c b/drivers/tty/serial/etraxfs-uart.c index a57301a6fe42..679709f51fd4 100644 --- a/drivers/tty/serial/etraxfs-uart.c +++ b/drivers/tty/serial/etraxfs-uart.c @@ -950,7 +950,7 @@ static int etraxfs_uart_remove(struct platform_device *pdev) port = platform_get_drvdata(pdev); uart_remove_one_port(&etraxfs_uart_driver, port); - etraxfs_uart_ports[pdev->id] = NULL; + etraxfs_uart_ports[port->line] = NULL; return 0; } From 32aa6339d9c5156de5d881b103e0e360934d6a74 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 1 Jul 2015 14:19:52 +0200 Subject: [PATCH 05/10] sc16is7xx: fix Kconfig dependencies When I2C=m and SPI=y or-ing them will produce =y while what we need is the lower bound, i.e. =m. Fortunately SPI is a boolean so we need to handle only one special case. Reported-by: kbuild test robot Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 76e65b714471..15b4079a335e 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1185,7 +1185,7 @@ config SERIAL_SC16IS7XX_CORE config SERIAL_SC16IS7XX tristate "SC16IS7xx serial support" select SERIAL_CORE - depends on I2C || SPI_MASTER + depends on (SPI_MASTER && !I2C) || I2C help This selects support for SC16IS7xx serial ports. Supported ICs are SC16IS740, SC16IS741, SC16IS750, SC16IS752, From dec273ecc1169ade46999bb0feca3814915f5c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bo=20Svang=C3=A5rd?= Date: Sat, 13 Jun 2015 13:40:20 +0200 Subject: [PATCH 06/10] sc16is7xx: fix FIFO address of secondary UART MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calls to regmap_raw_read/write needed register rewrite in a similar way as function calls to regmap_read/write already had. This enables reading/writing the serial datastream to the device. Signed-off-by: Bo Svangård Signed-off-by: Jakub Kicinski Signed-off-by: Jon Ringle Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sc16is7xx.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 9e6576004a42..5ccc698cbbfa 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -354,6 +354,26 @@ static void sc16is7xx_port_write(struct uart_port *port, u8 reg, u8 val) (reg << SC16IS7XX_REG_SHIFT) | port->line, val); } +static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen) +{ + struct sc16is7xx_port *s = dev_get_drvdata(port->dev); + u8 addr = (SC16IS7XX_RHR_REG << SC16IS7XX_REG_SHIFT) | port->line; + + regcache_cache_bypass(s->regmap, true); + regmap_raw_read(s->regmap, addr, s->buf, rxlen); + regcache_cache_bypass(s->regmap, false); +} + +static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send) +{ + struct sc16is7xx_port *s = dev_get_drvdata(port->dev); + u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | port->line; + + regcache_cache_bypass(s->regmap, true); + regmap_raw_write(s->regmap, addr, s->buf, to_send); + regcache_cache_bypass(s->regmap, false); +} + static void sc16is7xx_port_update(struct uart_port *port, u8 reg, u8 mask, u8 val) { @@ -508,10 +528,7 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, s->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG); bytes_read = 1; } else { - regcache_cache_bypass(s->regmap, true); - regmap_raw_read(s->regmap, SC16IS7XX_RHR_REG, - s->buf, rxlen); - regcache_cache_bypass(s->regmap, false); + sc16is7xx_fifo_read(port, rxlen); bytes_read = rxlen; } @@ -591,9 +608,8 @@ static void sc16is7xx_handle_tx(struct uart_port *port) s->buf[i] = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); } - regcache_cache_bypass(s->regmap, true); - regmap_raw_write(s->regmap, SC16IS7XX_THR_REG, s->buf, to_send); - regcache_cache_bypass(s->regmap, false); + + sc16is7xx_fifo_write(port, to_send); } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) From 907eda32a36fcdb979bdb91ea097abb3dd2c23c9 Mon Sep 17 00:00:00 2001 From: David Jander Date: Fri, 26 Jun 2015 08:11:30 +0200 Subject: [PATCH 07/10] Revert "serial: imx: initialized DMA w/o HW flow enabled" This reverts commit 068500e08dc87ea9a453cc4a500cf3ab28d0f936. According to some tests, SDMA support is broken at least for i.MX6 without HW flow control. Different forms of data-corruption appear either with the ROM firmware for the SDMA controller as well as when loading Freescale provided SDMA firmware versions 1.1 or 3.1. Signed-off-by: David Jander Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 2c90dc31bfaa..54fdc7866ea1 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1121,11 +1121,6 @@ static int imx_startup(struct uart_port *port) writel(temp & ~UCR4_DREN, sport->port.membase + UCR4); - /* Can we enable the DMA support? */ - if (is_imx6q_uart(sport) && !uart_console(port) && - !sport->dma_is_inited) - imx_uart_dma_init(sport); - spin_lock_irqsave(&sport->port.lock, flags); /* Reset fifo's and state machines */ i = 100; @@ -1143,9 +1138,6 @@ static int imx_startup(struct uart_port *port) writel(USR1_RTSD, sport->port.membase + USR1); writel(USR2_ORE, sport->port.membase + USR2); - if (sport->dma_is_inited && !sport->dma_is_enabled) - imx_enable_dma(sport); - temp = readl(sport->port.membase + UCR1); temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN; @@ -1316,6 +1308,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, } else { ucr2 |= UCR2_CTSC; } + + /* Can we enable the DMA support? */ + if (is_imx6q_uart(sport) && !uart_console(port) + && !sport->dma_is_inited) + imx_uart_dma_init(sport); } else { termios->c_cflag &= ~CRTSCTS; } @@ -1432,6 +1429,8 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) imx_enable_ms(&sport->port); + if (sport->dma_is_inited && !sport->dma_is_enabled) + imx_enable_dma(sport); spin_unlock_irqrestore(&sport->port.lock, flags); } From 7525a9901b5ee3c84933ad069e41506c37404ddc Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 8 Jul 2015 23:10:06 -0400 Subject: [PATCH 08/10] m32r: Add ioreadXX/iowriteXX big-endian mmio accessors commit c627f2ceb692 ("serial: 8250: Add support for big-endian MMIO accesses") added support for 32-bit big-endian mmio to the 8250 driver. Support for ioreadXXbe/iowriteXXbe io accessors was missing from m32r arch, which caused build errors. Add trivial macro mmio accessors. Reported-by: Fengguang Wu Cc: Kevin Cernekee Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- arch/m32r/include/asm/io.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/m32r/include/asm/io.h b/arch/m32r/include/asm/io.h index 0c3f25ee3381..f8de767ce2bc 100644 --- a/arch/m32r/include/asm/io.h +++ b/arch/m32r/include/asm/io.h @@ -174,6 +174,11 @@ static inline void _writel(unsigned long l, unsigned long addr) #define iowrite16 writew #define iowrite32 writel +#define ioread16be(addr) be16_to_cpu(readw(addr)) +#define ioread32be(addr) be32_to_cpu(readl(addr)) +#define iowrite16be(v, addr) writew(cpu_to_be16(v), (addr)) +#define iowrite32be(v, addr) writel(cpu_to_be32(v), (addr)) + #define mmiowb() #define flush_write_buffers() do { } while (0) /* M32R_FIXME */ From e144c58cad6667876173dd76977e9e6557e34941 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 12 Jul 2015 21:05:26 -0400 Subject: [PATCH 09/10] serial: core: Fix crashes while echoing when closing While closing, new rx data may be received after the input buffers have been flushed but before stop_rx() halts receiving [1]. The new data might not be processed by flush_to_ldisc() until after uart_shutdown() and normal input processing is re-enabled (ie., tty->closing = 0). The race is outlined below: CPU 0 | CPU 1 | uart_close() | tty_port_close_start() | tty->closing = 1 | tty_ldisc_flush() | | => IRQ | while (LSR & data ready) | uart_insert_char() | tty_flip_buffer_push() | <= EOI stop_rx() | . uart_shutdown() | . free xmit.buf | . tty_port_tty_set(NULL) | . tty->closing = 0 | . | flush_to_ldisc() | n_tty_receive_buf_common() | __receive_buf() | ... | commit_echoes() | uart_flush_chars() | __uart_start() | ** OOPS on port.tty deref ** tty_ldisc_flush() | Input processing must be prevented from echoing (tty->closing = 1) until _after_ the input buffers have been flushed again at the end of uart_close(). [1] In fact, some input may actually be buffered _after_ stop_rx() since the rx interrupt may have already triggered but not yet been handled when stop_rx() disables rx interrupts. Fixes: 2e758910832d ("serial: core: Flush ldisc after dropping port mutex in uart_close()") Reported-by: Robert Elliott Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 7ae1592f7ec9..f36852067f20 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1418,7 +1418,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) mutex_lock(&port->mutex); uart_shutdown(tty, state); tty_port_tty_set(port, NULL); - tty->closing = 0; + spin_lock_irqsave(&port->lock, flags); if (port->blocked_open) { @@ -1444,6 +1444,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) mutex_unlock(&port->mutex); tty_ldisc_flush(tty); + tty->closing = 0; } static void uart_wait_until_sent(struct tty_struct *tty, int timeout) From 61e86cc90af49cecef9c54ccea1f572fbcb695ac Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 12 Jul 2015 20:47:35 -0400 Subject: [PATCH 10/10] tty: vt: Fix !TASK_RUNNING diagnostic warning from paste_selection() Pasting text with gpm on a VC produced warning [1]. Reset task state to TASK_RUNNING in the paste_selection() loop, if the loop did not sleep. [1] WARNING: CPU: 6 PID: 1960 at /home/peter/src/kernels/mainline/kernel/sched/core.c:7286 __might_sleep+0x7f/0x90() do not call blocking ops when !TASK_RUNNING; state=1 set at [] paste_selection+0x9e/0x1a0 Modules linked in: btrfs xor raid6_pq ufs qnx4 hfsplus hfs minix ntfs msdos jfs xfs libcrc32c ..... CPU: 6 PID: 1960 Comm: gpm Not tainted 4.1.0-rc7+tty-xeon+debug #rc7+tty Hardware name: Dell Inc. Precision WorkStation T5400 /0RW203, BIOS A11 04/30/2012 ffffffff81c9c0a0 ffff8802b0fd3ac8 ffffffff8185778a 0000000000000001 ffff8802b0fd3b18 ffff8802b0fd3b08 ffffffff8108039a ffffffff82ae8510 ffffffff81c9ce00 0000000000000015 0000000000000000 0000000000000000 Call Trace: [] dump_stack+0x4f/0x7b [] warn_slowpath_common+0x8a/0xc0 [] warn_slowpath_fmt+0x46/0x50 [] ? __lock_acquire+0xe2d/0x13a0 [] ? paste_selection+0x9e/0x1a0 [] ? paste_selection+0x9e/0x1a0 [] __might_sleep+0x7f/0x90 [] down_read+0x2a/0xa0 [] ? sched_clock_cpu+0xb8/0xe0 [] n_tty_receive_buf_common+0x4c/0xba0 [] ? mark_held_locks+0x75/0xa0 [] ? _raw_spin_unlock_irqrestore+0x65/0x80 [] ? get_parent_ip+0x11/0x50 [] n_tty_receive_buf2+0x14/0x20 [] paste_selection+0x157/0x1a0 [] ? wake_up_state+0x20/0x20 [] tioclinux+0xb8/0x2c0 [] vt_ioctl+0xaee/0x11a0 [] ? sched_clock_local+0x25/0x90 [] ? vtime_account_user+0x91/0xa0 [] tty_ioctl+0x20c/0xe20 [] ? vtime_account_user+0x91/0xa0 [] ? get_parent_ip+0x11/0x50 [] ? preempt_count_sub+0x49/0x50 [] ? context_tracking_exit+0x5c/0x290 [] ? context_tracking_exit+0x5c/0x290 [] do_vfs_ioctl+0x318/0x570 [] ? trace_hardirqs_on+0xd/0x10 [] ? trace_hardirqs_on_caller+0x115/0x1e0 [] ? __fget_light+0x6c/0xa0 [] SyS_ioctl+0x81/0xa0 [] system_call_fastpath+0x16/0x7a Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/selection.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index ea27804d87af..381a2b13682c 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -356,6 +356,7 @@ int paste_selection(struct tty_struct *tty) schedule(); continue; } + __set_current_state(TASK_RUNNING); count = sel_buffer_lth - pasted; count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, NULL, count);