Explorar o código

Merge tag 'tty-4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial driver fixes from Greg KH:
 "Here are a number of small tty and serial driver fixes for reported
  issues for 4.9-rc3. Nothing major, but they do resolve a bunch of
  problems with the tty core changes that are in 4.9-rc1, and finally
  the atmel serial driver is back working properly.

  All have been in linux-next with no reported issues"

* tag 'tty-4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  tty: serial_core: fix NULL struct tty pointer access in uart_write_wakeup
  tty: serial_core: Fix serial console crash on port shutdown
  tty/serial: at91: fix hardware handshake on Atmel platforms
  vt: clear selection before resizing
  sc16is7xx: always write state when configuring GPIO as an output
  sh-sci: document R8A7743/5 support
  tty: serial: 8250: 8250_core: NXP SC16C2552 workaround
  tty: limit terminal size to 4M chars
  tty: serial: fsl_lpuart: Fix Tx DMA edge case
  serial: 8250_lpss: enable MSI for sure
  serial: core: fix console problems on uart_close
  serial: 8250_uniphier: fix clearing divisor latch access bit
  serial: 8250_uniphier: fix more unterminated string
  serial: pch_uart: add terminate entry for dmi_system_id tables
  devicetree: bindings: uart: Add new compatible string for ZynqMP
  serial: xuartps: Add new compatible string for ZynqMP
  serial: SERIAL_STM32 should depend on HAS_DMA
  serial: stm32: Fix comparisons with undefined register
  tty: vt, fix bogus division in csi_J
Linus Torvalds %!s(int64=9) %!d(string=hai) anos
pai
achega
37cc6bb8f2

+ 3 - 1
Documentation/devicetree/bindings/serial/cdns,uart.txt

@@ -1,7 +1,9 @@
 Binding for Cadence UART Controller
 Binding for Cadence UART Controller
 
 
 Required properties:
 Required properties:
-- compatible : should be "cdns,uart-r1p8", or "xlnx,xuartps"
+- compatible :
+  Use "xlnx,xuartps","cdns,uart-r1p8" for Zynq-7xxx SoC.
+  Use "xlnx,zynqmp-uart","cdns,uart-r1p12" for Zynq Ultrascale+ MPSoC.
 - reg: Should contain UART controller registers location and length.
 - reg: Should contain UART controller registers location and length.
 - interrupts: Should contain UART controller interrupts.
 - interrupts: Should contain UART controller interrupts.
 - clocks: Must contain phandles to the UART clocks
 - clocks: Must contain phandles to the UART clocks

+ 8 - 0
Documentation/devicetree/bindings/serial/renesas,sci-serial.txt

@@ -9,6 +9,14 @@ Required properties:
     - "renesas,scifb-r8a73a4" for R8A73A4 (R-Mobile APE6) SCIFB compatible UART.
     - "renesas,scifb-r8a73a4" for R8A73A4 (R-Mobile APE6) SCIFB compatible UART.
     - "renesas,scifa-r8a7740" for R8A7740 (R-Mobile A1) SCIFA compatible UART.
     - "renesas,scifa-r8a7740" for R8A7740 (R-Mobile A1) SCIFA compatible UART.
     - "renesas,scifb-r8a7740" for R8A7740 (R-Mobile A1) SCIFB compatible UART.
     - "renesas,scifb-r8a7740" for R8A7740 (R-Mobile A1) SCIFB compatible UART.
+    - "renesas,scif-r8a7743" for R8A7743 (RZ/G1M) SCIF compatible UART.
+    - "renesas,scifa-r8a7743" for R8A7743 (RZ/G1M) SCIFA compatible UART.
+    - "renesas,scifb-r8a7743" for R8A7743 (RZ/G1M) SCIFB compatible UART.
+    - "renesas,hscif-r8a7743" for R8A7743 (RZ/G1M) HSCIF compatible UART.
+    - "renesas,scif-r8a7745" for R8A7745 (RZ/G1E) SCIF compatible UART.
+    - "renesas,scifa-r8a7745" for R8A7745 (RZ/G1E) SCIFA compatible UART.
+    - "renesas,scifb-r8a7745" for R8A7745 (RZ/G1E) SCIFB compatible UART.
+    - "renesas,hscif-r8a7745" for R8A7745 (RZ/G1E) HSCIF compatible UART.
     - "renesas,scif-r8a7778" for R8A7778 (R-Car M1) SCIF compatible UART.
     - "renesas,scif-r8a7778" for R8A7778 (R-Car M1) SCIF compatible UART.
     - "renesas,scif-r8a7779" for R8A7779 (R-Car H1) SCIF compatible UART.
     - "renesas,scif-r8a7779" for R8A7779 (R-Car H1) SCIF compatible UART.
     - "renesas,scif-r8a7790" for R8A7790 (R-Car H2) SCIF compatible UART.
     - "renesas,scif-r8a7790" for R8A7790 (R-Car H2) SCIF compatible UART.

