diff mbox series

[v3,3/8] serial: core, 8250: set RS485 termination gpio in serial core

Message ID 20220710150322.2846170-4-LinoSanfilippo@gmx.de
State Superseded
Headers show
Series Fixes and cleanup for RS485 | expand

Commit Message

Lino Sanfilippo July 10, 2022, 3:03 p.m. UTC
From: Lino Sanfilippo <l.sanfilippo@kunbus.com>

In serial8250_em485_config() the termination GPIO is set with the uart_port
spinlock held. This is an issue if setting the GPIO line can sleep (e.g.
since the concerning GPIO expander is connected via SPI or I2C).

Fix this by setting the termination line outside of the uart_port spinlock
in the serial core and using gpiod_set_value_cansleep() which instead of
gpiod_set_value() allows it to sleep.

Beside fixing the termination GPIO line setting for the 8250 driver this
change also makes setting the termination GPIO generic for all UART
drivers.

Signed-off-by: Lino Sanfilippo <l.sanfilippo@kunbus.com>
---
 drivers/tty/serial/8250/8250_port.c |  3 ---
 drivers/tty/serial/serial_core.c    | 12 ++++++++++++
 2 files changed, 12 insertions(+), 3 deletions(-)

Comments

kernel test robot July 10, 2022, 4:07 p.m. UTC | #1
Hi Lino,

I love your patch! Perhaps something to improve:

[auto build test WARNING on 7e5b4322cde067e1d0f1bf8f490e93f664a7c843]

url:    https://github.com/intel-lab-lkp/linux/commits/Lino-Sanfilippo/Fixes-and-cleanup-for-RS485/20220710-230624
base:   7e5b4322cde067e1d0f1bf8f490e93f664a7c843
config: hexagon-randconfig-r041-20220710 (https://download.01.org/0day-ci/archive/20220710/202207102355.Y27cvu6y-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 6ce63e267aab79ca87bf63453d34dd3909ab978d)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/846f02e6da9692810ed632dd72f45af667c3cc67
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Lino-Sanfilippo/Fixes-and-cleanup-for-RS485/20220710-230624
        git checkout 846f02e6da9692810ed632dd72f45af667c3cc67
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/tty/serial/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/tty/serial/serial_core.c:1364:6: warning: logical not is only applied to the left hand side of this bitwise operator [-Wlogical-not-parentheses]
           if (!rs485->flags & SER_RS485_ENABLED)
               ^             ~
   drivers/tty/serial/serial_core.c:1364:6: note: add parentheses after the '!' to evaluate the bitwise operator first
           if (!rs485->flags & SER_RS485_ENABLED)
               ^
                (                               )
   drivers/tty/serial/serial_core.c:1364:6: note: add parentheses around left hand side expression to silence this warning
           if (!rs485->flags & SER_RS485_ENABLED)
               ^
               (            )
   1 warning generated.


vim +1364 drivers/tty/serial/serial_core.c

  1360	
  1361	static void uart_set_rs485_termination(struct uart_port *port,
  1362					       const struct serial_rs485 *rs485)
  1363	{
> 1364		if (!rs485->flags & SER_RS485_ENABLED)
  1365			return;
  1366	
  1367		gpiod_set_value_cansleep(port->rs485_term_gpio,
  1368					 !!(rs485->flags & SER_RS485_TERMINATE_BUS));
  1369	}
  1370
diff mbox series

Patch

diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index ed2a606f2da7..72252d956f17 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -676,9 +676,6 @@  int serial8250_em485_config(struct uart_port *port, struct ktermios *termios,
 		rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
 	}
 
-	gpiod_set_value(port->rs485_term_gpio,
-			rs485->flags & SER_RS485_TERMINATE_BUS);
-
 	/*
 	 * Both serial8250_em485_init() and serial8250_em485_destroy()
 	 * are idempotent.
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 1db44cde76f6..612a97788341 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1358,12 +1358,23 @@  static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs4
 	memset(rs485->padding1, 0, sizeof(rs485->padding1));
 }
 
+static void uart_set_rs485_termination(struct uart_port *port,
+				       const struct serial_rs485 *rs485)
+{
+	if (!rs485->flags & SER_RS485_ENABLED)
+		return;
+
+	gpiod_set_value_cansleep(port->rs485_term_gpio,
+				 !!(rs485->flags & SER_RS485_TERMINATE_BUS));
+}
+
 int uart_rs485_config(struct uart_port *port)
 {
 	struct serial_rs485 *rs485 = &port->rs485;
 	int ret;
 
 	uart_sanitize_serial_rs485(port, rs485);
+	uart_set_rs485_termination(port, rs485);
 
 	ret = port->rs485_config(port, NULL, rs485);
 	if (ret)
@@ -1406,6 +1417,7 @@  static int uart_set_rs485_config(struct tty_struct *tty, struct uart_port *port,
 	if (ret)
 		return ret;
 	uart_sanitize_serial_rs485(port, &rs485);
+	uart_set_rs485_termination(port, &rs485);
 
 	spin_lock_irqsave(&port->lock, flags);
 	ret = port->rs485_config(port, &tty->termios, &rs485);