diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-28 20:33:54 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-28 20:33:54 -0800 |
| commit | 117eda8f71ff545cfdec8fe8073adbd173a1ceff (patch) | |
| tree | 7a6fe1729d34581c563b5f7a883f049ee272f1e3 | |
| parent | c0ea81b4d37837409d0dfd2036098a7babb312ed (diff) | |
| parent | 598134ffcab5bfb1d342458732394487063e1b9e (diff) | |
| download | linux-117eda8f71ff545cfdec8fe8073adbd173a1ceff.tar.gz linux-117eda8f71ff545cfdec8fe8073adbd173a1ceff.tar.bz2 linux-117eda8f71ff545cfdec8fe8073adbd173a1ceff.zip | |
Merge tag 'tty-4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH:
"Here is the large TTY/Serial driver set of patches for 4.21-rc1.
A number of small serial driver changes along with some good tty core
fixes for long-reported issues with locking. There is also a new
console font added to the tree, for high-res screens, so that should
be helpful for many.
The last patch in the series is a revert of an older one in the tree,
it came late but it resolves a reported issue that linux-next was
having for some people.
Full details are in the shortlog, and all of these, with the exception
of the revert, have been in linux-next for a while with no reported
issues"
* tag 'tty-4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (85 commits)
Revert "serial: 8250: Default SERIAL_OF_PLATFORM to SERIAL_8250"
serial: sccnxp: Allow to use non-standard baud rates
serial: sccnxp: Adds a delay between sequential read/write cycles
tty: serial: qcom_geni_serial: Fix UART hang
tty: serial: qcom_geni_serial: Fix wrap around of TX buffer
serial: max310x: Fix tx_empty() callback
dt-bindings: serial: sh-sci: Document r8a774c0 bindings
dt-bindings: serial: sh-sci: Document r8a774a1 bindings
Fonts: New Terminus large console font
dt-bindings: serial: lpuart: add imx8qxp compatible string
serial: uartps: Fix interrupt mask issue to handle the RX interrupts properly
serial: uartps: Fix error path when alloc failed
serial: uartps: Check if the device is a console
serial: uartps: Add the device_init_wakeup
tty: serial: samsung: Increase maximum baudrate
tty: serial: samsung: Properly set flags in autoCTS mode
tty: Use of_node_name_{eq,prefix} for node name comparisons
tty/serial: do not free trasnmit buffer page under port lock
serial: 8250: Rate limit serial port rx interrupts during input overruns
dt-bindings: serial: 8250: Add rate limit for serial port input overruns
...
55 files changed, 3039 insertions, 313 deletions
diff --git a/Documentation/devicetree/bindings/dma/8250_mtk_dma.txt b/Documentation/devicetree/bindings/dma/8250_mtk_dma.txt new file mode 100644 index 000000000000..3fe0961bcf64 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/8250_mtk_dma.txt @@ -0,0 +1,33 @@ +* Mediatek UART APDMA Controller + +Required properties: +- compatible should contain: + * "mediatek,mt2712-uart-dma" for MT2712 compatible APDMA + * "mediatek,mt6577-uart-dma" for MT6577 and all of the above + +- reg: The base address of the APDMA register bank. + +- interrupts: A single interrupt specifier. + +- clocks : Must contain an entry for each entry in clock-names. + See ../clocks/clock-bindings.txt for details. +- clock-names: The APDMA clock for register accesses + +Examples: + + apdma: dma-controller@11000380 { + compatible = "mediatek,mt2712-uart-dma"; + reg = <0 0x11000380 0 0x400>; + interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_LOW>, + <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>, + <GIC_SPI 65 IRQ_TYPE_LEVEL_LOW>, + <GIC_SPI 66 IRQ_TYPE_LEVEL_LOW>, + <GIC_SPI 67 IRQ_TYPE_LEVEL_LOW>, + <GIC_SPI 68 IRQ_TYPE_LEVEL_LOW>, + <GIC_SPI 69 IRQ_TYPE_LEVEL_LOW>, + <GIC_SPI 70 IRQ_TYPE_LEVEL_LOW>; + clocks = <&pericfg CLK_PERI_AP_DMA>; + clock-names = "apdma"; + #dma-cells = <1>; + }; + diff --git a/Documentation/devicetree/bindings/serial/8250.txt b/Documentation/devicetree/bindings/serial/8250.txt index aeb6db4e35c3..da50321da34d 100644 --- a/Documentation/devicetree/bindings/serial/8250.txt +++ b/Documentation/devicetree/bindings/serial/8250.txt @@ -51,6 +51,7 @@ Optional properties: - tx-threshold: Specify the TX FIFO low water indication for parts with programmable TX FIFO thresholds. - resets : phandle + reset specifier pairs +- overrun-throttle-ms : how long to pause uart rx when input overrun is encountered. Note: * fsl,ns16550: diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt index 6bd3f2e93d61..21483ba820bc 100644 --- a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt +++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt @@ -8,6 +8,8 @@ Required properties: on LS1021A SoC with 32-bit big-endian register organization - "fsl,imx7ulp-lpuart" for lpuart compatible with the one integrated on i.MX7ULP SoC with 32-bit little-endian register organization + - "fsl,imx8qxp-lpuart" for lpuart compatible with the one integrated + on i.MX8QXP SoC with 32-bit little-endian register organization - reg : Address and length of the register set for the device - interrupts : Should contain uart interrupt - clocks : phandle + clock specifier pairs, one for each entry in clock-names diff --git a/Documentation/devicetree/bindings/serial/lantiq_asc.txt b/Documentation/devicetree/bindings/serial/lantiq_asc.txt index 3acbd309ab9d..40e81a5818f6 100644 --- a/Documentation/devicetree/bindings/serial/lantiq_asc.txt +++ b/Documentation/devicetree/bindings/serial/lantiq_asc.txt @@ -6,8 +6,23 @@ Required properties: - interrupts: the 3 (tx rx err) interrupt numbers. The interrupt specifier depends on the interrupt-parent interrupt controller. +Optional properties: +- clocks: Should contain frequency clock and gate clock +- clock-names: Should be "freq" and "asc" + Example: +asc0: serial@16600000 { + compatible = "lantiq,asc"; + reg = <0x16600000 0x100000>; + interrupt-parent = <&gic>; + interrupts = <GIC_SHARED 103 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SHARED 105 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SHARED 106 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cgu CLK_SSX4>, <&cgu GCLK_UART>; + clock-names = "freq", "asc"; +}; + asc1: serial@e100c00 { compatible = "lantiq,asc"; reg = <0xE100C00 0x400>; diff --git a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt index e52e16c6bc57..20232ad05d89 100644 --- a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt +++ b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt @@ -24,6 +24,10 @@ Required properties: - "renesas,hscif-r8a7745" for R8A7745 (RZ/G1E) HSCIF compatible UART. - "renesas,scif-r8a77470" for R8A77470 (RZ/G1C) SCIF compatible UART. - "renesas,hscif-r8a77470" for R8A77470 (RZ/G1C) HSCIF compatible UART. + - "renesas,scif-r8a774a1" for R8A774A1 (RZ/G2M) SCIF compatible UART. + - "renesas,hscif-r8a774a1" for R8A774A1 (RZ/G2M) HSCIF compatible UART. + - "renesas,scif-r8a774c0" for R8A774C0 (RZ/G2E) SCIF compatible UART. + - "renesas,hscif-r8a774c0" for R8A774C0 (RZ/G2E) HSCIF 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-r8a7790" for R8A7790 (R-Car H2) SCIF compatible UART. @@ -61,13 +65,13 @@ Required properties: - "renesas,scifa-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFA compatible UART. - "renesas,scifb-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFB compatible UART. - "renesas,rcar-gen1-scif" for R-Car Gen1 SCIF compatible UART, - - "renesas,rcar-gen2-scif" for R-Car Gen2 SCIF compatible UART, - - "renesas,rcar-gen3-scif" for R-Car Gen3 SCIF compatible UART, - - "renesas,rcar-gen2-scifa" for R-Car Gen2 SCIFA compatible UART, - - "renesas,rcar-gen2-scifb" for R-Car Gen2 SCIFB compatible UART, + - "renesas,rcar-gen2-scif" for R-Car Gen2 and RZ/G1 SCIF compatible UART, + - "renesas,rcar-gen3-scif" for R-Car Gen3 and RZ/G2 SCIF compatible UART, + - "renesas,rcar-gen2-scifa" for R-Car Gen2 and RZ/G1 SCIFA compatible UART, + - "renesas,rcar-gen2-scifb" for R-Car Gen2 and RZ/G1 SCIFB compatible UART, - "renesas,rcar-gen1-hscif" for R-Car Gen1 HSCIF compatible UART, - - "renesas,rcar-gen2-hscif" for R-Car Gen2 HSCIF compatible UART, - - "renesas,rcar-gen3-hscif" for R-Car Gen3 HSCIF compatible UART, + - "renesas,rcar-gen2-hscif" for R-Car Gen2 and RZ/G1 HSCIF compatible UART, + - "renesas,rcar-gen3-hscif" for R-Car Gen3 and RZ/G2 HSCIF compatible UART, - "renesas,scif" for generic SCIF compatible UART. - "renesas,scifa" for generic SCIFA compatible UART. - "renesas,scifb" for generic SCIFB compatible UART. diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 9d03b2ff5df6..2e2ffe7010aa 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -66,6 +66,14 @@ config TTY_PRINTK If unsure, say N. +config TTY_PRINTK_LEVEL + depends on TTY_PRINTK + int "ttyprintk log level (1-7)" + range 1 7 + default "6" + help + Printk log level to use for ttyprintk messages. + config PRINTER tristate "Parallel printer support" depends on PARPORT diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index 67549ce88cc9..88808dbba486 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -37,6 +37,8 @@ static struct ttyprintk_port tpk_port; */ #define TPK_STR_SIZE 508 /* should be bigger then max expected line length */ #define TPK_MAX_ROOM 4096 /* we could assume 4K for instance */ +#define TPK_PREFIX KERN_SOH __stringify(CONFIG_TTY_PRINTK_LEVEL) + static int tpk_curr; static char tpk_buffer[TPK_STR_SIZE + 4]; @@ -45,7 +47,7 @@ static void tpk_flush(void) { if (tpk_curr > 0) { tpk_buffer[tpk_curr] = '\0'; - pr_info("[U] %s\n", tpk_buffer); + printk(TPK_PREFIX "[U] %s\n", tpk_buffer); tpk_curr = 0; } } diff --git a/drivers/gnss/serial.c b/drivers/gnss/serial.c index 31e891f00175..def64b36d994 100644 --- a/drivers/gnss/serial.c +++ b/drivers/gnss/serial.c @@ -65,7 +65,7 @@ static int gnss_serial_write_raw(struct gnss_device *gdev, /* write is only buffered synchronously */ ret = serdev_device_write(serdev, buf, count, MAX_SCHEDULE_TIMEOUT); - if (ret < 0) + if (ret < 0 || ret < count) return ret; /* FIXME: determine if interrupted? */ diff --git a/drivers/gnss/sirf.c b/drivers/gnss/sirf.c index 2c22836d3ffd..226f6e6fe01b 100644 --- a/drivers/gnss/sirf.c +++ b/drivers/gnss/sirf.c @@ -85,7 +85,7 @@ static int sirf_write_raw(struct gnss_device *gdev, const unsigned char *buf, /* write is only buffered synchronously */ ret = serdev_device_write(serdev, buf, count, MAX_SCHEDULE_TIMEOUT); - if (ret < 0) + if (ret < 0 || ret < count) return ret; /* FIXME: determine if interrupted? */ diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c index 77baf895108f..c66412566efc 100644 --- a/drivers/tty/hvc/hvc_opal.c +++ b/drivers/tty/hvc/hvc_opal.c @@ -353,7 +353,7 @@ void __init hvc_opal_init_early(void) if (!opal) return; for_each_child_of_node(opal, np) { - if (!strcmp(np->name, "serial")) { + if (of_node_name_eq(np, "serial")) { stdout_node = np; break; } diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c index 59eaa620bf13..6de6d4a1a221 100644 --- a/drivers/tty/hvc/hvc_vio.c +++ b/drivers/tty/hvc/hvc_vio.c @@ -371,20 +371,11 @@ device_initcall(hvc_vio_init); /* after drivers/tty/hvc/hvc_console.c */ void __init hvc_vio_init_early(void) { const __be32 *termno; - const char *name; const struct hv_ops *ops; /* find the boot console from /chosen/stdout */ - if (!of_stdout) - return; - name = of_get_property(of_stdout, "name", NULL); - if (!name) { - printk(KERN_WARNING "stdout node missing 'name' property!\n"); - return; - } - /* Check if it's a virtual terminal */ - if (strncmp(name, "vty", 3) != 0) + if (!of_node_name_prefix(of_stdout, "vty")) return; termno = of_get_property(of_stdout, "reg", NULL); if (termno == NULL) diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index dabb391909aa..99460af61b77 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -612,7 +612,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, } /* no data */ - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { ret = -EAGAIN; break; } @@ -679,7 +679,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, if (tbuf) break; - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { error = -EAGAIN; break; } diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 749a608c40b0..f75696f0ee2d 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -1085,7 +1085,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, pMsg = remove_msg(pInfo, pClient); if (pMsg == NULL) { /* no messages available. */ - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { ret = -EAGAIN; goto unlock; } diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 3ad460219fd6..5dc9686697cf 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1702,7 +1702,7 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, down_read(&tty->termios_rwsem); - while (1) { + do { /* * When PARMRK is set, each input char may take up to 3 chars * in the read buf; reduce the buffer space avail by 3x @@ -1744,7 +1744,7 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, fp += n; count -= n; rcvd += n; - } + } while (!test_bit(TTY_LDISC_CHANGING, &tty->flags)); tty->receive_room = room; @@ -2211,7 +2211,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, break; if (!timeout) break; - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { retval = -EAGAIN; break; } @@ -2365,7 +2365,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, } if (!nr) break; - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { retval = -EAGAIN; break; } diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 9db93f500b4e..a0ac16ee6575 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -15,6 +15,7 @@ #include <linux/of_device.h> #include <linux/pm_domain.h> #include <linux/pm_runtime.h> +#include <linux/sched.h> #include <linux/serdev.h> #include <linux/slab.h> @@ -216,6 +217,21 @@ void serdev_device_write_wakeup(struct serdev_device *serdev) } EXPORT_SYMBOL_GPL(serdev_device_write_wakeup); +/** + * serdev_device_write_buf() - write data asynchronously + * @serdev: serdev device + * @buf: data to be written + * @count: number of bytes to write + * + * Write data to the device asynchronously. + * + * Note that any accepted data has only been buffered by the controller; use + * serdev_device_wait_until_sent() to make sure the controller write buffer + * has actually been emptied. + * + * Return: The number of bytes written (less than count if not enough room in + * the write buffer), or a negative errno on errors. + */ int serdev_device_write_buf(struct serdev_device *serdev, const unsigned char *buf, size_t count) { @@ -228,17 +244,42 @@ int serdev_device_write_buf(struct serdev_device *serdev, } EXPORT_SYMBOL_GPL(serdev_device_write_buf); +/** + * serdev_device_write() - write data synchronously + * @serdev: serdev device + * @buf: data to be written + * @count: number of bytes to write + * @timeout: timeout in jiffies, or 0 to wait indefinitely + * + * Write data to the device synchronously by repeatedly calling + * serdev_device_write() until the controller has accepted all data (unless + * interrupted by a timeout or a signal). + * + * Note that any accepted data has only been buffered by the controller; use + * serdev_device_wait_until_sent() to make sure the controller write buffer + * has actually been emptied. + * + * Note that this function depends on serdev_device_write_wakeup() being + * called in the serdev driver write_wakeup() callback. + * + * Return: The number of bytes written (less than count if interrupted), + * -ETIMEDOUT or -ERESTARTSYS if interrupted before any bytes were written, or + * a negative errno on errors. + */ int serdev_device_write(struct serdev_device *serdev, const unsigned char *buf, size_t count, - unsigned long timeout) + long timeout) { struct serdev_controller *ctrl = serdev->ctrl; + int written = 0; int ret; - if (!ctrl || !ctrl->ops->write_buf || - (timeout && !serdev->ops->write_wakeup)) + if (!ctrl || !ctrl->ops->write_buf || !serdev->ops->write_wakeup) return -EINVAL; + if (timeout == 0) + timeout = MAX_SCHEDULE_TIMEOUT; + mutex_lock(&serdev->write_lock); do { reinit_completion(&serdev->write_comp); @@ -247,14 +288,29 @@ int serdev_device_write(struct serdev_device *serdev, if (ret < 0) break; + written += ret; buf += ret; count -= ret; - } while (count && - (timeout = wait_for_completion_timeout(&serdev->write_comp, - timeout))); + if (count == 0) + break; + + timeout = wait_for_completion_interruptible_timeout(&serdev->write_comp, + timeout); + } while (timeout > 0); mutex_unlock(&serdev->write_lock); - return ret < 0 ? ret : (count ? -ETIMEDOUT : 0); + + if (ret < 0) + return ret; + + if (timeout <= 0 && written == 0) { + if (timeout == -ERESTARTSYS) + return -ERESTARTSYS; + else + return -ETIMEDOUT; + } + + return written; } EXPORT_SYMBOL_GPL(serdev_device_write); diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c index 435bec40dee6..0438d9a905ce 100644 --- a/drivers/tty/serial/8250/8250_aspeed_vuart.c +++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c @@ -5,6 +5,10 @@ * Copyright (C) 2016 Jeremy Kerr <jk@ozlabs.org>, IBM Corp. * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp. */ +#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include <linux/device.h> #include <linux/module.h> #include <linux/of_address.h> @@ -293,7 +297,7 @@ static int aspeed_vuart_handle_irq(struct uart_port *port) if (lsr & UART_LSR_THRE) serial8250_tx_chars(up); - spin_unlock_irqrestore(&port->lock, flags); + uart_unlock_and_check_sysrq(port, flags); return 1; } diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 94f3e1c64490..189ab1212d9a 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -942,6 +942,21 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * return NULL; } +static void serial_8250_overrun_backoff_work(struct work_struct *work) +{ + struct uart_8250_port *up = + container_of(to_delayed_work(work), struct uart_8250_port, + overrun_backoff); + struct uart_port *port = &up->port; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + up->ier |= UART_IER_RLSI | UART_IER_RDI; + up->port.read_status_mask |= UART_LSR_DR; + serial_out(up, UART_IER, up->ier); + spin_unlock_irqrestore(&port->lock, flags); +} + /** * serial8250_register_8250_port - register a serial port * @up: serial port template @@ -1056,6 +1071,16 @@ int serial8250_register_8250_port(struct uart_8250_port *up) ret = 0; } } + + /* Initialise interrupt backoff work if required */ + if (up->overrun_backoff_time_ms > 0) { + uart->overrun_backoff_time_ms = up->overrun_backoff_time_ms; + INIT_DELAYED_WORK(&uart->overrun_backoff, + serial_8250_overrun_backoff_work); + } else { + uart->overrun_backoff_time_ms = 0; + } + mutex_unlock(&serial_mutex); return ret; diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c index 6640a4c7ddd1..aa0e216d5ead 100644 --- a/drivers/tty/serial/8250/8250_fsl.c +++ b/drivers/tty/serial/8250/8250_fsl.c @@ -1,4 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 +#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include <linux/serial_reg.h> #include <linux/serial_8250.h> @@ -45,8 +49,29 @@ int fsl8250_handle_irq(struct uart_port *port) lsr = orig_lsr = up->port.serial_in(&up->port, UART_LSR); - if (lsr & (UART_LSR_DR | UART_LSR_BI)) + /* Process incoming characters first */ + if ((lsr & (UART_LSR_DR | UART_LSR_BI)) && + (up->ier & (UART_IER_RLSI | UART_IER_RDI))) { lsr = serial8250_rx_chars(up, lsr); + } + + /* Stop processing interrupts on input overrun */ |
