Эх сурвалжийг харах

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

Pull tty/serial fixes from Greg KH:
 "Here are some tty and serial driver fixes for 4.0-rc3.

  Along with the atime fix that you know about, here are some other
  serial driver bugfixes as well.  Most notable is a wait_until_sent
  bugfix that was traced back to being around since before 2.6.12 that
  Johan has fixed up.

  All have been in linux-next successfully"

* tag 'tty-4.0-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  TTY: fix tty_wait_until_sent maximum timeout
  TTY: fix tty_wait_until_sent on 64-bit machines
  USB: serial: fix infinite wait_until_sent timeout
  TTY: bfin_jtag_comm: remove incorrect wait_until_sent operation
  net: irda: fix wait_until_sent poll timeout
  serial: uapi: Declare all userspace-visible io types
  serial: core: Fix iotype userspace breakage
  serial: sprd: Fix missing spin_unlock in sprd_handle_irq()
  console: Fix console name size mismatch
  tty: fix up atime/mtime mess, take four
  serial: 8250_dw: Fix get_mctrl behaviour
  serial:8250:8250_pci: delete unneeded quirk entries
  serial:8250:8250_pci: fix redundant entry report for WCH_CH352_2S
  Change email address for 8250_pci
  serial: 8250: Revert "tty: serial: 8250_core: read only RX if there is something in the FIFO"
  Revert "tty/serial: of_serial: add DT alias ID handling"
Linus Torvalds 10 жил өмнө
parent
commit
bbbce516bb

+ 16 - 0
Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt

@@ -21,6 +21,18 @@ Optional properties:
 - reg-io-width : the size (in bytes) of the IO accesses that should be
 - reg-io-width : the size (in bytes) of the IO accesses that should be
   performed on the device.  If this property is not present then single byte
   performed on the device.  If this property is not present then single byte
   accesses are used.
   accesses are used.
+- dcd-override : Override the DCD modem status signal. This signal will always
+  be reported as active instead of being obtained from the modem status
+  register. Define this if your serial port does not use this pin.
+- dsr-override : Override the DTS modem status signal. This signal will always
+  be reported as active instead of being obtained from the modem status
+  register. Define this if your serial port does not use this pin.
+- cts-override : Override the CTS modem status signal. This signal will always
+  be reported as active instead of being obtained from the modem status
+  register. Define this if your serial port does not use this pin.
+- ri-override : Override the RI modem status signal. This signal will always be
+  reported as inactive instead of being obtained from the modem status register.
+  Define this if your serial port does not use this pin.
 
 
 Example:
 Example:
 
 
@@ -31,6 +43,10 @@ Example:
 		interrupts = <10>;
 		interrupts = <10>;
 		reg-shift = <2>;
 		reg-shift = <2>;
 		reg-io-width = <4>;
 		reg-io-width = <4>;
+		dcd-override;
+		dsr-override;
+		cts-override;
+		ri-override;
 	};
 	};
 
 
 Example with one clock:
 Example with one clock:

+ 0 - 13
drivers/tty/bfin_jtag_comm.c

@@ -210,18 +210,6 @@ bfin_jc_chars_in_buffer(struct tty_struct *tty)
 	return circ_cnt(&bfin_jc_write_buf);
 	return circ_cnt(&bfin_jc_write_buf);
 }
 }
 
 
