summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>2022-06-06 13:04:19 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-06-10 13:49:57 +0200
commitbe2e2cb1d28195792539ac2539f8c40c39d3dd4c (patch)
tree4249ae287f350aa0713c4db269bc50dbdff87da9 /drivers
parentaeae8f222fdd34bdddc1050dc073e56b2242c9b5 (diff)
downloadlinux-stable-be2e2cb1d28195792539ac2539f8c40c39d3dd4c.tar.gz
linux-stable-be2e2cb1d28195792539ac2539f8c40c39d3dd4c.tar.bz2
linux-stable-be2e2cb1d28195792539ac2539f8c40c39d3dd4c.zip
serial: Sanitize rs485_struct
Sanitize serial_rs485 struct before calling into rs485_setup. The drivers provide supported_rs485 to help sanitization of the fields. If neither of SER_RS485_RTS_ON_SEND or SER_RS485_RTS_AFTER_SEND supported, don't pretend they can be set to sane settings but clear them both instead. If only one of them is supported it may look tempting to use the one driver supports to set the other, however, the userspace does not have that information readily available so it wouldn't be helpful. While adjusting the documentation, remove also the claim that TIOCGRS485 would call driver specific code. In reality, it does nothing else than copies the stored serial_rs485 structure from uart_port to userspace. Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Link: https://lore.kernel.org/r/20220606100433.13793-23-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/tty/serial/serial_core.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 44a50158552d..f0d7b3d20731 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1278,36 +1278,61 @@ static int uart_get_icount(struct tty_struct *tty,
static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs485 *rs485)
{
+ u32 supported_flags = port->rs485_supported->flags;
+
/* pick sane settings if the user hasn't */
- if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
+ if ((supported_flags & (SER_RS485_RTS_ON_SEND|SER_RS485_RTS_AFTER_SEND)) &&
+ !(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;
+ supported_flags |= SER_RS485_RTS_ON_SEND|SER_RS485_RTS_AFTER_SEND;
}
- if (rs485->delay_rts_before_send > RS485_MAX_RTS_DELAY) {
+ if (!port->rs485_supported->delay_rts_before_send) {
+ if (rs485->delay_rts_before_send) {
+ dev_warn_ratelimited(port->dev,
+ "%s (%d): RTS delay before sending not supported\n",
+ port->name, port->line);
+ }
+ rs485->delay_rts_before_send = 0;
+ } else 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) {
+ if (!port->rs485_supported->delay_rts_after_send) {
+ if (rs485->delay_rts_after_send) {
+ dev_warn_ratelimited(port->dev,
+ "%s (%d): RTS delay after sending not supported\n",
+ port->name, port->line);
+ }
+ rs485->delay_rts_after_send = 0;
+ } else 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);
}
+
+ rs485->flags &= supported_flags;
+
/* Return clean padding area to userspace */
memset(rs485->padding, 0, sizeof(rs485->padding));
}
int uart_rs485_config(struct uart_port *port)
{
- return port->rs485_config(port, &port->rs485);
+ struct serial_rs485 *rs485 = &port->rs485;
+
+ uart_sanitize_serial_rs485(port, rs485);
+
+ return port->rs485_config(port, rs485);
}
EXPORT_SYMBOL_GPL(uart_rs485_config);