From nobody Sat Jun 20 08:25:30 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C09523B5846; Fri, 17 Apr 2026 10:24:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776421475; cv=none; b=e3/XGs3gNsSa6SJHVn9dAmUjxJQVaX6JMauB8bteukeWWoW+R2m/EVXewYT6rHNkcarSYhiJqcOmmSm0C+pXxXmKPovPvsdyERlc9vkeXBJRkObaF+fSK4TTo3ik/VPpxXgdmfafOMSevaUfnnKUzc8OX7uUDpyszmLxxCu2Wto= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776421475; c=relaxed/simple; bh=T0ZrDrOUya3oWk76FafMuetyc8sBId1vQHkE6ajtlN4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nyhQgoRQagcWvY7eRX2Q2v5Nmpa0+7/87aAt2OYDgUdWlQbSomDe3izGdIEBZcxaqEvp6md54E7mD7XOof7Ltpbv2G9RuuE2aCq/4yGuEIANOiDOi8TlINq985kIvaOs+9Bx0WTEwcgpZvf8ANWGfJwMIaYikSDxMcereBpiocU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=hWk9eHLt; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=OhgACVqF; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="hWk9eHLt"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="OhgACVqF" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1776421464; 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=ZYcmU/kilVLmia4EQ1s3pMoP9RDTiRvnL/dWf1YvggE=; b=hWk9eHLtP2IOq9lD8W6aoKEqZvEUvTXZPue2T9bhxRK6TJXsV3m+iZ/qSZWS/tVRUmW3eo C2fXzG6pXrx9/uGLuaJZPxE3zGw+ZSsa1fhkiwmk1U4iRJOK6hYKue/2DjYhj8PZfJizWw +uA6G+YP+WHFV0rcHACusUD+qvfLd7grSdsrv0yWoAeSWjP6lMCopy8sxDPHF1Udy87hoU l4iy971HdXoEPBBiTMYeOjyx6c4j9PvgIev1JrbDW1dI9SFlnxn0dX65DO0yCE6lecyuYN 5gN7EY0qogSDYzoSLyaRAwsrjzxb2N8sM4mgmA/82VvbLUcbwhsIO+H3Ux1FrQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1776421464; 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=ZYcmU/kilVLmia4EQ1s3pMoP9RDTiRvnL/dWf1YvggE=; b=OhgACVqFzgiMJWOdWk2luwKUifG72jplYcjQx5v42o99bi6ROrzC/TjKIkWm491yK55Wuc bqdYQmlTlONWSkDA== To: "Greg Kroah-Hartman" , Jiri Slaby Cc: linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org Subject: [PATCH tty v3 1/6] serial: core: Add dedicated uart_port field for console flow Date: Fri, 17 Apr 2026 12:30:14 +0206 Message-ID: <20260417102423.40984-2-john.ogness@linutronix.de> In-Reply-To: <20260417102423.40984-1-john.ogness@linutronix.de> References: <20260417102423.40984-1-john.ogness@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently the UPF_CONS_FLOW bit in the uart_port.flags field is used by serial console drivers to identify if a user has configured flow control on the console. This policy is most commonly setup during early boot, but can be changed at runtime. The bits in uart_port.flags are either hardware and driver properties that are initialized before usage or are properties that can be changed via the tty layer. The UPF_CONS_FLOW is an exception because it is a console-only policy that can change at runtime and its setting and usage have nothing to do with the tty layer. This actually causes a problem for its usage because uart_port.flags is synchronized by a related tty_port.mutex, but a console has no relation to a tty (other than sharing the port). This is probably why console flow control is not properly available for most serial drivers. And it is hindering being able to provide a proper implementation. Commit d01f4d181c92 ("serial: core: Privatize tty->hw_stopped") addressed a similar issue to deal with software assisted CTS flow state tracking. Add a new uart_port boolean field "cons_flow" to store the user configuration for console flow control. Add get/set wrappers to allow for adding more policies later and/or locking constraint validation. Mark UPF_CONS_FLOW as deprecated. Signed-off-by: John Ogness --- include/linux/serial_core.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 666430b478997..2327a364ded16 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -533,6 +533,7 @@ struct uart_port { #define UPF_HARD_FLOW ((__force upf_t) (UPF_AUTO_CTS | UPF_AUTO_RTS)) /* Port has hardware-assisted s/w flow control */ #define UPF_SOFT_FLOW ((__force upf_t) BIT_ULL(22)) +/* Deprecated: use uart_get_cons_flow()/uart_set_cons_flow() instead. */ #define UPF_CONS_FLOW ((__force upf_t) BIT_ULL(23)) #define UPF_SHARE_IRQ ((__force upf_t) BIT_ULL(24)) #define UPF_EXAR_EFR ((__force upf_t) BIT_ULL(25)) @@ -567,6 +568,7 @@ struct uart_port { #define UPSTAT_SYNC_FIFO ((__force upstat_t) (1 << 5)) =20 bool hw_stopped; /* sw-assisted CTS flow state */ + bool cons_flow; /* user specified console flow control */ unsigned int mctrl; /* current modem ctrl settings */ unsigned int frame_time; /* frame timing in ns */ unsigned int type; /* port type */ @@ -1163,6 +1165,16 @@ static inline bool uart_softcts_mode(struct uart_por= t *uport) return ((uport->status & mask) =3D=3D UPSTAT_CTS_ENABLE); } =20 +static inline void uart_set_cons_flow(struct uart_port *uport, bool on) +{ + uport->cons_flow =3D on; +} + +static inline bool uart_get_cons_flow(const struct uart_port *uport) +{ + return uport->cons_flow; +} + /* * The following are helper functions for the low level drivers. */ --=20 2.47.3 From nobody Sat Jun 20 08:25:30 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C028B3A6F15; Fri, 17 Apr 2026 10:24:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776421475; cv=none; b=EsgC7JmTZ2+G3WT7oNAT1ZyYdqAnsvkyQODdFQKUBu8fwmNegstLHh4zQZzWtzmSToDqe9M3WaobuGJ+IPJ01dGpElszoWK+e7RuIMXfEQCpk6onLX/bnxsh0tXvEe4ISq3gCUmTSThc1h2ZGcIi87cesVYU4JgVf14Jep7L6Yk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776421475; c=relaxed/simple; bh=pizWJrvuQ48cGLUkst8VVI51daUIasrR1V7+pSa+3gY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G63c3GQt0gmi4mRBDaNgrZsaNCksRyy9bXnPlnHmmjEIGvjaTzIwiDHiL93yl5esu2AaFjuocZmP6x+UblESU2EBVur3HOoY9WfLM5pnWKVLVQ2IZWGE9SNJ21HROFHuCGK5J+v3XUSQ6rc4g5Z6FG/4EWEUhICCyYUtqePjl24= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=1gqdm1+K; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=fLWGHfzh; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="1gqdm1+K"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="fLWGHfzh" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1776421464; 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=GMrkWwsRJJM8nf2vHkNwRnlQxiLbrNpUSyN/P1PXVuU=; b=1gqdm1+KQYmc0lEaKrij2m/6iN7QFvYv3SdOnrNnO3SQ1wiZPG7keCQDQS/EHzu7rYSJjx oJYIZYC7rWtTseO47NUH2BarudQdV3LxY/ouu2PE7mvadxv7BbskGH0GtJmDBgcQAELXRi HFIpXvcs+6U8+PB2JDCmJdgwf+vws3F84XiquOpqtoNZETiE2qZw87Acz6gOQtIDhxucuJ exTPPcqTcj9C8X2f1qI9P8rhoNnfCtu8i3OEose6YbeUN81e9u0xCAD4ncMqUDF31UIkJ8 bHZ9sdkkeNVnWaMdQ0GBHltkPl17ml2MK76xbsc2OckN1+qgjvTzclWhDJnuXw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1776421464; 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=GMrkWwsRJJM8nf2vHkNwRnlQxiLbrNpUSyN/P1PXVuU=; b=fLWGHfzhqiorZuAalaeL38ZW4UB8KT8DPAXlcCpsSmhp/s5uf+e10bZ3MXAqW5jtletG/x EYf5LmNSdHizcLDQ== To: "Greg Kroah-Hartman" , Jiri Slaby Cc: linux-kernel@vger.kernel.org, Krzysztof Kozlowski , Alim Akhtar , "David S. Miller" , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Andy Shevchenko , Thomas Fourier , Kees Cook , linux-serial@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, sparclinux@vger.kernel.org Subject: [PATCH tty v3 2/6] serial: Replace driver usage of UPF_CONS_FLOW Date: Fri, 17 Apr 2026 12:30:15 +0206 Message-ID: <20260417102423.40984-3-john.ogness@linutronix.de> In-Reply-To: <20260417102423.40984-1-john.ogness@linutronix.de> References: <20260417102423.40984-1-john.ogness@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Rather than using the UPF_CONS_FLOW bit of uart_port.flags to track the user configuration of console flow control, use the newly added uart_port.cons_flow (via its get/set functions). A coccinelle script was used to perform the search/replace. Note1: The sh-sci driver is blindly copying platform data configuration flags to uart_port.flags. Thus UPF_CONS_FLOW could get set. A follow-up commit will address this. Note2: Aside from sh-sci, the samsung_tty driver is also using UPF_CONS_FLOW as a platform data configuration flag. Signed-off-by: John Ogness --- drivers/tty/serial/8250/8250_port.c | 4 ++-- drivers/tty/serial/bcm63xx_uart.c | 2 +- drivers/tty/serial/omap-serial.c | 2 +- drivers/tty/serial/pch_uart.c | 2 +- drivers/tty/serial/pxa.c | 2 +- drivers/tty/serial/samsung_tty.c | 8 ++++---- drivers/tty/serial/serial_txx9.c | 4 ++-- drivers/tty/serial/sunsu.c | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/= 8250_port.c index af78cc02f38e7..c91b0fa7111a7 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1988,7 +1988,7 @@ static void wait_for_xmitr(struct uart_8250_port *up,= int bits) wait_for_lsr(up, bits); =20 /* Wait up to 1s for flow control if necessary */ - if (up->port.flags & UPF_CONS_FLOW) { + if (uart_get_cons_flow(&up->port)) { for (tmout =3D 1000000; tmout; tmout--) { unsigned int msr =3D serial_in(up, UART_MSR); up->msr_saved_flags |=3D msr & MSR_SAVE_FLAGS; @@ -3351,7 +3351,7 @@ void serial8250_console_write(struct uart_8250_port *= up, const char *s, * it regardless of the CTS state. Therefore, only use fifo * if we don't use control flow. */ - !(up->port.flags & UPF_CONS_FLOW); + !uart_get_cons_flow(&up->port); =20 if (likely(use_fifo)) serial8250_console_fifo_write(up, s, count); diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx= _uart.c index 51df9d2d8bfc5..be6777dfdc532 100644 --- a/drivers/tty/serial/bcm63xx_uart.c +++ b/drivers/tty/serial/bcm63xx_uart.c @@ -675,7 +675,7 @@ static void wait_for_xmitr(struct uart_port *port) } =20 /* Wait up to 1s for flow control if necessary */ - if (port->flags & UPF_CONS_FLOW) { + if (uart_get_cons_flow(port)) { tmout =3D 1000000; while (--tmout) { unsigned int val; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-ser= ial.c index 0b85f47ff19e0..a9879bc655745 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1092,7 +1092,7 @@ static void __maybe_unused wait_for_xmitr(struct uart= _omap_port *up) } while (!uart_lsr_tx_empty(status)); =20 /* Wait up to 1s for flow control if necessary */ - if (up->port.flags & UPF_CONS_FLOW) { + if (uart_get_cons_flow(&up->port)) { for (tmout =3D 1000000; tmout; tmout--) { unsigned int msr =3D serial_in(up, UART_MSR); =20 diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 6729d8e83c3c5..08cb9ff30506f 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1444,7 +1444,7 @@ static void wait_for_xmitr(struct eg20t_port *up, int= bits) } =20 /* Wait up to 1s for flow control if necessary */ - if (up->port.flags & UPF_CONS_FLOW) { + if (uart_get_cons_flow(&up->port)) { unsigned int tmout; for (tmout =3D 1000000; tmout; tmout--) { unsigned int msr =3D ioread8(up->membase + UART_MSR); diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index fea0255067ccd..80afa47f09880 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c @@ -573,7 +573,7 @@ static void wait_for_xmitr(struct uart_pxa_port *up) } while (!uart_lsr_tx_empty(status)); =20 /* Wait up to 1s for flow control if necessary */ - if (up->port.flags & UPF_CONS_FLOW) { + if (uart_get_cons_flow(&up->port)) { tmout =3D 1000000; while (--tmout && ((serial_in(up, UART_MSR) & UART_MSR_CTS) =3D=3D 0)) diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_= tty.c index e27806bf2cf3e..f9b0dbded1f43 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -319,7 +319,7 @@ static void s3c24xx_serial_stop_tx(struct uart_port *po= rt) ourport->tx_enabled =3D 0; ourport->tx_in_progress =3D 0; =20 - if (port->flags & UPF_CONS_FLOW) + if (uart_get_cons_flow(port)) s3c24xx_serial_rx_enable(port); =20 ourport->tx_mode =3D 0; @@ -493,7 +493,7 @@ static void s3c24xx_serial_start_tx(struct uart_port *p= ort) struct tty_port *tport =3D &port->state->port; =20 if (!ourport->tx_enabled) { - if (port->flags & UPF_CONS_FLOW) + if (uart_get_cons_flow(port)) s3c24xx_serial_rx_disable(port); =20 ourport->tx_enabled =3D 1; @@ -781,7 +781,7 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx= _uart_port *ourport) uerstat =3D rd_regl(port, S3C2410_UERSTAT); ch =3D rd_reg(port, S3C2410_URXH); =20 - if (port->flags & UPF_CONS_FLOW) { + if (uart_get_cons_flow(port)) { bool txe =3D s3c24xx_serial_txempty_nofifo(port); =20 if (ourport->rx_enabled) { @@ -1830,7 +1830,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_ua= rt_port *ourport, =20 if (cfg->uart_flags & UPF_CONS_FLOW) { dev_dbg(port->dev, "enabling flow control\n"); - port->flags |=3D UPF_CONS_FLOW; + uart_set_cons_flow(port, true); } =20 /* sort our the physical and virtual addresses for each UART */ diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_t= xx9.c index 436a559234dfe..103f03c1fe748 100644 --- a/drivers/tty/serial/serial_txx9.c +++ b/drivers/tty/serial/serial_txx9.c @@ -422,7 +422,7 @@ static void wait_for_xmitr(struct uart_port *up) udelay(1); =20 /* Wait up to 1s for flow control if necessary */ - if (up->flags & UPF_CONS_FLOW) { + if (uart_get_cons_flow(up)) { tmout =3D 1000000; while (--tmout && (sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS)) @@ -857,7 +857,7 @@ serial_txx9_console_write(struct console *co, const cha= r *s, unsigned int count) * Disable flow-control if enabled (and unnecessary) */ flcr =3D sio_in(up, TXX9_SIFLCR); - if (!(up->flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES)) + if (!uart_get_cons_flow(up) && (flcr & TXX9_SIFLCR_TES)) sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES); =20 uart_console_write(up, s, count, serial_txx9_console_putchar); diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index 6505a1930da9a..97019b5ec49e2 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -1245,7 +1245,7 @@ static void wait_for_xmitr(struct uart_sunsu_port *up) } while (!uart_lsr_tx_empty(status)); =20 /* Wait up to 1s for flow control if necessary */ - if (up->port.flags & UPF_CONS_FLOW) { + if (uart_get_cons_flow(&up->port)) { tmout =3D 1000000; while (--tmout && ((serial_in(up, UART_MSR) & UART_MSR_CTS) =3D=3D 0)) --=20 2.47.3 From nobody Sat Jun 20 08:25:30 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C07EE3B5843; Fri, 17 Apr 2026 10:24:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776421477; cv=none; b=hjFWkBPWazyY7lgCgXJLoow7Gth52RcdXtChmeiyfCaPFhpjPBXxyqUypr16HtSlz2JTCEvnbfT8UuOIKifveSs4grTpB+15BnykKM0pXz9eXED0+N4BHiEMS//vY+m6rt8vSCvNsbS+S1cPaEF/rViJ8OawngZeP4bZv5NllWk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776421477; c=relaxed/simple; bh=FBc35jOLYTmmpSOg0YwyTzm85KVf0EeX+eBqFKfNFyQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Y65e5m+BRNORgcbuiAaR95vu3lAA0NlYsFhJ15hV+6mlEAuUdBW8X3GfEUbRKdoa/t2+pZq+/4dRWWAXzwBArjpqhCCXYjZtQANpNYDNdiaT8lZQ1lZWVO/Yi82weYukNAcLH+VWDZwbfnGaiGmDAUkZGGh4qXOlXVeFTKO1P/o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=CSLX3ZQY; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=1VryJevP; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="CSLX3ZQY"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="1VryJevP" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1776421465; 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=hDCT9NWTKM7j7JKLQuSA1A60h0cYwjtf3icEnr1EbJQ=; b=CSLX3ZQYG8BTpJshW6vbPQLMsS5k1xpmEGzzaB599xNYL8DnxsckIfSlupQEjpKH/j2Hax kE0ufxG/luJAbLyizP+A/hsg4fr1JbzoeEC8O7Z1NJJRbbVceMRhVqp+Irr6Uxqqb+A5to +5KySzgSyd9YMNVaBvBMJZIXGwQfsB/qeDQt0G2BHhD0ttUHoyEfiol0uOy8sgzSbcBiql WXdB8CBUI86MRTdPl+muwcyVtnUjwLeRXluNE+WsTdOBg+nKJ2eKmrq14vcQIN/wlzqxw1 R/RMLAMpBUsOqDMW77oSvevhdbJ+hlkrO/Y878fGGoMMudsOurXYPyLKiHnGRw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1776421465; 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=hDCT9NWTKM7j7JKLQuSA1A60h0cYwjtf3icEnr1EbJQ=; b=1VryJevPlcEbgb3C1ubxKN98BPXvQfYaKxAIk5R6oqdOXQFyyV49hiMg0yYL/kBRJopq3y tbG/YFgGaXGS7xDQ== To: "Greg Kroah-Hartman" , Jiri Slaby Cc: linux-kernel@vger.kernel.org, Biju Das , Geert Uytterhoeven , Lad Prabhakar , Wolfram Sang , Thierry Bultel , linux-serial@vger.kernel.org Subject: [PATCH tty v3 3/6] serial: sh-sci: Avoid deprecated UPF_CONS_FLOW Date: Fri, 17 Apr 2026 12:30:16 +0206 Message-ID: <20260417102423.40984-4-john.ogness@linutronix.de> In-Reply-To: <20260417102423.40984-1-john.ogness@linutronix.de> References: <20260417102423.40984-1-john.ogness@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Avoid setting the uart_port.flags deprecated UPF_CONS_FLOW bit if it has been configured in the platform data. Use the new cons_flow wrappers instead. Signed-off-by: John Ogness --- drivers/tty/serial/sh-sci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 6c819b6b24258..07d272dc4e74a 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -3369,9 +3369,12 @@ static int sci_init_single(struct platform_device *d= ev, } =20 port->type =3D SCI_PUBLIC_PORT_ID(p->type); - port->flags =3D UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags; + port->flags =3D UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | + (p->flags & ~UPF_CONS_FLOW); port->fifosize =3D sci_port->params->fifosize; =20 + uart_set_cons_flow(port, p->flags & UPF_CONS_FLOW); + if (p->type =3D=3D PORT_SCI && !dev->dev.of_node) { if (sci_port->reg_size >=3D 0x20) port->regshift =3D 2; --=20 2.47.3 From nobody Sat Jun 20 08:25:30 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5911B3B4EA5; Fri, 17 Apr 2026 10:24:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776421478; cv=none; b=LYmJn5euu7uFpJokI9OKLbBn8g9mriui34363Uf2VrKGWIakjQhtc9uLfvMKYo+V5wSg9onIfvJXT83vrLNQwVbR02r+HYZztiq5DVoMQpkxNrS07aMb6kO+OufnS/mR3/R+LOwHkdk1Step4Zu6T4TkSW6YdOY0DXqRP14OeZI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776421478; c=relaxed/simple; bh=ZX5GXVmVzRtuIIlqSB17DJ71jWWOjYQmqPSXs+OjCX8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kpEnrqATj/E20PNghogjsNl0pZSMlngTkiDdI8+V+bUMwbeMWurbjK2bpYCujHENke9mYuNIb6LssXYF/rvJnmTVYrFfRIEYEl9bo3R6GJ1RPQgXoqiAyCwbqz1q1Cqso4JRZ05+SiCpOPFUeaTfc3VVe1SipaiZXot5aVH8C08= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=rtaHV79c; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=UWC10xuQ; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="rtaHV79c"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="UWC10xuQ" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1776421465; 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=3vaT9CcLP8jwFrjEqEJkhzbb3urNIEyX/8R45U6Cak4=; b=rtaHV79cjuxc1myWNuNCEPUNZ+Er1g8pEGqC7tfiMlzISom4fuYGkkJuHudtPTpCJvxUCF 3x4acLXvCrIkcQY2g9BC1fGkPpBNuxP1O7ZLfa9WtohwzlrcMETAsh+UzUG0bEX8t4GMHb cbHmOL7+UI/QNx0NVcDBP+za78KRAJJ83VjjW4xDD7AO4TjMhJDumbbMMAEEoH4R8iyMY5 zS9mBDjb3+dpBPDhEXg6mUG8HK4aJRZW7Ai9YV37J4x/ngDrjSxGa3kGfaeOLp6D380by4 65QDcsq9MLtzHPZkaRWS/7D0y/H2BDatI+GCJNYYcQgU+SySd0jHZSF909PYug== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1776421465; 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=3vaT9CcLP8jwFrjEqEJkhzbb3urNIEyX/8R45U6Cak4=; b=UWC10xuQviFzpTIEaJmWDGkqWYy4iZX18hD7/c9752LGoH8ixXDz3ybRp8NeseJ0iaL6Ta 1uabZkTzN5Dp9TAg== To: "Greg Kroah-Hartman" , Jiri Slaby Cc: linux-kernel@vger.kernel.org, =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Thomas Gleixner , Osama Abdelkader , Xin Zhao , Ingo Molnar , linux-serial@vger.kernel.org Subject: [PATCH tty v3 4/6] serial: 8250: Set cons_flow on port registration Date: Fri, 17 Apr 2026 12:30:17 +0206 Message-ID: <20260417102423.40984-5-john.ogness@linutronix.de> In-Reply-To: <20260417102423.40984-1-john.ogness@linutronix.de> References: <20260417102423.40984-1-john.ogness@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Since console flow control policy is no longer part of uart_port.flags, explicitly set the policy for the port. Signed-off-by: John Ogness --- drivers/tty/serial/8250/8250_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/= 8250_core.c index a428e88938eb7..32b894ab26768 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -746,6 +746,8 @@ int serial8250_register_8250_port(const struct uart_825= 0_port *up) uart->lsr_save_mask =3D up->lsr_save_mask; uart->dma =3D up->dma; =20 + uart_set_cons_flow(&uart->port, uart_get_cons_flow(&up->port)); + /* Take tx_loadsz from fifosize if it wasn't set separately */ if (uart->port.fifosize && !uart->tx_loadsz) uart->tx_loadsz =3D uart->port.fifosize; --=20 2.47.3 From nobody Sat Jun 20 08:25:30 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EFF1A3B6C0E; Fri, 17 Apr 2026 10:24:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776421479; cv=none; b=nk8KJCtDBQuy3Dwg5wDiO0XuTSB+4sJJWGZYNay1IqW8jqKFuqZCNJcC0u3qFDOfRgqR3KQyZWLn68WO3fGiCalW06UoalxGT1vTy0bnxllew4MSvMJp831v5RMmVt6aUsA7oCLmH0RZVwQmJQL5HB/nBGXSmE3OJ9DLL2U6zyA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776421479; c=relaxed/simple; bh=9yFLVKakLkkiOEqaGGZspsRBWbyRAs5bN2Z3/85Xq4g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YDwH0//CL5FTGRGb4IfkTHrA5b4dszgjJrHLkvsGcMMHEm0lkvWDbFViFfYMyA1C0YO3vcRblVleg6b07PIG/jbo6SBvqtjpcmJxyUgX0vWOAXdMe31v+oBJoMnQloT052ZDmi+oo0KFD15J60H7tEIL7cWwKYgaGFV9b8dcQ0Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=KROVrwwJ; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=kuyZDQ+0; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="KROVrwwJ"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="kuyZDQ+0" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1776421466; 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=7zGtVxAk0EWfLsuiGtoS8oZDRAse+qfp7+FW77t1bxg=; b=KROVrwwJ0SncT59ANLfYJh8L9CUEPqO898XYTbPi4HqdELVv5DukQqQs0+BvJpRd/AHYFh c7sSLOIhjXMs71+65+5out/mIdjNTgtufoZoW9TkUcFA0JeAIEJFs+t5Pje0DQfAydi31P 1Pu8FC86ipQjL2GoxzEIOtNVgkEp1n6BmJmzKs+nUe2s57DwZu+cdtQGvwaGaFIaou3Sir ggj3nLn/mOzjihDjx/FvutHopz7uSdNf3ZTkiLFFd3Gao+c4Q6BAUsB0TbmJO0cPtOx09f EFUhL3bgkFxK/Bnyv9o6IJcv8FSVdYGXb950bgR+IGWTM7L+AbOsmmrA4wkXHw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1776421466; 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=7zGtVxAk0EWfLsuiGtoS8oZDRAse+qfp7+FW77t1bxg=; b=kuyZDQ+0Pchv9kJ6E7SeLm9sVSlsib40KvYlACkiL/YukHxerfEz1O0khFdqQGqT+c1qDd BqGYl3w7f60zojBg== To: "Greg Kroah-Hartman" , Jiri Slaby Cc: linux-kernel@vger.kernel.org, =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Andy Shevchenko , linux-serial@vger.kernel.org Subject: [PATCH tty v3 5/6] serial: 8250: Check LSR timeout on console flow control Date: Fri, 17 Apr 2026 12:30:18 +0206 Message-ID: <20260417102423.40984-6-john.ogness@linutronix.de> In-Reply-To: <20260417102423.40984-1-john.ogness@linutronix.de> References: <20260417102423.40984-1-john.ogness@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" wait_for_xmitr() calls wait_for_lsr() to wait for the transmission registers to be empty. wait_for_lsr() can timeout after a reasonable amount of time. When console flow control is active, wait_for_xmitr() additionally polls CTS, waiting for the peer to signal that it is ready to receive more data. If hardware flow control is enabled (auto CTS) and the peer deasserts CTS, wait_for_lsr() will timeout. If additionally console flow control is active and while polling CTS the peer asserts CTS, the console will assume it can immediately transmit, even though the transmission registers may not be empty. This can lead to data loss. Avoid this problem by performing an extra wait_for_lsr() upon CTS assertion if wait_for_lsr() previously timed out. Signed-off-by: John Ogness --- drivers/tty/serial/8250/8250_port.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/= 8250_port.c index c91b0fa7111a7..b3247c55eebd5 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1984,16 +1984,20 @@ static bool wait_for_lsr(struct uart_8250_port *up,= int bits) static void wait_for_xmitr(struct uart_8250_port *up, int bits) { unsigned int tmout; + bool tx_ready; =20 - wait_for_lsr(up, bits); + tx_ready =3D wait_for_lsr(up, bits); =20 /* Wait up to 1s for flow control if necessary */ if (uart_get_cons_flow(&up->port)) { for (tmout =3D 1000000; tmout; tmout--) { unsigned int msr =3D serial_in(up, UART_MSR); up->msr_saved_flags |=3D msr & MSR_SAVE_FLAGS; - if (msr & UART_MSR_CTS) + if (msr & UART_MSR_CTS) { + if (!tx_ready) + wait_for_lsr(up, bits); break; + } udelay(1); touch_nmi_watchdog(); } --=20 2.47.3 From nobody Sat Jun 20 08:25:30 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F08393B7B96; Fri, 17 Apr 2026 10:24:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776421479; cv=none; b=AoVEkZbB0ne70gYndUnmoJV7ygjcoMc1WFsAB37l165wZ26U2Wp7RfPW/oRcnkrZG9BDjy343ebcD46Pg91pY8qi/dz71OuYThIF/BlT2ufrsyLciVt5TjbCkOgs8lI6a+tfy7g7Z2Kggr/gv6zD7aVDSIHvyiNBP0zEu8sNEfw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776421479; c=relaxed/simple; bh=oAaaXXWYBEecliZw7EGA9JF0bbO6a8+N7fXnfXjT0tw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WrXpLBh5gLkkd3rvu4RJvo9pwmUJ1cLoy6MiLPwe+DwzzvgsOgrKnh/Ts6fOvFTLg/aBYRb/sN7Os5ah1lG+j6jxGK0RvtQ1+8So6oG5R2VKyqevrW1RFADjv2cmniwK+EOKN3MoXnL4MCU5AAXzIHQSwVkgK+Yk+TSLgvP9ZI8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=cHwoLhKK; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=qfj4f4jH; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="cHwoLhKK"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="qfj4f4jH" From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1776421466; 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=6rBA1j0t+0AXQc6CwVomnArJ8ZNUDmgC5Q5lNAkjDRQ=; b=cHwoLhKKCV4nfndoFZ4bSYVq5AGVNMVrQfMAePdDJ4PcYs+U0aUB7bKC3Fdddr4SdBPESS KmPr9smu+UgsKTcG69hoJr04zxyzEu/dgTVhAoFJmEwkEFFtxvwI1+Ovzmh35tdtgeWJNb EUI79dMRWcneosyp3pSjO5oNNKZhnGnR0j5GFd4MRDy6wmpXKLJywjujdHR5ZoOOrdrHRa WPrHfDxvrCQlubHdqf5Vzd5KlagZxpEwdwIod38eJnYHwCiI8t7aJNMIqfyOX7Zm6JnGvC yacQduIuCaQ9mWNh1O9b3Q84zRfQ6DCuOF4Jb17cLOEKzaLObxPJWznMpcrHKA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1776421466; 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=6rBA1j0t+0AXQc6CwVomnArJ8ZNUDmgC5Q5lNAkjDRQ=; b=qfj4f4jH+nDrzNGOHhegdVtQIdjczB6fpRqv/J/PxGczW7CmNDeI9CXxkf+vzHTwOeVkf0 pVzZ9RMdk5IBhMCw== To: "Greg Kroah-Hartman" , Jiri Slaby Cc: linux-kernel@vger.kernel.org, =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Ingo Molnar , Osama Abdelkader , Andy Shevchenko , Krzysztof Kozlowski , Gerhard Engleder , Lukas Wunner , "Dr. David Alan Gilbert" , Joseph Tilahun , linux-serial@vger.kernel.org Subject: [PATCH tty v3 6/6] serial: 8250: Add support for console flow control Date: Fri, 17 Apr 2026 12:30:19 +0206 Message-ID: <20260417102423.40984-7-john.ogness@linutronix.de> In-Reply-To: <20260417102423.40984-1-john.ogness@linutronix.de> References: <20260417102423.40984-1-john.ogness@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The kernel documentation specifies that the console option 'r' can be used to enable hardware flow control for console writes. The 8250 driver does include code for hardware flow control on the console if cons_flow is set, but there is no code path that actually sets this. However, that is not the only issue. The problems are: 1. Specifying the console option 'r' does not lead to cons_flow being set. 2. Even if cons_flow would be set, serial8250_register_8250_port() clears it. 3. When the console option 'r' is specified, uart_set_options() attempts to initialize the port for CRTSCTS. However, afterwards it does not set the UPSTAT_CTS_ENABLE status bit and therefore on boot, uart_cts_enabled() is always false. This policy bit is important for console drivers as a criteria if they may poll CTS. 4. Even though uart_set_options() attempts to initialize the port for CRTSCTS, the 8250 set_termios() callback does not enable the RTS signal (TIOCM_RTS) and thus the hardware is not properly initialized for CTS polling. 5. Even if modem control was properly setup for CTS polling (TIOCM_RTS), uart_configure_port() clears TIOCM_RTS, thus breaking CTS polling. 6. wait_for_xmitr() and serial8250_console_write() use cons_flow to decide if CTS polling should occur. However, the condition should also include a check that it is not in RS485 mode and CRTSCTS is actually enabled in the hardware. Address all these issues as conservatively as possible by gating them behind checks focussed on the user specifying console hardware flow control support and the hardware being configured for CTS polling at the time of the write to the UART. Since checking the UPSTAT_CTS_ENABLE status bit is a part of the new condition gate, these changes also support runtime termios updates to disable/enable CRTSCTS. Signed-off-by: John Ogness --- drivers/tty/serial/8250/8250_core.c | 6 +++++- drivers/tty/serial/8250/8250_port.c | 13 +++++++++++-- drivers/tty/serial/serial_core.c | 21 ++++++++++++++++++++- include/linux/serial_core.h | 8 ++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/= 8250_core.c index 32b894ab26768..a19646e24d883 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -693,6 +693,7 @@ static void serial_8250_overrun_backoff_work(struct wor= k_struct *work) int serial8250_register_8250_port(const struct uart_8250_port *up) { struct uart_8250_port *uart; + bool cons_flow; int ret; =20 if (up->port.uartclk =3D=3D 0) @@ -716,6 +717,9 @@ int serial8250_register_8250_port(const struct uart_825= 0_port *up) if (uart->port.type =3D=3D PORT_8250_CIR) return -ENODEV; =20 + /* Preserve specified console flow control. */ + cons_flow =3D uart_get_cons_flow(&uart->port); + if (uart->port.dev) uart_remove_one_port(&serial8250_reg, &uart->port); =20 @@ -746,7 +750,7 @@ int serial8250_register_8250_port(const struct uart_825= 0_port *up) uart->lsr_save_mask =3D up->lsr_save_mask; uart->dma =3D up->dma; =20 - uart_set_cons_flow(&uart->port, uart_get_cons_flow(&up->port)); + uart_set_cons_flow(&uart->port, uart_get_cons_flow(&up->port) | cons_flow= ); =20 /* Take tx_loadsz from fifosize if it wasn't set separately */ if (uart->port.fifosize && !uart->tx_loadsz) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/= 8250_port.c index b3247c55eebd5..f585145a6211a 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1989,7 +1989,7 @@ static void wait_for_xmitr(struct uart_8250_port *up,= int bits) tx_ready =3D wait_for_lsr(up, bits); =20 /* Wait up to 1s for flow control if necessary */ - if (uart_get_cons_flow(&up->port)) { + if (uart_console_hwflow_active(&up->port)) { for (tmout =3D 1000000; tmout; tmout--) { unsigned int msr =3D serial_in(up, UART_MSR); up->msr_saved_flags |=3D msr & MSR_SAVE_FLAGS; @@ -2786,6 +2786,12 @@ serial8250_do_set_termios(struct uart_port *port, st= ruct ktermios *termios, serial8250_set_efr(port, termios); serial8250_set_divisor(port, baud, quot, frac); serial8250_set_fcr(port, termios); + /* Consoles manually poll CTS for hardware flow control. */ + if (uart_console(port) && + !(port->rs485.flags & SER_RS485_ENABLED) + && termios->c_cflag & CRTSCTS) { + port->mctrl |=3D TIOCM_RTS; + } serial8250_set_mctrl(port, port->mctrl); } =20 @@ -3355,7 +3361,7 @@ void serial8250_console_write(struct uart_8250_port *= up, const char *s, * it regardless of the CTS state. Therefore, only use fifo * if we don't use control flow. */ - !uart_get_cons_flow(&up->port); + !uart_console_hwflow_active(&up->port); =20 if (likely(use_fifo)) serial8250_console_fifo_write(up, s, count); @@ -3425,6 +3431,9 @@ int serial8250_console_setup(struct uart_port *port, = char *options, bool probe) if (ret) return ret; =20 + /* Track user-specified console flow control. */ + uart_set_cons_flow(port, flow =3D=3D 'r'); + if (port->dev) pm_runtime_get_sync(port->dev); =20 diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_c= ore.c index 89cebdd278410..840336f95c5f6 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2235,6 +2235,18 @@ uart_set_options(struct uart_port *port, struct cons= ole *co, port->mctrl |=3D TIOCM_DTR; =20 port->ops->set_termios(port, &termios, &dummy); + + /* + * If console hardware flow control was specified and is supported, + * the related policy UPSTAT_CTS_ENABLE must be set to allow console + * drivers to identify if CTS should be used for polling. + */ + if (flow =3D=3D 'r' && (termios.c_cflag & CRTSCTS)) { + /* Synchronize @status RMW update against the console. */ + guard(uart_port_lock_irqsave)(port); + port->status |=3D UPSTAT_CTS_ENABLE; + } + /* * Allow the setting of the UART parameters with a NULL console * too: @@ -2541,7 +2553,14 @@ uart_configure_port(struct uart_driver *drv, struct = uart_state *state, * We probably don't need a spinlock around this, but */ scoped_guard(uart_port_lock_irqsave, port) { - port->mctrl &=3D TIOCM_DTR; + unsigned int mask =3D TIOCM_DTR; + + /* Console hardware flow control polls CTS. */ + if (uart_console_hwflow_active(port)) + mask |=3D TIOCM_RTS; + + port->mctrl &=3D mask; + if (!(port->rs485.flags & SER_RS485_ENABLED)) port->ops->set_mctrl(port, port->mctrl); } diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 2327a364ded16..ff1145e86088b 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -1175,6 +1175,14 @@ static inline bool uart_get_cons_flow(const struct u= art_port *uport) return uport->cons_flow; } =20 +static inline bool uart_console_hwflow_active(struct uart_port *uport) +{ + return uart_console(uport) && + !(uport->rs485.flags & SER_RS485_ENABLED) && + uart_get_cons_flow(uport) && + uart_cts_enabled(uport); +} + /* * The following are helper functions for the low level drivers. */ --=20 2.47.3