Takashi Iwai 49170b
From 93a770b7e16772530196674ffc79bb13fa927dc6 Mon Sep 17 00:00:00 2001
Takashi Iwai 49170b
From: Lukas Wunner <lukas@wunner.de>
Takashi Iwai 49170b
Date: Sun, 2 Jan 2022 18:52:44 +0100
Takashi Iwai 49170b
Subject: [PATCH] serial: core: Keep mctrl register state and cached copy in sync
Takashi Iwai 49170b
Git-commit: 93a770b7e16772530196674ffc79bb13fa927dc6
Takashi Iwai 49170b
Patch-mainline: v5.17-rc1
Takashi Iwai 49170b
References: git-fixes
Takashi Iwai 49170b
Takashi Iwai 49170b
struct uart_port contains a cached copy of the Modem Control signals.
Takashi Iwai 49170b
It is used to skip register writes in uart_update_mctrl() if the new
Takashi Iwai 49170b
signal state equals the old signal state.  It also avoids a register
Takashi Iwai 49170b
read to obtain the current state of output signals.
Takashi Iwai 49170b
Takashi Iwai 49170b
When a uart_port is registered, uart_configure_port() changes signal
Takashi Iwai 49170b
state but neglects to keep the cached copy in sync.  That may cause
Takashi Iwai 49170b
a subsequent register write to be incorrectly skipped.  Fix it before
Takashi Iwai 49170b
it trips somebody up.
Takashi Iwai 49170b
Takashi Iwai 49170b
This behavior has been present ever since the serial core was introduced
Takashi Iwai 49170b
in 2002:
Takashi Iwai 49170b
https://git.kernel.org/history/history/c/33c0d1b0c3eb
Takashi Iwai 49170b
Takashi Iwai 49170b
So far it was never an issue because the cached copy is initialized to 0
Takashi Iwai 49170b
by kzalloc() and when uart_configure_port() is executed, at most DTR has
Takashi Iwai 49170b
been set by uart_set_options() or sunsu_console_setup().  Therefore,
Takashi Iwai 49170b
a stable designation seems unnecessary.
Takashi Iwai 49170b
Takashi Iwai 49170b
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Takashi Iwai 49170b
Link: https://lore.kernel.org/r/bceeaba030b028ed810272d55d5fc6f3656ddddb.1641129752.git.lukas@wunner.de
Takashi Iwai 49170b
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Takashi Iwai 49170b
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai 49170b
Takashi Iwai 49170b
---
Takashi Iwai 49170b
 drivers/tty/serial/serial_core.c | 3 ++-
Takashi Iwai 49170b
 1 file changed, 2 insertions(+), 1 deletion(-)
Takashi Iwai 49170b
Takashi Iwai 49170b
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
Takashi Iwai 49170b
index 259f28ec6c8b..dc40c4155356 100644
Takashi Iwai 49170b
--- a/drivers/tty/serial/serial_core.c
Takashi Iwai 49170b
+++ b/drivers/tty/serial/serial_core.c
Takashi Iwai 49170b
@@ -2389,7 +2389,8 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
Takashi Iwai 49170b
 		 * We probably don't need a spinlock around this, but
Takashi Iwai 49170b
 		 */
Takashi Iwai 49170b
 		spin_lock_irqsave(&port->lock, flags);
Takashi Iwai 49170b
-		port->ops->set_mctrl(port, port->mctrl & TIOCM_DTR);
Takashi Iwai 49170b
+		port->mctrl &= TIOCM_DTR;
Takashi Iwai 49170b
+		port->ops->set_mctrl(port, port->mctrl);
Takashi Iwai 49170b
 		spin_unlock_irqrestore(&port->lock, flags);
Takashi Iwai 49170b
 
Takashi Iwai 49170b
 		/*
Takashi Iwai 49170b
-- 
Takashi Iwai 49170b
2.31.1
Takashi Iwai 49170b