-static void
-bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	unsigned long expire = jiffies + timeout;
-	while (!circ_empty(&bfin_jc_write_buf)) {
-		if (signal_pending(current))
-			break;
-		if (time_after(jiffies, expire))
-			break;
-	}
-}
-
 static const struct tty_operations bfin_jc_ops = {
 static const struct tty_operations bfin_jc_ops = {
 	.open            = bfin_jc_open,
 	.open            = bfin_jc_open,
 	.close           = bfin_jc_close,
 	.close           = bfin_jc_close,
@@ -230,7 +218,6 @@ static const struct tty_operations bfin_jc_ops = {
 	.flush_chars     = bfin_jc_flush_chars,
 	.flush_chars     = bfin_jc_flush_chars,
 	.write_room      = bfin_jc_write_room,
 	.write_room      = bfin_jc_write_room,
 	.chars_in_buffer = bfin_jc_chars_in_buffer,
 	.chars_in_buffer = bfin_jc_chars_in_buffer,
-	.wait_until_sent = bfin_jc_wait_until_sent,
 };
 };
 
 
 static int __init bfin_jc_init(void)
 static int __init bfin_jc_init(void)

+ 5 - 6
drivers/tty/serial/8250/8250_core.c

@@ -2138,8 +2138,8 @@ int serial8250_do_startup(struct uart_port *port)
 	/*
 	/*
 	 * Clear the interrupt registers.
 	 * Clear the interrupt registers.
 	 */
 	 */
-	if (serial_port_in(port, UART_LSR) & UART_LSR_DR)
-		serial_port_in(port, UART_RX);
+	serial_port_in(port, UART_LSR);
+	serial_port_in(port, UART_RX);
 	serial_port_in(port, UART_IIR);
 	serial_port_in(port, UART_IIR);
 	serial_port_in(port, UART_MSR);
 	serial_port_in(port, UART_MSR);
 
 
@@ -2300,8 +2300,8 @@ dont_test_tx_en:
 	 * saved flags to avoid getting false values from polling
 	 * saved flags to avoid getting false values from polling
 	 * routines or the previous session.
 	 * routines or the previous session.
 	 */
 	 */
-	if (serial_port_in(port, UART_LSR) & UART_LSR_DR)
-		serial_port_in(port, UART_RX);
+	serial_port_in(port, UART_LSR);
+	serial_port_in(port, UART_RX);
 	serial_port_in(port, UART_IIR);
 	serial_port_in(port, UART_IIR);
 	serial_port_in(port, UART_MSR);
 	serial_port_in(port, UART_MSR);
 	up->lsr_saved_flags = 0;
 	up->lsr_saved_flags = 0;
@@ -2394,8 +2394,7 @@ void serial8250_do_shutdown(struct uart_port *port)
 	 * Read data port to reset things, and then unlink from
 	 * Read data port to reset things, and then unlink from
 	 * the IRQ chain.
 	 * the IRQ chain.
 	 */
 	 */
-	if (serial_port_in(port, UART_LSR) & UART_LSR_DR)
-		serial_port_in(port, UART_RX);
+	serial_port_in(port, UART_RX);
 	serial8250_rpm_put(up);
 	serial8250_rpm_put(up);
 
 
 	del_timer_sync(&up->timer);
 	del_timer_sync(&up->timer);

+ 32 - 0
drivers/tty/serial/8250/8250_dw.c

@@ -59,6 +59,8 @@ struct dw8250_data {
 	u8			usr_reg;
 	u8			usr_reg;
 	int			last_mcr;
 	int			last_mcr;
 	int			line;
 	int			line;
+	int			msr_mask_on;
+	int			msr_mask_off;
 	struct clk		*clk;
 	struct clk		*clk;
 	struct clk		*pclk;
 	struct clk		*pclk;
 	struct reset_control	*rst;
 	struct reset_control	*rst;
@@ -81,6 +83,12 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
 		value &= ~UART_MSR_DCTS;
 		value &= ~UART_MSR_DCTS;
 	}
 	}
 
 
+	/* Override any modem control signals if needed */
+	if (offset == UART_MSR) {
+		value |= d->msr_mask_on;
+		value &= ~d->msr_mask_off;
+	}
+
 	return value;
 	return value;
 }
 }
 
 
