Skip to content

Commit

Permalink
serial: 8250: Support console on software emulated rs485 ports
Browse files Browse the repository at this point in the history
Commit e490c91 ("tty: Add software emulated RS485 support for 8250")
introduced support to use RTS as an rs485 Transmit Enable signal if data
is transmitted through the tty layer.

Console messages bypass the tty layer and instead are emitted via
serial8250_console_write().  Amend that function to drive RTS as well,
allowing for a console on rs485 ports.

Note that serial8250_console_write() may be called concurrently to the
tty layer accessing the port.  The two protect their accesses with the
port lock, but serial8250_console_write() may find RTS still being
asserted by the tty layer, in which case it shouldn't be deasserted
after the console message has been printed.  Recognize such situations
by checking the em485->tx_stopped flag.

If a delay_rts_before_send or delay_rts_after_send has been specified,
serial8250_console_write() busy-waits for its duration.  Optimizations
for those wait times are conceivable:  E.g. if RTS is already asserted,
we could check whether em485->start_tx_timer is active and wait only
for the remaining expire time.  But this would require calling into
the hrtimer infrastructure, which involves acquiring locks and
potentially reprogramming timer hardware.  Such operations seem too
risky in the context of console printout, which needs to work even when
the kernel has crashed and emits a BUG splat.  So I've gone with a
simplistic solution which just always waits for the full delay.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: Matwey V. Kornilov <matwey@sai.msu.ru>
Link: https://lore.kernel.org/r/65edffce4670a19e598015c03cbe46f1ffd93e43.1582895077.git.lukas@wunner.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Lukas Wunner authored and Greg Kroah-Hartman committed Mar 7, 2020
1 parent f93bf75 commit 7f98030
Showing 1 changed file with 13 additions and 0 deletions.
13 changes: 13 additions & 0 deletions drivers/tty/serial/8250/8250_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -3204,6 +3204,7 @@ static void serial8250_console_restore(struct uart_8250_port *up)
void serial8250_console_write(struct uart_8250_port *up, const char *s,
unsigned int count)
{
struct uart_8250_em485 *em485 = up->em485;
struct uart_port *port = &up->port;
unsigned long flags;
unsigned int ier;
Expand Down Expand Up @@ -3234,6 +3235,12 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
up->canary = 0;
}

if (em485) {
if (em485->tx_stopped)
up->rs485_start_tx(up);
mdelay(port->rs485.delay_rts_before_send);
}

uart_console_write(port, s, count, serial8250_console_putchar);

/*
Expand All @@ -3243,6 +3250,12 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
wait_for_xmitr(up, BOTH_EMPTY);
serial_port_out(port, UART_IER, ier);

if (em485) {
mdelay(port->rs485.delay_rts_before_send);
if (em485->tx_stopped)
up->rs485_stop_tx(up);
}

/*
* The receive handling will happen properly because the
* receive ready bit will still be set; it is not cleared
Expand Down

0 comments on commit 7f98030

Please sign in to comment.