Skip to content

Commit

Permalink
serial: core: Consider rs485 settings to drive RTS
Browse files Browse the repository at this point in the history
Previously the rs485 settings weren't considered when setting the RTS
line, so e.g. closing and reopening a port made serial_core to drive
the line as if rs485 was disabled.

This patch fixes those issues.

Signed-off-by: Rafael Gago Castano <rgc@hms.se>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Rafael Gago authored and Greg Kroah-Hartman committed Aug 28, 2017
1 parent d77dc47 commit a6845e1
Showing 1 changed file with 25 additions and 9 deletions.
34 changes: 25 additions & 9 deletions drivers/tty/serial/serial_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,27 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
#define uart_set_mctrl(port, set) uart_update_mctrl(port, set, 0)
#define uart_clear_mctrl(port, clear) uart_update_mctrl(port, 0, clear)

static void uart_port_dtr_rts(struct uart_port *uport, int raise)
{
int rs485_on = uport->rs485_config &&
(uport->rs485.flags & SER_RS485_ENABLED);
int RTS_after_send = !!(uport->rs485.flags & SER_RS485_RTS_AFTER_SEND);

if (raise) {
if (rs485_on && !RTS_after_send) {
uart_set_mctrl(uport, TIOCM_DTR);
uart_clear_mctrl(uport, TIOCM_RTS);
} else {
uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
}
} else {
unsigned int clear = TIOCM_DTR;

clear |= (!rs485_on || !RTS_after_send) ? TIOCM_RTS : 0;
uart_clear_mctrl(uport, clear);
}
}

/*
* Startup the port. This will be called once per open. All calls
* will be serialised by the per-port mutex.
Expand Down Expand Up @@ -214,7 +235,7 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
* port is open and ready to respond.
*/
if (init_hw && C_BAUD(tty))
uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
uart_port_dtr_rts(uport, 1);
}

/*
Expand Down Expand Up @@ -272,7 +293,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
uport->cons->cflag = tty->termios.c_cflag;

if (!tty || C_HUPCL(tty))
uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
uart_port_dtr_rts(uport, 0);

uart_port_shutdown(port);
}
Expand Down Expand Up @@ -1658,20 +1679,15 @@ static int uart_carrier_raised(struct tty_port *port)
return 0;
}

static void uart_dtr_rts(struct tty_port *port, int onoff)
static void uart_dtr_rts(struct tty_port *port, int raise)
{
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport;

uport = uart_port_ref(state);
if (!uport)
return;

if (onoff)
uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
else
uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);

uart_port_dtr_rts(uport, raise);
uart_port_deref(uport);
}

Expand Down

0 comments on commit a6845e1

Please sign in to comment.