@@ -334,6 +342,30 @@ static int dw8250_probe_of(struct uart_port *p,
 	if (id >= 0)
 	if (id >= 0)
 		p->line = id;
 		p->line = id;
 
 
+	if (of_property_read_bool(np, "dcd-override")) {
+		/* Always report DCD as active */
+		data->msr_mask_on |= UART_MSR_DCD;
+		data->msr_mask_off |= UART_MSR_DDCD;
+	}
+
+	if (of_property_read_bool(np, "dsr-override")) {
+		/* Always report DSR as active */
+		data->msr_mask_on |= UART_MSR_DSR;
+		data->msr_mask_off |= UART_MSR_DDSR;
+	}
+
+	if (of_property_read_bool(np, "cts-override")) {
+		/* Always report DSR as active */
+		data->msr_mask_on |= UART_MSR_DSR;
+		data->msr_mask_off |= UART_MSR_DDSR;
+	}
+
+	if (of_property_read_bool(np, "ri-override")) {
+		/* Always report Ring indicator as inactive */
+		data->msr_mask_off |= UART_MSR_RI;
+		data->msr_mask_off |= UART_MSR_TERI;
+	}
+
 	/* clock got configured through clk api, all done */
 	/* clock got configured through clk api, all done */
 	if (p->uartclk)
 	if (p->uartclk)
 		return 0;
 		return 0;

+ 1 - 19
drivers/tty/serial/8250/8250_pci.c

@@ -69,7 +69,7 @@ static void moan_device(const char *str, struct pci_dev *dev)
 	       "Please send the output of lspci -vv, this\n"
 	       "Please send the output of lspci -vv, this\n"
 	       "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
 	       "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
 	       "manufacturer and name of serial board or\n"
 	       "manufacturer and name of serial board or\n"
-	       "modem board to rmk+serial@arm.linux.org.uk.\n",
+	       "modem board to <linux-serial@vger.kernel.org>.\n",
 	       pci_name(dev), str, dev->vendor, dev->device,
 	       pci_name(dev), str, dev->vendor, dev->device,
 	       dev->subsystem_vendor, dev->subsystem_device);
 	       dev->subsystem_vendor, dev->subsystem_device);
 }
 }
@@ -1987,13 +1987,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
 		.setup		= byt_serial_setup,
 		.setup		= byt_serial_setup,
 	},
 	},