+ 1 - 1
drivers/tty/serial/8250/8250_lpss.c

@@ -213,7 +213,7 @@ static int qrk_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
 	struct pci_dev *pdev = to_pci_dev(port->dev);
 	struct pci_dev *pdev = to_pci_dev(port->dev);
 	int ret;
 	int ret;
 
 
-	ret = pci_alloc_irq_vectors(pdev, 1, 1, 0);
+	ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 

+ 2 - 1
drivers/tty/serial/8250/8250_port.c

@@ -83,7 +83,8 @@ static const struct serial8250_config uart_config[] = {
 		.name		= "16550A",
 		.name		= "16550A",
 		.fifo_size	= 16,
 		.fifo_size	= 16,
 		.tx_loadsz	= 16,
 		.tx_loadsz	= 16,
-		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
+				  UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
 		.rxtrig_bytes	= {1, 4, 8, 14},
 		.rxtrig_bytes	= {1, 4, 8, 14},
 		.flags		= UART_CAP_FIFO,
 		.flags		= UART_CAP_FIFO,
 	},
 	},

+ 2 - 2
drivers/tty/serial/8250/8250_uniphier.c

@@ -99,7 +99,7 @@ static void uniphier_serial_out(struct uart_port *p, int offset, int value)
 	case UART_LCR:
 	case UART_LCR:
 		valshift = UNIPHIER_UART_LCR_SHIFT;
 		valshift = UNIPHIER_UART_LCR_SHIFT;
 		/* Divisor latch access bit does not exist. */
 		/* Divisor latch access bit does not exist. */
-		value &= ~(UART_LCR_DLAB << valshift);
+		value &= ~UART_LCR_DLAB;
 		/* fall through */
 		/* fall through */
 	case UART_MCR:
 	case UART_MCR:
 		offset = UNIPHIER_UART_LCR_MCR;
 		offset = UNIPHIER_UART_LCR_MCR;
@@ -199,7 +199,7 @@ static int uniphier_uart_probe(struct platform_device *pdev)
 
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!regs) {
 	if (!regs) {
-		dev_err(dev, "failed to get memory resource");
+		dev_err(dev, "failed to get memory resource\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 

+ 1 - 0
drivers/tty/serial/Kconfig

@@ -1625,6 +1625,7 @@ config SERIAL_SPRD_CONSOLE
 config SERIAL_STM32
 config SERIAL_STM32
 	tristate "STMicroelectronics STM32 serial port support"
 	tristate "STMicroelectronics STM32 serial port support"
 	select SERIAL_CORE
 	select SERIAL_CORE
+	depends on HAS_DMA
 	depends on ARM || COMPILE_TEST
 	depends on ARM || COMPILE_TEST
 	help
 	help
 	  This driver is for the on-chip Serial Controller on
 	  This driver is for the on-chip Serial Controller on

+ 22 - 4
drivers/tty/serial/atmel_serial.c

@@ -2132,11 +2132,29 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 		mode |= ATMEL_US_USMODE_RS485;
 		mode |= ATMEL_US_USMODE_RS485;
 	} else if (termios->c_cflag & CRTSCTS) {
 	} else if (termios->c_cflag & CRTSCTS) {
 		/* RS232 with hardware handshake (RTS/CTS) */
 		/* RS232 with hardware handshake (RTS/CTS) */
-		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 {
+		if (atmel_use_fifo(port) &&
+		    !mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) {
+			/*
+			 * with ATMEL_US_USMODE_HWHS set, the controller will
+			 * be able to drive the RTS pin high/low when the RX
+			 * FIFO is above RXFTHRES/below RXFTHRES2.
+			 * It will also disable the transmitter when the CTS
+			 * pin is high.
+			 * This mode is not activated if CTS pin is a GPIO
+			 * because in this case, the transmitter is always
+			 * disabled (there must be an internal pull-up
+			 * responsible for this behaviour).
+			 * If the RTS pin is a GPIO, the controller won't be
+			 * able to drive it according to the FIFO thresholds,
+			 * but it will be handled by the driver.
+			 */
 			mode |= ATMEL_US_USMODE_HWHS;
 			mode |= ATMEL_US_USMODE_HWHS;
+		} else {
+			/*
+			 * For platforms without FIFO, the flow control is
+			 * handled by the driver.
+			 */
+			mode |= ATMEL_US_USMODE_NORMAL;
 		}
 		}
 	} else {
 	} else {
 		/* RS232 without hadware handshake */
 		/* RS232 without hadware handshake */

+ 1 - 2
drivers/tty/serial/fsl_lpuart.c

@@ -328,7 +328,7 @@ static void lpuart_dma_tx(struct lpuart_port *sport)
 
 
 	sport->dma_tx_bytes = uart_circ_chars_pending(xmit);
 	sport->dma_tx_bytes = uart_circ_chars_pending(xmit);
 
 
-	if (xmit->tail < xmit->head) {
+	if (xmit->tail < xmit->head || xmit->head == 0) {
 		sport->dma_tx_nents = 1;
 		sport->dma_tx_nents = 1;
 		sg_init_one(sgl, xmit->buf + xmit->tail, sport->dma_tx_bytes);
 		sg_init_one(sgl, xmit->buf + xmit->tail, sport->dma_tx_bytes);
 	} else {
 	} else {
@@ -359,7 +359,6 @@ static void lpuart_dma_tx(struct lpuart_port *sport)
 	sport->dma_tx_in_progress = true;
 	sport->dma_tx_in_progress = true;
 	sport->dma_tx_cookie = dmaengine_submit(sport->dma_tx_desc);
 	sport->dma_tx_cookie = dmaengine_submit(sport->dma_tx_desc);
 	dma_async_issue_pending(sport->dma_tx_chan);
 	dma_async_issue_pending(sport->dma_tx_chan);
-
 }
 }
 
 
 static void lpuart_dma_tx_complete(void *arg)
 static void lpuart_dma_tx_complete(void *arg)

+ 1 - 0
drivers/tty/serial/pch_uart.c

@@ -419,6 +419,7 @@ static struct dmi_system_id pch_uart_dmi_table[] = {
 		},
 		},
 		(void *)MINNOW_UARTCLK,
 		(void *)MINNOW_UARTCLK,
 	},
 	},
