From patchwork Fri Feb 28 13:31:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukas Wunner X-Patchwork-Id: 214237 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ECC1FC3F2CD for ; Fri, 28 Feb 2020 13:43:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B65FA246AE for ; Fri, 28 Feb 2020 13:43:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726880AbgB1Nn2 (ORCPT ); Fri, 28 Feb 2020 08:43:28 -0500 Received: from mailout2.hostsharing.net ([83.223.78.233]:50607 "EHLO mailout2.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726151AbgB1Nn2 (ORCPT ); Fri, 28 Feb 2020 08:43:28 -0500 Received: from h08.hostsharing.net (h08.hostsharing.net [IPv6:2a01:37:1000::53df:5f1c:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout2.hostsharing.net (Postfix) with ESMTPS id CF59910189AC1; Fri, 28 Feb 2020 14:36:51 +0100 (CET) Received: from localhost (unknown [87.130.102.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id 8222161249E4; Fri, 28 Feb 2020 14:36:51 +0100 (CET) X-Mailbox-Line: From b1ce34ca9bc4d7bdc6e9852fcf30b1f4e37c8a80 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Lukas Wunner Date: Fri, 28 Feb 2020 14:31:01 +0100 Subject: [PATCH 1/8] serial: 8250: Don't touch RTS modem control while in rs485 mode To: Greg Kroah-Hartman , Jiri Slaby , "Nicolas Saenz Julienne" Cc: "Matwey V. Kornilov" , Heiko Schocher , Giulio Benetti , Uwe Kleine-Koenig , Stefan Wahren , Matthias Brugger , Martin Sperl , linux-serial@vger.kernel.org, linux-rpi-kernel@lists.infradead.org Sender: linux-serial-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org serial8250_do_set_mctrl() currently allows modifying the RTS modem control line even when RTS is used as an rs485 Transmit Enable signal. It is thus possible for user space to interfere with rs485 communication by invoking a TIOCMSET ioctl(). Ignore such change requests and retain the current RTS polarity when in rs485 mode. Note that serial8250_set_mctrl() is always called with port->lock held, so there's no risk that RTS is changed concurrently. Signed-off-by: Lukas Wunner Cc: Matwey V. Kornilov --- drivers/tty/serial/8250/8250_port.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index f398f162a1fd..a8f4cedde4dc 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1924,6 +1924,13 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl) struct uart_8250_port *up = up_to_u8250p(port); unsigned char mcr; + if (port->rs485.flags & SER_RS485_ENABLED) { + if (serial8250_in_MCR(up) & UART_MCR_RTS) + mctrl |= TIOCM_RTS; + else + mctrl &= ~TIOCM_RTS; + } + mcr = serial8250_TIOCM_to_MCR(mctrl); mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; From patchwork Fri Feb 28 13:31:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukas Wunner X-Patchwork-Id: 214239 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D59EEC3F2D2 for ; Fri, 28 Feb 2020 13:40:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A87F6246AE for ; Fri, 28 Feb 2020 13:40:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726151AbgB1Nk0 (ORCPT ); Fri, 28 Feb 2020 08:40:26 -0500 Received: from mailout1.hostsharing.net ([83.223.95.204]:33265 "EHLO mailout1.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725796AbgB1Nk0 (ORCPT ); Fri, 28 Feb 2020 08:40:26 -0500 Received: from h08.hostsharing.net (h08.hostsharing.net [83.223.95.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout1.hostsharing.net (Postfix) with ESMTPS id D17BF101303AB; Fri, 28 Feb 2020 14:40:23 +0100 (CET) Received: from localhost (unknown [87.130.102.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id 9654361249E8; Fri, 28 Feb 2020 14:40:23 +0100 (CET) X-Mailbox-Line: From fcef63642dc4eae41ae7842d23747b2bf5d40285 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Lukas Wunner Date: Fri, 28 Feb 2020 14:31:03 +0100 Subject: [PATCH 3/8] serial: 8250: Deduplicate ->rs485_config() callback To: Greg Kroah-Hartman , Jiri Slaby , "Nicolas Saenz Julienne" Cc: "Matwey V. Kornilov" , Heiko Schocher , Giulio Benetti , Uwe Kleine-Koenig , Stefan Wahren , Matthias Brugger , Martin Sperl , linux-serial@vger.kernel.org, linux-rpi-kernel@lists.infradead.org Sender: linux-serial-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Commit e490c9144cfa ("tty: Add software emulated RS485 support for 8250") introduced support to use RTS as an rs485 Transmit Enable signal. Drivers opt in to the feature by calling serial8250_em485_init() from their ->rs485_config() callback. So far there are two drivers doing that, 8250_omap.c and 8250_of.c. Both use an identical callback. We're about to add a third user of that callback, therefore deduplicate it and move it to 8250_port.c. Drivers now opt in to rs485 software emulation by assigning the generic serial8250_rs485_config() callback introduced herein to their .rs485_config struct member. This change allows unexporting serial8250_em485_init() and declaring it static. Signed-off-by: Lukas Wunner Cc: Matwey V. Kornilov Cc: Heiko Schocher --- drivers/tty/serial/8250/8250.h | 2 +- drivers/tty/serial/8250/8250_of.c | 32 +--------------------- drivers/tty/serial/8250/8250_omap.c | 32 +--------------------- drivers/tty/serial/8250/8250_port.c | 41 +++++++++++++++++++++++++++-- 4 files changed, 42 insertions(+), 65 deletions(-) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 33ad9d6de532..e83b66e0f593 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -156,7 +156,7 @@ void serial8250_rpm_put(struct uart_8250_port *p); void serial8250_rpm_get_tx(struct uart_8250_port *p); void serial8250_rpm_put_tx(struct uart_8250_port *p); -int serial8250_em485_init(struct uart_8250_port *p); +int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485); void serial8250_em485_destroy(struct uart_8250_port *p); /* MCR <-> TIOCM conversion */ diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index ad92f451f3b9..4a68a8785caa 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -25,36 +25,6 @@ struct of_serial_info { int line; }; -static int of_8250_rs485_config(struct uart_port *port, - struct serial_rs485 *rs485) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - /* Clamp the delays to [0, 100ms] */ - rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); - rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); - - port->rs485 = *rs485; - - /* - * Both serial8250_em485_init and serial8250_em485_destroy - * are idempotent - */ - if (rs485->flags & SER_RS485_ENABLED) { - int ret = serial8250_em485_init(up); - - if (ret) { - rs485->flags &= ~SER_RS485_ENABLED; - port->rs485.flags &= ~SER_RS485_ENABLED; - } - return ret; - } - - serial8250_em485_destroy(up); - - return 0; -} - /* * Fill a struct uart_port for a given device node */ @@ -184,7 +154,7 @@ static int of_platform_serial_setup(struct platform_device *ofdev, port->flags |= UPF_SKIP_TEST; port->dev = &ofdev->dev; - port->rs485_config = of_8250_rs485_config; + port->rs485_config = serial8250_em485_config; switch (type) { case PORT_RT2880: diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 6f343ca08440..fff70cb25046 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -714,36 +714,6 @@ static void omap_8250_throttle(struct uart_port *port) pm_runtime_put_autosuspend(port->dev); } -static int omap_8250_rs485_config(struct uart_port *port, - struct serial_rs485 *rs485) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - /* Clamp the delays to [0, 100ms] */ - rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); - rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); - - port->rs485 = *rs485; - - /* - * Both serial8250_em485_init and serial8250_em485_destroy - * are idempotent - */ - if (rs485->flags & SER_RS485_ENABLED) { - int ret = serial8250_em485_init(up); - - if (ret) { - rs485->flags &= ~SER_RS485_ENABLED; - port->rs485.flags &= ~SER_RS485_ENABLED; - } - return ret; - } - - serial8250_em485_destroy(up); - - return 0; -} - static void omap_8250_unthrottle(struct uart_port *port) { struct omap8250_priv *priv = port->private_data; @@ -1187,7 +1157,7 @@ static int omap8250_probe(struct platform_device *pdev) up.port.shutdown = omap_8250_shutdown; up.port.throttle = omap_8250_throttle; up.port.unthrottle = omap_8250_unthrottle; - up.port.rs485_config = omap_8250_rs485_config; + up.port.rs485_config = serial8250_em485_config; up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); ret = of_alias_get_id(np, "serial"); diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 40efcea8c6e7..73244806d701 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -615,7 +615,7 @@ EXPORT_SYMBOL_GPL(serial8250_rpm_put); * * Return 0 - success, -errno - otherwise */ -int serial8250_em485_init(struct uart_8250_port *p) +static int serial8250_em485_init(struct uart_8250_port *p) { if (p->em485) return 0; @@ -636,7 +636,6 @@ int serial8250_em485_init(struct uart_8250_port *p) return 0; } -EXPORT_SYMBOL_GPL(serial8250_em485_init); /** * serial8250_em485_destroy() - put uart_8250_port into normal state @@ -664,6 +663,44 @@ void serial8250_em485_destroy(struct uart_8250_port *p) } EXPORT_SYMBOL_GPL(serial8250_em485_destroy); +/** + * serial8250_em485_config() - generic ->rs485_config() callback + * @port: uart port + * @rs485: rs485 settings + * + * Generic callback usable by 8250 uart drivers to activate rs485 settings + * if the uart is incapable of driving RTS as a Transmit Enable signal in + * hardware, relying on software emulation instead. + */ +int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + /* clamp the delays to [0, 100ms] */ + rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); + rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); + + port->rs485 = *rs485; + + /* + * Both serial8250_em485_init() and serial8250_em485_destroy() + * are idempotent. + */ + if (rs485->flags & SER_RS485_ENABLED) { + int ret = serial8250_em485_init(up); + + if (ret) { + rs485->flags &= ~SER_RS485_ENABLED; + port->rs485.flags &= ~SER_RS485_ENABLED; + } + return ret; + } + + serial8250_em485_destroy(up); + return 0; +} +EXPORT_SYMBOL_GPL(serial8250_em485_config); + /* * These two wrappers ensure that enable_runtime_pm_tx() can be called more than * once and disable_runtime_pm_tx() will still disable RPM because the fifo is From patchwork Fri Feb 28 13:31:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukas Wunner X-Patchwork-Id: 214238 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9AF8CC3F2D2 for ; Fri, 28 Feb 2020 13:42:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6EF54246AE for ; Fri, 28 Feb 2020 13:42:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726366AbgB1NmM (ORCPT ); Fri, 28 Feb 2020 08:42:12 -0500 Received: from mailout2.hostsharing.net ([83.223.78.233]:36799 "EHLO mailout2.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725796AbgB1NmM (ORCPT ); Fri, 28 Feb 2020 08:42:12 -0500 X-Greylist: delayed 318 seconds by postgrey-1.27 at vger.kernel.org; Fri, 28 Feb 2020 08:42:11 EST Received: from h08.hostsharing.net (h08.hostsharing.net [IPv6:2a01:37:1000::53df:5f1c:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout2.hostsharing.net (Postfix) with ESMTPS id EF6311008D087; Fri, 28 Feb 2020 14:42:09 +0100 (CET) Received: from localhost (unknown [87.130.102.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id AC59861249E8; Fri, 28 Feb 2020 14:42:09 +0100 (CET) X-Mailbox-Line: From bca638405550eaf92f0c6060b553b687f35885e0 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Lukas Wunner Date: Fri, 28 Feb 2020 14:31:05 +0100 Subject: [PATCH 5/8] serial: 8250: Deduplicate rs485 active_timer assignment To: Greg Kroah-Hartman , Jiri Slaby , "Nicolas Saenz Julienne" Cc: "Matwey V. Kornilov" , Heiko Schocher , Giulio Benetti , Uwe Kleine-Koenig , Stefan Wahren , Matthias Brugger , Martin Sperl , linux-serial@vger.kernel.org, linux-rpi-kernel@lists.infradead.org Sender: linux-serial-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org When rs485 transmission over an 8250 port stops, __stop_tx() assigns active_timer = NULL before calling __stop_tx_rs485(). That function in turn either assigns active_timer = stop_tx_timer and rearms the timer (in case a delay_rts_after_send needs to be observed) or directly calls __do_stop_tx_rs485(). Move the assignment active_timer = NULL to __stop_tx_rs485() into the branch which directly calls __do_stop_tx_rs485(), thereby avoiding a duplicate assignment and simplifying the code. Signed-off-by: Lukas Wunner Cc: Matwey V. Kornilov --- drivers/tty/serial/8250/8250_port.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index d281aea061d6..1a71625a0d43 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1498,6 +1498,7 @@ static void __stop_tx_rs485(struct uart_8250_port *p) p->port.rs485.delay_rts_after_send); } else { __do_stop_tx_rs485(p); + em485->active_timer = NULL; } } @@ -1522,8 +1523,6 @@ static inline void __stop_tx(struct uart_8250_port *p) if ((lsr & BOTH_EMPTY) != BOTH_EMPTY) return; - em485->active_timer = NULL; - __stop_tx_rs485(p); } __do_stop_tx(p); From patchwork Fri Feb 28 13:31:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukas Wunner X-Patchwork-Id: 214236 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BE89CC3F2CD for ; Fri, 28 Feb 2020 13:46:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 99F6F246A8 for ; Fri, 28 Feb 2020 13:46:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726525AbgB1NqL (ORCPT ); Fri, 28 Feb 2020 08:46:11 -0500 Received: from mailout2.hostsharing.net ([83.223.78.233]:49307 "EHLO mailout2.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726642AbgB1NqK (ORCPT ); Fri, 28 Feb 2020 08:46:10 -0500 Received: from h08.hostsharing.net (h08.hostsharing.net [IPv6:2a01:37:1000::53df:5f1c:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout2.hostsharing.net (Postfix) with ESMTPS id EE5AD1008CFF6; Fri, 28 Feb 2020 14:46:08 +0100 (CET) Received: from localhost (unknown [87.130.102.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id ACF8561249E8; Fri, 28 Feb 2020 14:46:08 +0100 (CET) X-Mailbox-Line: From 65edffce4670a19e598015c03cbe46f1ffd93e43 Mon Sep 17 00:00:00 2001 Message-Id: <65edffce4670a19e598015c03cbe46f1ffd93e43.1582895077.git.lukas@wunner.de> In-Reply-To: References: From: Lukas Wunner Date: Fri, 28 Feb 2020 14:31:08 +0100 Subject: [PATCH 8/8] serial: 8250: Support console on software emulated rs485 ports To: Greg Kroah-Hartman , Jiri Slaby , "Nicolas Saenz Julienne" Cc: "Matwey V. Kornilov" , Heiko Schocher , Giulio Benetti , Uwe Kleine-Koenig , Stefan Wahren , Matthias Brugger , Martin Sperl , linux-serial@vger.kernel.org, linux-rpi-kernel@lists.infradead.org Sender: linux-serial-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Commit e490c9144cfa ("tty: Add software emulated RS485 support for 8250") introduced support to use RTS as an rs485 Transmit Enable signal if data is transmitted through the tty layer. Console messages bypass the tty layer and instead are emitted via serial8250_console_write(). Amend that function to drive RTS as well, allowing for a console on rs485 ports. Note that serial8250_console_write() may be called concurrently to the tty layer accessing the port. The two protect their accesses with the port lock, but serial8250_console_write() may find RTS still being asserted by the tty layer, in which case it shouldn't be deasserted after the console message has been printed. Recognize such situations by checking the em485->tx_stopped flag. If a delay_rts_before_send or delay_rts_after_send has been specified, serial8250_console_write() busy-waits for its duration. Optimizations for those wait times are conceivable: E.g. if RTS is already asserted, we could check whether em485->start_tx_timer is active and wait only for the remaining expire time. But this would require calling into the hrtimer infrastructure, which involves acquiring locks and potentially reprogramming timer hardware. Such operations seem too risky in the context of console printout, which needs to work even when the kernel has crashed and emits a BUG splat. So I've gone with a simplistic solution which just always waits for the full delay. Signed-off-by: Lukas Wunner Cc: Matwey V. Kornilov --- drivers/tty/serial/8250/8250_port.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 8e8cca690bf9..0879bb8855cf 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -3204,6 +3204,7 @@ static void serial8250_console_restore(struct uart_8250_port *up) void serial8250_console_write(struct uart_8250_port *up, const char *s, unsigned int count) { + struct uart_8250_em485 *em485 = up->em485; struct uart_port *port = &up->port; unsigned long flags; unsigned int ier; @@ -3234,6 +3235,12 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, up->canary = 0; } + if (em485) { + if (em485->tx_stopped) + up->rs485_start_tx(up); + mdelay(port->rs485.delay_rts_before_send); + } + uart_console_write(port, s, count, serial8250_console_putchar); /* @@ -3243,6 +3250,12 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, wait_for_xmitr(up, BOTH_EMPTY); serial_port_out(port, UART_IER, ier); + if (em485) { + mdelay(port->rs485.delay_rts_before_send); + if (em485->tx_stopped) + up->rs485_stop_tx(up); + } + /* * The receive handling will happen properly because the * receive ready bit will still be set; it is not cleared