From patchwork Fri Oct 25 10:57:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 13850549 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CC001D0C602 for ; Fri, 25 Oct 2024 11:33:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=4tycoxXMZP2qAEgVyWrz9W3wqW1U06QeuS7WtgHLseQ=; b=fyGpiXAVg1nu6coYQLNxJJm5W0 9/pwMEwU+zrBOaAJb0S9UT6MtKRBwEanyYSh3+NnyGq8y5q70Cx7X6tgwUyOSb9TOg3yM8imMYnbU SV4VzSUIrZEoOIEMCfv1PHmcXB8qV4DnlLGM6DwmDMcOQD+jBPWeXYxe1uZvav9LhuoCah49pzmsn g3pt0yiS0qOO/lRBXm1GiLA+GHf2so/lZH7LX6cu0s/HqHl3tluUb24CJ5US+uCo/KaUKg/+8C+Q3 xIvXfthXwnJKAT/dVDj6lK1M3IE1jpErZkhwuo+dJ6pWsx5WE4g49ACL7ww6+9UTP1faRyA9/Esg+ 6nckTsCw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1t4IZL-00000003WTI-3eib; Fri, 25 Oct 2024 11:33:27 +0000 Received: from galois.linutronix.de ([2a0a:51c0:0:12e:550::1]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1t4I0c-00000003Qzc-0N54; Fri, 25 Oct 2024 10:57:37 +0000 From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1729853852; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4tycoxXMZP2qAEgVyWrz9W3wqW1U06QeuS7WtgHLseQ=; b=slrwLbOGv/F1VYgap0ous/jqd4LPXjiFrtb3BPBmMYFkSuDjBh2mFPfkGJq8sK8x4nmjx0 xFB9z/WVqzVLbBRThpuzYmmOBp608Huy6bcjs7jh81z2Sl3VXw73z12YkTfTQWR6dL4z8n OQv9j8/0lhf9zs3KKpUwRpaYQJ4L0GUpPkDlpClY7+Q8CF4hYfLQuR4hRjfesw/EU5Toau C3NM22ABiGRgs7ijV/HSzw8SUAn7RJ/2Y9vcFsEnpboXYztmNXVccx6aNISD/9bGUpvNy3 sdt6SL5ml+TsDGGlv8HVFHQUeoI8VUf0jQA6Ki5j1mAIAzbgFTsRAKoLGzaF+g== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1729853852; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4tycoxXMZP2qAEgVyWrz9W3wqW1U06QeuS7WtgHLseQ=; b=6Ai98LwU1yRYVVR8VovVPP2dQVZbVhhWcHFPpUNgmaYbyJCHM0FfZyU778L/xjXWeBhio3 y13LfZg0w+N6aLAA== To: Greg Kroah-Hartman Cc: Jiri Slaby , Petr Mladek , Sergey Senozhatsky , Steven Rostedt , Thomas Gleixner , Esben Haabendal , linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, Florian Fainelli , Broadcom internal kernel review list , Ray Jui , Scott Branden , Andy Shevchenko , "Paul E. McKenney" , Arnd Bergmann , Stefan Wahren , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Kevin Hilman , Markus Schneider-Pargmann , Ronald Wahl , Udit Kumar , Griffin Kroah-Hartman , Rengarajan S , Lino Sanfilippo , Serge Semin , linux-rpi-kernel@lists.infradead.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH tty-next v3 4/6] serial: 8250: Specify console context for rs485_start/stop_tx Date: Fri, 25 Oct 2024 13:03:26 +0206 Message-Id: <20241025105728.602310-5-john.ogness@linutronix.de> In-Reply-To: <20241025105728.602310-1-john.ogness@linutronix.de> References: <20241025105728.602310-1-john.ogness@linutronix.de> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241025_035734_460488_2BD0119C X-CRM114-Status: GOOD ( 19.37 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org For RS485 mode, if SER_RS485_RX_DURING_TX is not available, the console write callback needs to enable/disable TX. It does this by calling the rs485_start/stop_tx() callbacks. However, these callbacks will disable/enable interrupts, which is a problem for console write, as it must be responsible for disabling/enabling interrupts. Add an argument @in_con to the rs485_start/stop_tx() callbacks to specify if they are being called from console write. If so, the callbacks will not handle interrupt disabling/enabling. For all call sites other than console write, there is no functional change. Signed-off-by: John Ogness --- drivers/tty/serial/8250/8250.h | 4 +-- drivers/tty/serial/8250/8250_bcm2835aux.c | 4 +-- drivers/tty/serial/8250/8250_omap.c | 2 +- drivers/tty/serial/8250/8250_port.c | 34 +++++++++++++++-------- include/linux/serial_8250.h | 4 +-- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index e5310c65cf52..0d8717be0df7 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -231,8 +231,8 @@ void serial8250_rpm_put_tx(struct uart_8250_port *p); int serial8250_em485_config(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485); -void serial8250_em485_start_tx(struct uart_8250_port *p); -void serial8250_em485_stop_tx(struct uart_8250_port *p); +void serial8250_em485_start_tx(struct uart_8250_port *p, bool in_con); +void serial8250_em485_stop_tx(struct uart_8250_port *p, bool in_con); void serial8250_em485_destroy(struct uart_8250_port *p); extern struct serial_rs485 serial8250_em485_supported; diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index fdb53b54e99e..c9a106a86b56 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -46,7 +46,7 @@ struct bcm2835aux_data { u32 cntl; }; -static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up) +static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up, bool in_con) { if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) { struct bcm2835aux_data *data = dev_get_drvdata(up->port.dev); @@ -65,7 +65,7 @@ static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up) serial8250_out_MCR(up, UART_MCR_RTS); } -static void bcm2835aux_rs485_stop_tx(struct uart_8250_port *up) +static void bcm2835aux_rs485_stop_tx(struct uart_8250_port *up, bool in_con) { if (up->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) serial8250_out_MCR(up, 0); diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index b3be0fb184a3..fcbed7e98231 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -365,7 +365,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up) if (up->port.rs485.flags & SER_RS485_ENABLED && up->port.rs485_config == serial8250_em485_config) - serial8250_em485_stop_tx(up); + serial8250_em485_stop_tx(up, false); } /* diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 09ac521d232a..7c50387194ad 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -558,7 +558,7 @@ static int serial8250_em485_init(struct uart_8250_port *p) deassert_rts: if (p->em485->tx_stopped) - p->rs485_stop_tx(p); + p->rs485_stop_tx(p, false); return 0; } @@ -1398,10 +1398,11 @@ static void serial8250_stop_rx(struct uart_port *port) /** * serial8250_em485_stop_tx() - generic ->rs485_stop_tx() callback * @p: uart 8250 port + * @in_con: true if called from console write, otherwise false * * Generic callback usable by 8250 uart drivers to stop rs485 transmission. */ -void serial8250_em485_stop_tx(struct uart_8250_port *p) +void serial8250_em485_stop_tx(struct uart_8250_port *p, bool in_con) { unsigned char mcr = serial8250_in_MCR(p); @@ -1419,7 +1420,9 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p) if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) { serial8250_clear_and_reinit_fifos(p); - __serial8250_start_rx_int(p); + /* In console context, caller handles interrupt enabling. */ + if (!in_con) + __serial8250_start_rx_int(p); } } EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx); @@ -1434,7 +1437,7 @@ static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t) serial8250_rpm_get(p); uart_port_lock_irqsave(&p->port, &flags); if (em485->active_timer == &em485->stop_tx_timer) { - p->rs485_stop_tx(p); + p->rs485_stop_tx(p, false); em485->active_timer = NULL; em485->tx_stopped = true; } @@ -1466,7 +1469,7 @@ static void __stop_tx_rs485(struct uart_8250_port *p, u64 stop_delay) em485->active_timer = &em485->stop_tx_timer; hrtimer_start(&em485->stop_tx_timer, ns_to_ktime(stop_delay), HRTIMER_MODE_REL); } else { - p->rs485_stop_tx(p); + p->rs485_stop_tx(p, false); em485->active_timer = NULL; em485->tx_stopped = true; } @@ -1555,6 +1558,7 @@ static inline void __start_tx(struct uart_port *port) /** * serial8250_em485_start_tx() - generic ->rs485_start_tx() callback * @up: uart 8250 port + * @in_con: true if called from console write, otherwise false * * Generic callback usable by 8250 uart drivers to start rs485 transmission. * Assumes that setting the RTS bit in the MCR register means RTS is high. @@ -1562,12 +1566,20 @@ static inline void __start_tx(struct uart_port *port) * stoppable by disabling the UART_IER_RDI interrupt. (Some chips set the * UART_LSR_DR bit even when UART_IER_RDI is disabled, foiling this approach.) */ -void serial8250_em485_start_tx(struct uart_8250_port *up) +void serial8250_em485_start_tx(struct uart_8250_port *up, bool in_con) { unsigned char mcr = serial8250_in_MCR(up); - if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) - serial8250_stop_rx(&up->port); + if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) { + /* + * In console context, caller handles interrupt disabling. So + * only LSR_DR masking is needed. + */ + if (in_con) + __serial8250_stop_rx_mask_dr(&up->port); + else + serial8250_stop_rx(&up->port); + } if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) mcr |= UART_MCR_RTS; @@ -1600,7 +1612,7 @@ static bool start_tx_rs485(struct uart_port *port) if (em485->tx_stopped) { em485->tx_stopped = false; - up->rs485_start_tx(up); + up->rs485_start_tx(up, false); if (up->port.rs485.delay_rts_before_send > 0) { em485->active_timer = &em485->start_tx_timer; @@ -3402,7 +3414,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, if (em485) { if (em485->tx_stopped) - up->rs485_start_tx(up); + up->rs485_start_tx(up, true); mdelay(port->rs485.delay_rts_before_send); } @@ -3440,7 +3452,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, if (em485) { mdelay(port->rs485.delay_rts_after_send); if (em485->tx_stopped) - up->rs485_stop_tx(up); + up->rs485_stop_tx(up, true); } serial_port_out(port, UART_IER, ier); diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index e0717c8393d7..c25c026d173d 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -161,8 +161,8 @@ struct uart_8250_port { void (*dl_write)(struct uart_8250_port *up, u32 value); struct uart_8250_em485 *em485; - void (*rs485_start_tx)(struct uart_8250_port *); - void (*rs485_stop_tx)(struct uart_8250_port *); + void (*rs485_start_tx)(struct uart_8250_port *up, bool in_con); + void (*rs485_stop_tx)(struct uart_8250_port *up, bool in_con); /* Serial port overrun backoff */ struct delayed_work overrun_backoff;