Commit 4afeced5 authored by Lino Sanfilippo's avatar Lino Sanfilippo Committed by Greg Kroah-Hartman
Browse files

serial: core: fix sanitizing check for RTS settings



Among other things uart_sanitize_serial_rs485() tests the sanity of the RTS
settings in a RS485 configuration that has been passed by userspace.
If RTS-on-send and RTS-after-send are both set or unset the configuration
is adjusted and RTS-after-send is disabled and RTS-on-send enabled.

This however makes only sense if both RTS modes are actually supported by
the driver.

With commit be2e2cb1 ("serial: Sanitize rs485_struct") the code does
take the driver support into account but only checks if one of both RTS
modes are supported. This may lead to the errorneous result of RTS-on-send
being set even if only RTS-after-send is supported.

Fix this by changing the implemented logic: First clear all unsupported
flags in the RS485 configuration, then adjust an invalid RTS setting by
taking into account which RTS mode is supported.

Cc:  <stable@vger.kernel.org>
Fixes: be2e2cb1 ("serial: Sanitize rs485_struct")
Reviewed-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: default avatarLino Sanfilippo <l.sanfilippo@kunbus.com>
Link: https://lore.kernel.org/r/20240103061818.564-4-l.sanfilippo@kunbus.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1a33e33c
Loading
Loading
Loading
Loading
+18 −10
Original line number Diff line number Diff line
@@ -1376,19 +1376,27 @@ static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs4
		return;
	}

	rs485->flags &= supported_flags;

	/* Pick sane settings if the user hasn't */
	if ((supported_flags & (SER_RS485_RTS_ON_SEND|SER_RS485_RTS_AFTER_SEND)) &&
	    !(rs485->flags & SER_RS485_RTS_ON_SEND) ==
	if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
	    !(rs485->flags & SER_RS485_RTS_AFTER_SEND)) {
		if (supported_flags & SER_RS485_RTS_ON_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;
	}
		} else {
			rs485->flags |= SER_RS485_RTS_AFTER_SEND;
			rs485->flags &= ~SER_RS485_RTS_ON_SEND;

	rs485->flags &= supported_flags;
			dev_warn_ratelimited(port->dev,
				"%s (%d): invalid RTS setting, using RTS_AFTER_SEND instead\n",
				port->name, port->line);
		}
	}

	uart_sanitize_serial_rs485_delays(port, rs485);