-	{
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_QRK_UART,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_default_setup,
-	},
 	{
 	{
 		.vendor		= PCI_VENDOR_ID_INTEL,
 		.vendor		= PCI_VENDOR_ID_INTEL,
 		.device		= PCI_DEVICE_ID_INTEL_BSW_UART1,
 		.device		= PCI_DEVICE_ID_INTEL_BSW_UART1,
@@ -2199,13 +2192,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 	/*
 	/*
 	 * PLX
 	 * PLX
 	 */
 	 */
-	{
-		.vendor		= PCI_VENDOR_ID_PLX,
-		.device		= PCI_DEVICE_ID_PLX_9030,
-		.subvendor	= PCI_SUBVENDOR_ID_PERLE,
-		.subdevice	= PCI_ANY_ID,
-		.setup		= pci_default_setup,
-	},
 	{
 	{
 		.vendor		= PCI_VENDOR_ID_PLX,
 		.vendor		= PCI_VENDOR_ID_PLX,
 		.device		= PCI_DEVICE_ID_PLX_9050,
 		.device		= PCI_DEVICE_ID_PLX_9050,
@@ -5415,10 +5401,6 @@ static struct pci_device_id serial_pci_tbl[] = {
 		PCI_ANY_ID, PCI_ANY_ID,
 		PCI_ANY_ID, PCI_ANY_ID,
 		0, 0, pbn_b0_bt_2_115200 },
 		0, 0, pbn_b0_bt_2_115200 },
 
 
-	{	PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH352_2S,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0, 0, pbn_b0_bt_2_115200 },
-
 	{	PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH384_4S,
 	{	PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH384_4S,
 		PCI_ANY_ID, PCI_ANY_ID,
 		PCI_ANY_ID, PCI_ANY_ID,
 		0, 0, pbn_wch384_4 },
 		0, 0, pbn_wch384_4 },

+ 0 - 4
drivers/tty/serial/of_serial.c

@@ -133,10 +133,6 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
 	if (of_find_property(np, "no-loopback-test", NULL))
 	if (of_find_property(np, "no-loopback-test", NULL))
 		port->flags |= UPF_SKIP_TEST;
 		port->flags |= UPF_SKIP_TEST;
 
 
-	ret = of_alias_get_id(np, "serial");
-	if (ret >= 0)
-		port->line = ret;
-
 	port->dev = &ofdev->dev;
 	port->dev = &ofdev->dev;
 
 
 	switch (type) {
 	switch (type) {

+ 3 - 1
drivers/tty/serial/sprd_serial.c

@@ -293,8 +293,10 @@ static irqreturn_t sprd_handle_irq(int irq, void *dev_id)
 
 
 	ims = serial_in(port, SPRD_IMSR);
 	ims = serial_in(port, SPRD_IMSR);
 
 
-	if (!ims)
+	if (!ims) {
+		spin_unlock(&port->lock);
 		return IRQ_NONE;
 		return IRQ_NONE;
+	}
 
 
 	serial_out(port, SPRD_ICLR, ~0);
 	serial_out(port, SPRD_ICLR, ~0);
 
 

+ 2 - 2
drivers/tty/tty_io.c

@@ -1028,8 +1028,8 @@ EXPORT_SYMBOL(start_tty);
 /* We limit tty time update visibility to every 8 seconds or so. */
 /* We limit tty time update visibility to every 8 seconds or so. */
 static void tty_update_time(struct timespec *time)
 static void tty_update_time(struct timespec *time)
 {
 {
-	unsigned long sec = get_seconds() & ~7;
-	if ((long)(sec - time->tv_sec) > 0)
+	unsigned long sec = get_seconds();
+	if (abs(sec - time->tv_sec) & ~7)
 		time->tv_sec = sec;
 		time->tv_sec = sec;
 }
 }
 
 

+ 11 - 5
drivers/tty/tty_ioctl.c

@@ -217,11 +217,17 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout)
 #endif
 #endif
 	if (!timeout)
 	if (!timeout)
 		timeout = MAX_SCHEDULE_TIMEOUT;
 		timeout = MAX_SCHEDULE_TIMEOUT;
-	if (wait_event_interruptible_timeout(tty->write_wait,
-			!tty_chars_in_buffer(tty), timeout) >= 0) {
-		if (tty->ops->wait_until_sent)
-			tty->ops->wait_until_sent(tty, timeout);
-	}
+
+	timeout = wait_event_interruptible_timeout(tty->write_wait,
+			!tty_chars_in_buffer(tty), timeout);
+	if (timeout <= 0)
+		return;
+
+	if (timeout == MAX_SCHEDULE_TIMEOUT)
+		timeout = 0;
+
+	if (tty->ops->wait_until_sent)
+		tty->ops->wait_until_sent(tty, timeout);
 }
 }
 EXPORT_SYMBOL(tty_wait_until_sent);
 EXPORT_SYMBOL(tty_wait_until_sent);
 
 

+ 3 - 2
drivers/usb/serial/generic.c

@@ -258,7 +258,8 @@ void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout)
 	 * character or at least one jiffy.
 	 * character or at least one jiffy.
 	 */
 	 */
 	period = max_t(unsigned long, (10 * HZ / bps), 1);
 	period = max_t(unsigned long, (10 * HZ / bps), 1);
-	period = min_t(unsigned long, period, timeout);
+	if (timeout)
+		period = min_t(unsigned long, period, timeout);
 
 
 	dev_dbg(&port->dev, "%s - timeout = %u ms, period = %u ms\n",
 	dev_dbg(&port->dev, "%s - timeout = %u ms, period = %u ms\n",
 					__func__, jiffies_to_msecs(timeout),
 					__func__, jiffies_to_msecs(timeout),
@@ -268,7 +269,7 @@ void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout)
 		schedule_timeout_interruptible(period);
 		schedule_timeout_interruptible(period);
 		if (signal_pending(current))
 		if (signal_pending(current))
 			break;
 			break;
-		if (time_after(jiffies, expire))
+		if (timeout && time_after(jiffies, expire))
 			break;
 			break;
 	}
 	}
 }
 }

+ 7 - 7
include/linux/serial_core.h