+	{ }
 };
 };
 
 
 /* Return UART clock, checking for board specific clocks. */
 /* Return UART clock, checking for board specific clocks. */

+ 6 - 2
drivers/tty/serial/sc16is7xx.c

@@ -1130,9 +1130,13 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip,
 {
 {
 	struct sc16is7xx_port *s = gpiochip_get_data(chip);
 	struct sc16is7xx_port *s = gpiochip_get_data(chip);
 	struct uart_port *port = &s->p[0].port;
 	struct uart_port *port = &s->p[0].port;
+	u8 state = sc16is7xx_port_read(port, SC16IS7XX_IOSTATE_REG);
 
 
-	sc16is7xx_port_update(port, SC16IS7XX_IOSTATE_REG, BIT(offset),
-			      val ? BIT(offset) : 0);
+	if (val)
+		state |= BIT(offset);
+	else
+		state &= ~BIT(offset);
+	sc16is7xx_port_write(port, SC16IS7XX_IOSTATE_REG, state);
 	sc16is7xx_port_update(port, SC16IS7XX_IODIR_REG, BIT(offset),
 	sc16is7xx_port_update(port, SC16IS7XX_IODIR_REG, BIT(offset),
 			      BIT(offset));
 			      BIT(offset));
 
 

+ 4 - 4
drivers/tty/serial/serial_core.c

@@ -111,7 +111,7 @@ void uart_write_wakeup(struct uart_port *port)
 	 * closed.  No cookie for you.
 	 * closed.  No cookie for you.
 	 */
 	 */
 	BUG_ON(!state);
 	BUG_ON(!state);
-	tty_wakeup(state->port.tty);
+	tty_port_tty_wakeup(&state->port);
 }
 }
 
 
 static void uart_stop(struct tty_struct *tty)
 static void uart_stop(struct tty_struct *tty)
@@ -632,7 +632,7 @@ static void uart_flush_buffer(struct tty_struct *tty)
 	if (port->ops->flush_buffer)
 	if (port->ops->flush_buffer)
 		port->ops->flush_buffer(port);
 		port->ops->flush_buffer(port);
 	uart_port_unlock(port, flags);
 	uart_port_unlock(port, flags);
