Re: [PATCH v4 2/4] serial: 8250: introduce serial8250_discard_data()

From: Jiri Slaby
Date: Fri Apr 25 2025 - 02:49:09 EST


On 25. 04. 25, 8:24, Yunhui Cui wrote:
To prevent triggering PSLVERR, it is necessary to check whether the
UART_LSR_DR bit of UART_LSR is set before reading UART_RX.
Ensure atomicity of UART_LSR and UART_RX, put serial8250_discard_data()
under port->lock.

Signed-off-by: Yunhui Cui <cuiyunhui@xxxxxxxxxxxxx>
---
drivers/tty/serial/8250/8250.h | 15 +++++++++++
drivers/tty/serial/8250/8250_port.c | 42 ++++++++++++++---------------
2 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index b861585ca02a..5a106cf88207 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -162,6 +162,21 @@ static inline u16 serial_lsr_in(struct uart_8250_port *up)
return lsr;
}
+/*
+ * To avoid PSLVERR, check UART_LSR_DR in UART_LSR before
+ * reading UART_RX.
+ */
+static inline unsigned int serial8250_discard_data(struct uart_8250_port *up)
+{
+ u16 lsr;

Is lsr really 16-bit?

+
+ lsr = serial_in(up, UART_LSR);
+ if (lsr & UART_LSR_DR)
+ return serial_in(up, UART_RX);

Why does a discard function return a value at all?

+
+ return 0;
+}
+
/*
* For the 16C950
*/
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index a913135d5217..802ac50357c0 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
...
@@ -2137,25 +2136,21 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
static int serial8250_get_poll_char(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
- int status;
+ int status = NO_POLL_CHAR;
u16 lsr;
serial8250_rpm_get(up);
+ uart_port_lock_irqsave(port, &flags);
lsr = serial_port_in(port, UART_LSR);
-
- if (!(lsr & UART_LSR_DR)) {
- status = NO_POLL_CHAR;
- goto out;
- }
-
- status = serial_port_in(port, UART_RX);
+ if ((lsr & UART_LSR_DR))

Too many parentheses.

+ status = serial_port_in(port, UART_RX);
+ uart_port_unlock_irqrestore(port, flags);

thanks,
--
js
suse labs