From 2b01bfaeb41e1563322448d9b392ac924cbf22ef Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 17 Jul 2017 11:12:38 +0300 Subject: serial: st-asc: Potential error pointer dereference It looks like we intended to return an error code here, because we dereference "ascport->pinctrl" on the next lines. Fixes: 6929cb00a501 ("serial: st-asc: Read in all Pinctrl states") Signed-off-by: Dan Carpenter Acked-by: Lee Jones Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/st-asc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index f5335be344f6..6b0ca65027d0 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -758,6 +758,7 @@ static int asc_init_port(struct asc_port *ascport, if (IS_ERR(ascport->pinctrl)) { ret = PTR_ERR(ascport->pinctrl); dev_err(&pdev->dev, "Failed to get Pinctrl: %d\n", ret); + return ret; } ascport->states[DEFAULT] = -- cgit v1.2.3 From 4ab3c51e0540ba8464fe34d84cc35821bb77ae92 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 17 Jul 2017 11:34:23 +0300 Subject: serial: sh-sci: Uninitialized variables in sysfs files The kstrtol() function returns -ERANGE as well as -EINVAL so these tests are not enough. It's not a super serious bug, but my static checker correctly complains that the "r" variable might be used uninitialized. Fixes: 5d23188a473d ("serial: sh-sci: make RX FIFO parameters tunable via sysfs") Signed-off-by: Dan Carpenter Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index da5ddfc14778..e08b16b070c0 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1085,10 +1085,12 @@ static ssize_t rx_trigger_store(struct device *dev, { struct uart_port *port = dev_get_drvdata(dev); struct sci_port *sci = to_sci_port(port); + int ret; long r; - if (kstrtol(buf, 0, &r) == -EINVAL) - return -EINVAL; + ret = kstrtol(buf, 0, &r); + if (ret) + return ret; sci->rx_trigger = scif_set_rtrg(port, r); if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) @@ -1116,10 +1118,12 @@ static ssize_t rx_fifo_timeout_store(struct device *dev, { struct uart_port *port = dev_get_drvdata(dev); struct sci_port *sci = to_sci_port(port); + int ret; long r; - if (kstrtol(buf, 0, &r) == -EINVAL) - return -EINVAL; + ret = kstrtol(buf, 0, &r); + if (ret) + return ret; sci->rx_fifo_timeout = r; scif_set_rtrg(port, 1); if (r > 0) -- cgit v1.2.3 From 351ea50df545a4acaf8f61784949ceedbe923f03 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Jul 2017 13:48:58 +0200 Subject: Revert "serial: imx-serial - move DMA buffer configuration to DT" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit a3015affdf76ef279fbbb3710a220bab7e9ea04b as there are complaints that it is incorrect. Reported-by: Uwe Kleine-König Cc: Nandor Han Cc: Romain Perier Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- .../devicetree/bindings/serial/fsl-imx-uart.txt | 2 -- drivers/tty/serial/imx.c | 25 +++++++--------------- 2 files changed, 8 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt b/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt index e6b572409cf5..574c3a2c77d5 100644 --- a/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt +++ b/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt @@ -9,7 +9,6 @@ Optional properties: - fsl,irda-mode : Indicate the uart supports irda mode - fsl,dte-mode : Indicate the uart works in DTE mode. The uart works in DCE mode by default. -- fsl,dma-size : Indicate the size of the DMA buffer and its periods Please check Documentation/devicetree/bindings/serial/serial.txt for the complete list of generic properties. @@ -29,5 +28,4 @@ uart1: serial@73fbc000 { interrupts = <31>; uart-has-rtscts; fsl,dte-mode; - fsl,dma-size = <1024 4>; }; diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 9e3162bf3bd1..e33da75ceac5 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -186,11 +186,6 @@ #define UART_NR 8 -/* RX DMA buffer periods */ -#define RX_DMA_PERIODS 4 -#define RX_BUF_SIZE (PAGE_SIZE) - - /* i.MX21 type uart runs on all i.mx except i.MX1 and i.MX6q */ enum imx_uart_type { IMX1_UART, @@ -226,7 +221,6 @@ struct imx_port { struct dma_chan *dma_chan_rx, *dma_chan_tx; struct scatterlist rx_sgl, tx_sgl[2]; void *rx_buf; - unsigned int rx_buf_size; struct circ_buf rx_ring; unsigned int rx_periods; dma_cookie_t rx_cookie; @@ -967,6 +961,8 @@ static void imx_timeout(unsigned long data) } } +#define RX_BUF_SIZE (PAGE_SIZE) + /* * There are two kinds of RX DMA interrupts(such as in the MX6Q): * [1] the RX DMA buffer is full. @@ -1049,6 +1045,9 @@ static void dma_rx_callback(void *data) } } +/* RX DMA buffer periods */ +#define RX_DMA_PERIODS 4 + static int start_rx_dma(struct imx_port *sport) { struct scatterlist *sgl = &sport->rx_sgl; @@ -1059,8 +1058,9 @@ static int start_rx_dma(struct imx_port *sport) sport->rx_ring.head = 0; sport->rx_ring.tail = 0; + sport->rx_periods = RX_DMA_PERIODS; - sg_init_one(sgl, sport->rx_buf, sport->rx_buf_size); + sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE); ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE); if (ret == 0) { dev_err(dev, "DMA mapping error for RX.\n"); @@ -1171,7 +1171,7 @@ static int imx_uart_dma_init(struct imx_port *sport) goto err; } - sport->rx_buf = kzalloc(sport->rx_buf_size, GFP_KERNEL); + sport->rx_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!sport->rx_buf) { ret = -ENOMEM; goto err; @@ -2036,7 +2036,6 @@ static int serial_imx_probe_dt(struct imx_port *sport, { struct device_node *np = pdev->dev.of_node; int ret; - u32 dma_buf_size[2]; sport->devdata = of_device_get_match_data(&pdev->dev); if (!sport->devdata) @@ -2060,14 +2059,6 @@ static int serial_imx_probe_dt(struct imx_port *sport, if (of_get_property(np, "rts-gpios", NULL)) sport->have_rtsgpio = 1; - if (!of_property_read_u32_array(np, "fsl,dma-size", dma_buf_size, 2)) { - sport->rx_buf_size = dma_buf_size[0] * dma_buf_size[1]; - sport->rx_periods = dma_buf_size[1]; - } else { - sport->rx_buf_size = RX_BUF_SIZE; - sport->rx_periods = RX_DMA_PERIODS; - } - return 0; } #else -- cgit v1.2.3 From 514ab34dbad6c6fa824a1f56984c196e59082346 Mon Sep 17 00:00:00 2001 From: Ian Jamison Date: Fri, 14 Jul 2017 17:31:57 +0100 Subject: serial: imx: Prevent TX buffer PIO write when a DMA has been started Function imx_transmit_buffer starts a TX DMA if DMA is enabled, since commit 91a1a909f921 ("serial: imx: Support sw flow control in DMA mode"). It also carries on and attempts to write the same TX buffer using PIO. This results in TX data corruption and double-incrementing xmit->tail with the knock-on effect of tail passing head and a page of garbage being sent out. This seems to be triggered mostly when using RS485 half duplex on SMP systems, but is probably not limited to just those. Tested locally on an i.MX6Q with an RS485 half duplex transceiver on UART3, and also by Clemens Gruber. Tested-by: Clemens Gruber Signed-off-by: Ian Jamison Reviewed-by: Fabio Estevam Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index e33da75ceac5..80934e7bd67f 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -458,7 +458,7 @@ static inline void imx_transmit_buffer(struct imx_port *sport) } } - while (!uart_circ_empty(xmit) && + while (!uart_circ_empty(xmit) && !sport->dma_is_txing && !(readl(sport->port.membase + uts_reg(sport)) & UTS_TXFULL)) { /* send xmit->buf[xmit->tail] * out the port here */ -- cgit v1.2.3 From 3ee5447e8cd9a65d08fbb49fa9767cbf7fef6d91 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 11 Jul 2017 08:03:43 -0300 Subject: tty: serial: lpuart: Fix the logic for detecting the 32-bit type UART Commit 0d6fce904452 ("tty: serial: lpuart: introduce lpuart_soc_data to represent SoC property") introduced a buggy logic for detecting the 32-bit type UART since the condition: "if (sport->port.iotype & UPIO_MEM32BE)" is always true. Performing such bitfield AND operation is not correct, because in the case of Vybrid UART iotype is UPIO_MEM (2), so: UPIO_MEM & UPIO_MEM32BE = 010 & 110 = 010, which is true. Such logic tells the driver to always treat the UART operations as 32-bit, leading to the driver misbehavior on Vybrid. Fix the 32-bit type detection logic to avoid UART breakage on Vybrid. While at it, introduce a lpuart_is_32() function to help readability. Fixes: 0d6fce904452 ("tty: serial: lpuart: introduce lpuart_soc_data to represent SoC property") Reported-by: Vivien Didelot Signed-off-by: Fabio Estevam Reviewed-by: Dong Aisheng Tested-by: Vivien Didelot Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 343de8c384b0..898dcb091a27 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -619,6 +619,12 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port) TIOCSER_TEMT : 0; } +static bool lpuart_is_32(struct lpuart_port *sport) +{ + return sport->port.iotype == UPIO_MEM32 || + sport->port.iotype == UPIO_MEM32BE; +} + static irqreturn_t lpuart_txint(int irq, void *dev_id) { struct lpuart_port *sport = dev_id; @@ -627,7 +633,7 @@ static irqreturn_t lpuart_txint(int irq, void *dev_id) spin_lock_irqsave(&sport->port.lock, flags); if (sport->port.x_char) { - if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) + if (lpuart_is_32(sport)) lpuart32_write(&sport->port, sport->port.x_char, UARTDATA); else writeb(sport->port.x_char, sport->port.membase + UARTDR); @@ -635,14 +641,14 @@ static irqreturn_t lpuart_txint(int irq, void *dev_id) } if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { - if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) + if (lpuart_is_32(sport)) lpuart32_stop_tx(&sport->port); else lpuart_stop_tx(&sport->port); goto out; } - if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) + if (lpuart_is_32(sport)) lpuart32_transmit_buffer(sport); else lpuart_transmit_buffer(sport); @@ -1978,12 +1984,12 @@ static int __init lpuart_console_setup(struct console *co, char *options) if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else - if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) + if (lpuart_is_32(sport)) lpuart32_console_get_options(sport, &baud, &parity, &bits); else lpuart_console_get_options(sport, &baud, &parity, &bits); - if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) + if (lpuart_is_32(sport)) lpuart32_setup_watermark(sport); else lpuart_setup_watermark(sport); @@ -2118,7 +2124,7 @@ static int lpuart_probe(struct platform_device *pdev) } sport->port.irq = ret; sport->port.iotype = sdata->iotype; - if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) + if (lpuart_is_32(sport)) sport->port.ops = &lpuart32_pops; else sport->port.ops = &lpuart_pops; @@ -2145,7 +2151,7 @@ static int lpuart_probe(struct platform_device *pdev) platform_set_drvdata(pdev, &sport->port); - if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) + if (lpuart_is_32(sport)) lpuart_reg.cons = LPUART32_CONSOLE; else lpuart_reg.cons = LPUART_CONSOLE; @@ -2198,7 +2204,7 @@ static int lpuart_suspend(struct device *dev) struct lpuart_port *sport = dev_get_drvdata(dev); unsigned long temp; - if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) { + if (lpuart_is_32(sport)) { /* disable Rx/Tx and interrupts */ temp = lpuart32_read(&sport->port, UARTCTRL); temp &= ~(UARTCTRL_TE | UARTCTRL_TIE | UARTCTRL_TCIE); @@ -2249,7 +2255,7 @@ static int lpuart_resume(struct device *dev) if (sport->port.suspended && !sport->port.irq_wake) clk_prepare_enable(sport->clk); - if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) { + if (lpuart_is_32(sport)) { lpuart32_setup_watermark(sport); temp = lpuart32_read(&sport->port, UARTCTRL); temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE | -- cgit v1.2.3 From 6509f3096263ca2714ec938439a832b302a3a65e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 20 Jun 2017 22:34:13 +0200 Subject: tty: hide unused pty_get_peer function TIOCGPTPEER is only used for unix98 PTYs, and we get a warning when those are disabled: drivers/tty/pty.c:466:12: error: 'pty_get_peer' defined but not used [-Werror=unused-function] This moves the respective functions inside of the existing #ifdef. Fixes: 54ebbfb16034 ("tty: add TIOCGPTPEER ioctl") Signed-off-by: Arnd Bergmann Acked-by: Aleksa Sarai Reviewed-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 85 +++++++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index d1399aac05a1..284749fb0f6b 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -448,48 +448,6 @@ err: return retval; } -/** - * pty_open_peer - open the peer of a pty - * @tty: the peer of the pty being opened - * - * Open the cached dentry in tty->link, providing a safe way for userspace - * to get the slave end of a pty (where they have the master fd and cannot - * access or trust the mount namespace /dev/pts was mounted inside). - */ -static struct file *pty_open_peer(struct tty_struct *tty, int flags) -{ - if (tty->driver->subtype != PTY_TYPE_MASTER) - return ERR_PTR(-EIO); - return dentry_open(tty->link->driver_data, flags, current_cred()); -} - -static int pty_get_peer(struct tty_struct *tty, int flags) -{ - int fd = -1; - struct file *filp = NULL; - int retval = -EINVAL; - - fd = get_unused_fd_flags(0); - if (fd < 0) { - retval = fd; - goto err; - } - - filp = pty_open_peer(tty, flags); - if (IS_ERR(filp)) { - retval = PTR_ERR(filp); - goto err_put; - } - - fd_install(fd, filp); - return fd; - -err_put: - put_unused_fd(fd); -err: - return retval; -} - static void pty_cleanup(struct tty_struct *tty) { tty_port_put(tty->port); @@ -646,9 +604,50 @@ static inline void legacy_pty_init(void) { } /* Unix98 devices */ #ifdef CONFIG_UNIX98_PTYS - static struct cdev ptmx_cdev; +/** + * pty_open_peer - open the peer of a pty + * @tty: the peer of the pty being opened + * + * Open the cached dentry in tty->link, providing a safe way for userspace + * to get the slave end of a pty (where they have the master fd and cannot + * access or trust the mount namespace /dev/pts was mounted inside). + */ +static struct file *pty_open_peer(struct tty_struct *tty, int flags) +{ + if (tty->driver->subtype != PTY_TYPE_MASTER) + return ERR_PTR(-EIO); + return dentry_open(tty->link->driver_data, flags, current_cred()); +} + +static int pty_get_peer(struct tty_struct *tty, int flags) +{ + int fd = -1; + struct file *filp = NULL; + int retval = -EINVAL; + + fd = get_unused_fd_flags(0); + if (fd < 0) { + retval = fd; + goto err; + } + + filp = pty_open_peer(tty, flags); + if (IS_ERR(filp)) { + retval = PTR_ERR(filp); + goto err_put; + } + + fd_install(fd, filp); + return fd; + +err_put: + put_unused_fd(fd); +err: + return retval; +} + static int pty_unix98_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { -- cgit v1.2.3