Skip to content

Commit

Permalink
serial: core: move RS485 configuration tasks from drivers into core
Browse files Browse the repository at this point in the history
commit 0ed12af upstream.

Several drivers that support setting the RS485 configuration via userspace
implement one or more of the following tasks:

- in case of an invalid RTS configuration (both RTS after send and RTS on
  send set or both unset) fall back to enable RTS on send and disable RTS
  after send

- nullify the padding field of the returned serial_rs485 struct

- copy the configuration into the uart port struct

- limit RTS delays to 100 ms

Move these tasks into the serial core to make them generic and to provide
a consistent behaviour among all drivers.

Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
Link: https://lore.kernel.org/r/20220410104642.32195-2-LinoSanfilippo@gmx.de
Signed-off-by: Daisuke Mizobuchi <mizo@atmark-techno.com>
Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
LinoSanfilippo333 authored and gregkh committed Nov 3, 2022
1 parent 0753069 commit 63f75fe
Showing 1 changed file with 33 additions and 0 deletions.
33 changes: 33 additions & 0 deletions drivers/tty/serial/serial_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ static struct lock_class_key port_lock_key;

#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)

/*
* Max time with active RTS before/after data is sent.
*/
#define RS485_MAX_RTS_DELAY 100 /* msecs */

static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
struct ktermios *old_termios);
static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
Expand Down Expand Up @@ -1299,8 +1304,36 @@ static int uart_set_rs485_config(struct uart_port *port,
if (copy_from_user(&rs485, rs485_user, sizeof(*rs485_user)))
return -EFAULT;

/* pick sane settings if the user hasn't */
if (!(rs485.flags & SER_RS485_RTS_ON_SEND) ==
!(rs485.flags & SER_RS485_RTS_AFTER_SEND)) {
dev_warn_ratelimited(port->dev,
"%s (%d): invalid RTS setting, using RTS_ON_SEND instead\n",
port->name, port->line);
rs485.flags |= SER_RS485_RTS_ON_SEND;
rs485.flags &= ~SER_RS485_RTS_AFTER_SEND;
}

if (rs485.delay_rts_before_send > RS485_MAX_RTS_DELAY) {
rs485.delay_rts_before_send = RS485_MAX_RTS_DELAY;
dev_warn_ratelimited(port->dev,
"%s (%d): RTS delay before sending clamped to %u ms\n",
port->name, port->line, rs485.delay_rts_before_send);
}

if (rs485.delay_rts_after_send > RS485_MAX_RTS_DELAY) {
rs485.delay_rts_after_send = RS485_MAX_RTS_DELAY;
dev_warn_ratelimited(port->dev,
"%s (%d): RTS delay after sending clamped to %u ms\n",
port->name, port->line, rs485.delay_rts_after_send);
}
/* Return clean padding area to userspace */
memset(rs485.padding, 0, sizeof(rs485.padding));

spin_lock_irqsave(&port->lock, flags);
ret = port->rs485_config(port, &rs485);
if (!ret)
port->rs485 = rs485;
spin_unlock_irqrestore(&port->lock, flags);
if (ret)
return ret;
Expand Down

0 comments on commit 63f75fe

Please sign in to comment.