-	tty_wakeup(tty);
+	tty_port_tty_wakeup(&state->port);
 }
 }
 
 
 /*
 /*
@@ -2746,8 +2746,6 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
 	uport->cons = drv->cons;
 	uport->cons = drv->cons;
 	uport->minor = drv->tty_driver->minor_start + uport->line;
 	uport->minor = drv->tty_driver->minor_start + uport->line;
 
 
-	port->console = uart_console(uport);
-
 	/*
 	/*
 	 * If this port is a console, then the spinlock is already
 	 * If this port is a console, then the spinlock is already
 	 * initialised.
 	 * initialised.
@@ -2761,6 +2759,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
 
 
 	uart_configure_port(drv, state, uport);
 	uart_configure_port(drv, state, uport);
 
 
+	port->console = uart_console(uport);
+
 	num_groups = 2;
 	num_groups = 2;
 	if (uport->attr_group)
 	if (uport->attr_group)
 		num_groups++;
 		num_groups++;

+ 1 - 1
drivers/tty/serial/stm32-usart.h

@@ -31,7 +31,7 @@ struct stm32_usart_info {
 	struct stm32_usart_config cfg;
 	struct stm32_usart_config cfg;
 };
 };
 
 
-#define UNDEF_REG ~0
+#define UNDEF_REG 0xff
 
 
 /* Register offsets */
 /* Register offsets */
 struct stm32_usart_info stm32f4_info = {
 struct stm32_usart_info stm32f4_info = {

+ 2 - 0
drivers/tty/serial/xilinx_uartps.c

@@ -1200,6 +1200,7 @@ static int __init cdns_early_console_setup(struct earlycon_device *device,
 OF_EARLYCON_DECLARE(cdns, "xlnx,xuartps", cdns_early_console_setup);
 OF_EARLYCON_DECLARE(cdns, "xlnx,xuartps", cdns_early_console_setup);
 OF_EARLYCON_DECLARE(cdns, "cdns,uart-r1p8", cdns_early_console_setup);
 OF_EARLYCON_DECLARE(cdns, "cdns,uart-r1p8", cdns_early_console_setup);
 OF_EARLYCON_DECLARE(cdns, "cdns,uart-r1p12", cdns_early_console_setup);
 OF_EARLYCON_DECLARE(cdns, "cdns,uart-r1p12", cdns_early_console_setup);
+OF_EARLYCON_DECLARE(cdns, "xlnx,zynqmp-uart", cdns_early_console_setup);
 
 
 /**
 /**
  * cdns_uart_console_write - perform write operation
  * cdns_uart_console_write - perform write operation
@@ -1438,6 +1439,7 @@ static const struct of_device_id cdns_uart_of_match[] = {
 	{ .compatible = "xlnx,xuartps", },
 	{ .compatible = "xlnx,xuartps", },
 	{ .compatible = "cdns,uart-r1p8", },
 	{ .compatible = "cdns,uart-r1p8", },
 	{ .compatible = "cdns,uart-r1p12", .data = &zynqmp_uart_def },
 	{ .compatible = "cdns,uart-r1p12", .data = &zynqmp_uart_def },
+	{ .compatible = "xlnx,zynqmp-uart", .data = &zynqmp_uart_def },
 	{}
 	{}
 };
 };
 MODULE_DEVICE_TABLE(of, cdns_uart_of_match);
 MODULE_DEVICE_TABLE(of, cdns_uart_of_match);

+ 6 - 1
drivers/tty/vt/vt.c

@@ -870,10 +870,15 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
 	if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
 	if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
 		return 0;
 		return 0;
 
 
+	if (new_screen_size > (4 << 20))
+		return -EINVAL;
 	newscreen = kmalloc(new_screen_size, GFP_USER);
 	newscreen = kmalloc(new_screen_size, GFP_USER);
 	if (!newscreen)
 	if (!newscreen)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
+	if (vc == sel_cons)
+		clear_selection();
+
 	old_rows = vc->vc_rows;
 	old_rows = vc->vc_rows;
 	old_row_size = vc->vc_size_row;
 	old_row_size = vc->vc_size_row;
 
 
@@ -1176,7 +1181,7 @@ static void csi_J(struct vc_data *vc, int vpar)
 			break;
 			break;
 		case 3: /* erase scroll-back buffer (and whole display) */
 		case 3: /* erase scroll-back buffer (and whole display) */
 			scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
 			scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
-				    vc->vc_screenbuf_size >> 1);
+				    vc->vc_screenbuf_size);
 			set_origin(vc);
 			set_origin(vc);
 			if (con_is_visible(vc))
 			if (con_is_visible(vc))
 				update_screen(vc);
 				update_screen(vc);