summaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/8250/8250_fsl.c
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2022-07-04 10:51:19 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-07-08 15:13:22 +0200
commit9d3aaceb73acadf134596a2f8db9c451c1332d3d (patch)
tree3d130c1e0a3ffda5a2937afa62a0ec2796f1763b /drivers/tty/serial/8250/8250_fsl.c
parent7349660438603ed19282e75949561406531785a5 (diff)
downloadlinux-9d3aaceb73acadf134596a2f8db9c451c1332d3d.tar.bz2
serial: 8250_fsl: Don't report FE, PE and OE twice
Some Freescale 8250 implementations have the problem that a single long break results in one irq per character frame time. The code in fsl8250_handle_irq() that is supposed to handle that uses the BI bit in lsr_saved_flags to detect such a situation and then skip the second received character. However it also stores other error bits and so after a single frame error the character received in the next irq handling is passed to the upper layer with a frame error, too. So after a spike on the data line (which is correctly recognized as a frame error) the following valid character is thrown away, because the driver reports a frame error for that one, too. To weaken this problem restrict saving LSR to only the BI bit. Note however that the handling is still broken: - lsr_saved_flags is updated using orig_lsr which is the LSR content for the first received char, but there might be more in the FIFO, so a character is thrown away that is received later and not necessarily the one following the break. - The doubled break might be the 2nd and 3rd char in the FIFO, so the workaround doesn't catch these, because serial8250_rx_chars() doesn't handle the workaround. - lsr_saved_flags might have set UART_LSR_BI at the entry of fsl8250_handle_irq() which doesn't originate from fsl8250_handle_irq()'s "up->lsr_saved_flags |= orig_lsr & UART_LSR_BI;" but from e.g. from serial8250_tx_empty(). - For a long or a short break this isn't about two characters, but more or only a single one. Fixes: 9deaa53ac7fa ("serial: add irq handler for Freescale 16550 errata.") Acked-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Link: https://lore.kernel.org/r/20220704085119.55900-1-u.kleine-koenig@pengutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/8250/8250_fsl.c')
-rw-r--r--drivers/tty/serial/8250/8250_fsl.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c
index fd4005fcd0d6..8aad15622a2e 100644
--- a/drivers/tty/serial/8250/8250_fsl.c
+++ b/drivers/tty/serial/8250/8250_fsl.c
@@ -77,7 +77,7 @@ int fsl8250_handle_irq(struct uart_port *port)
if ((lsr & UART_LSR_THRE) && (up->ier & UART_IER_THRI))
serial8250_tx_chars(up);
- up->lsr_saved_flags = orig_lsr;
+ up->lsr_saved_flags |= orig_lsr & UART_LSR_BI;
uart_unlock_and_check_sysrq_irqrestore(&up->port, flags);