@@ -143,13 +143,13 @@ struct uart_port {
 	unsigned char		iotype;			/* io access style */
 	unsigned char		iotype;			/* io access style */
 	unsigned char		unused1;
 	unsigned char		unused1;
 
 
-#define UPIO_PORT		(0)			/* 8b I/O port access */
-#define UPIO_HUB6		(1)			/* Hub6 ISA card */
-#define UPIO_MEM		(2)			/* 8b MMIO access */
-#define UPIO_MEM32		(3)			/* 32b little endian */
-#define UPIO_MEM32BE		(4)			/* 32b big endian */
-#define UPIO_AU			(5)			/* Au1x00 and RT288x type IO */
-#define UPIO_TSI		(6)			/* Tsi108/109 type IO */
+#define UPIO_PORT		(SERIAL_IO_PORT)	/* 8b I/O port access */
+#define UPIO_HUB6		(SERIAL_IO_HUB6)	/* Hub6 ISA card */
+#define UPIO_MEM		(SERIAL_IO_MEM)		/* 8b MMIO access */
+#define UPIO_MEM32		(SERIAL_IO_MEM32)	/* 32b little endian */
+#define UPIO_AU			(SERIAL_IO_AU)		/* Au1x00 and RT288x type IO */
+#define UPIO_TSI		(SERIAL_IO_TSI)		/* Tsi108/109 type IO */
+#define UPIO_MEM32BE		(SERIAL_IO_MEM32BE)	/* 32b big endian */
 
 
 	unsigned int		read_status_mask;	/* driver specific */
 	unsigned int		read_status_mask;	/* driver specific */
 	unsigned int		ignore_status_mask;	/* driver specific */
 	unsigned int		ignore_status_mask;	/* driver specific */

+ 4 - 0
include/uapi/linux/serial.h

@@ -65,6 +65,10 @@ struct serial_struct {
 #define SERIAL_IO_PORT	0
 #define SERIAL_IO_PORT	0
 #define SERIAL_IO_HUB6	1
 #define SERIAL_IO_HUB6	1
 #define SERIAL_IO_MEM	2
 #define SERIAL_IO_MEM	2
+#define SERIAL_IO_MEM32	  3
+#define SERIAL_IO_AU	  4
+#define SERIAL_IO_TSI	  5
+#define SERIAL_IO_MEM32BE 6
 
 
 #define UART_CLEAR_FIFO		0x01
 #define UART_CLEAR_FIFO		0x01
 #define UART_USE_FIFO		0x02
 #define UART_USE_FIFO		0x02

+ 1 - 1
kernel/printk/console_cmdline.h

@@ -3,7 +3,7 @@
 
 
 struct console_cmdline
 struct console_cmdline
 {
 {
-	char	name[8];			/* Name of the driver	    */
+	char	name[16];			/* Name of the driver	    */
 	int	index;				/* Minor dev. to use	    */
 	int	index;				/* Minor dev. to use	    */
 	char	*options;			/* Options for the driver   */
 	char	*options;			/* Options for the driver   */
 #ifdef CONFIG_A11Y_BRAILLE_CONSOLE
 #ifdef CONFIG_A11Y_BRAILLE_CONSOLE

+ 1 - 0
kernel/printk/printk.c

@@ -2464,6 +2464,7 @@ void register_console(struct console *newcon)
 	for (i = 0, c = console_cmdline;
 	for (i = 0, c = console_cmdline;
 	     i < MAX_CMDLINECONSOLES && c->name[0];
 	     i < MAX_CMDLINECONSOLES && c->name[0];
 	     i++, c++) {
 	     i++, c++) {
+		BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));
 		if (strcmp(c->name, newcon->name) != 0)
 		if (strcmp(c->name, newcon->name) != 0)
 			continue;
 			continue;
 		if (newcon->index >= 0 &&
 		if (newcon->index >= 0 &&

+ 3 - 1
net/irda/ircomm/ircomm_tty.c

@@ -798,7 +798,9 @@ static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
 	orig_jiffies = jiffies;
 	orig_jiffies = jiffies;
 
 
 	/* Set poll time to 200 ms */
 	/* Set poll time to 200 ms */
-	poll_time = IRDA_MIN(timeout, msecs_to_jiffies(200));
+	poll_time = msecs_to_jiffies(200);
+	if (timeout)
+		poll_time = min_t(unsigned long, timeout, poll_time);
 
 
 	spin_lock_irqsave(&self->spinlock, flags);
 	spin_lock_irqsave(&self->spinlock, flags);
 	while (self->tx_skb && self->tx_skb->len) {
 	while (self->tx_skb && self->tx_skb->len) {