tty: serial_core: Set port active bit in uart_port_activate [Linux 4.9.187]

This Linux kernel change "tty: serial_core: Set port active bit in uart_port_activate" is included in the Linux 4.9.187 release. This change is authored by Serge Semin <fancer.lancer [at] gmail.com> on Wed May 8 13:44:41 2019 +0300. The commit for this change in Linux stable tree is 4780759 (patch) which is from upstream commit 13b18d3. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 13b18d3.

tty: serial_core: Set port active bit in uart_port_activate

[ Upstream commit 13b18d35909707571af9539f7731389fbf0feb31 ]

A bug was introduced by commit b3b576461864 ("tty: serial_core: convert
uart_open to use tty_port_open"). It caused a constant warning printed
into the system log regarding the tty and port counter mismatch:

[   21.644197] ttyS ttySx: tty_port_close_start: tty->count = 1 port count = 2

in case if session hangup was detected so the warning is printed starting
from the second open-close iteration.

Particularly the problem was discovered in situation when there is a
serial tty device without hardware back-end being setup. It is considered
by the tty-serial subsystems as a hardware problem with session hang up.
In this case uart_startup() will return a positive value with TTY_IO_ERROR
flag set in corresponding tty_struct instance. The same value will get
passed to be returned from the activate() callback and then being returned
from tty_port_open(). But since in this case tty_port_block_til_ready()
isn't called the TTY_PORT_ACTIVE flag isn't set (while the method had been
called before tty_port_open conversion was introduced and the rest of the
subsystem code expected the bit being set in this case), which prevents the
uart_hangup() method to perform any cleanups including the tty port
counter setting to zero. So the next attempt to open/close the tty device
will discover the counters mismatch.

In order to fix the problem we need to manually set the TTY_PORT_ACTIVE
flag in case if uart_startup() returned a positive value. In this case
the hang up procedure will perform a full set of cleanup actions including
the port ref-counter resetting.

Fixes: b3b576461864 "tty: serial_core: convert uart_open to use tty_port_open"
Signed-off-by: Serge Semin <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>

There are 7 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/tty/serial/serial_core.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 680fb3f..04c023f 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1725,6 +1725,7 @@ static int uart_port_activate(struct tty_port *port, struct tty_struct *tty)
 {
    struct uart_state *state = container_of(port, struct uart_state, port);
    struct uart_port *uport;
+   int ret;

    uport = uart_port_check(state);
    if (!uport || uport->flags & UPF_DEAD)
@@ -1735,7 +1736,11 @@ static int uart_port_activate(struct tty_port *port, struct tty_struct *tty)
    /*
     * Start up the serial port.
     */
-   return uart_startup(tty, state, 0);
+   ret = uart_startup(tty, state, 0);
+   if (ret > 0)
+       tty_port_set_active(port, 1);
+
+   return ret;
 }

 static const char *uart_type(struct uart_port *port)

Leave a Reply

Your email address will not be published. Required fields are marked *