* Re: [PATCH v7 5/6] ARM: dts: zte: Add D-Link DWR-932M support
From: Linus Walleij @ 2026-05-05 9:53 UTC (permalink / raw)
To: Stefan Dösinger
Cc: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Drew Fustini,
Greg Kroah-Hartman, Jiri Slaby, linux-doc, linux-kernel,
linux-arm-kernel, devicetree, soc, linux-serial
In-Reply-To: <20260429-send-v7-5-b432e00d2db8@gmail.com>
On Wed, Apr 29, 2026 at 9:14 PM Stefan Dösinger
<stefandoesinger@gmail.com> wrote:
> This adds base DT definition for zx297520v3 and one board that consumes it.
>
> The stock kernel does not use the armv7 timer, but it seems to work
> fine. The board has other board-specific timers that would need a driver
> and I see no reason to bother with them since the arm standard timer
> works.
>
> The caveat is the non-standard GIC setup needed to handle the timer's
> level-low PPI. This is the responsibility of the boot loader and
> documented in Documentation/arch/arm/zte/zx297520v3.rst.
>
> Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v7 6/6] ARM: zte: defconfig: Add a zx29 defconfig file
From: Linus Walleij @ 2026-05-05 9:54 UTC (permalink / raw)
To: Stefan Dösinger
Cc: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Drew Fustini,
Greg Kroah-Hartman, Jiri Slaby, linux-doc, linux-kernel,
linux-arm-kernel, devicetree, soc, linux-serial
In-Reply-To: <20260429-send-v7-6-b432e00d2db8@gmail.com>
On Wed, Apr 29, 2026 at 9:14 PM Stefan Dösinger
<stefandoesinger@gmail.com> wrote:
> This enables existing drivers for hardware that is present on this board
> even if it is not present in the DT yet.
>
> Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
I'm in favor of this, mainly because multi_v7 is pretty useless
for this board, it is absolutely too big to boot on the machine,
the board is odd and need some ARM64 stuff.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH net-next 2/3] ppp: unify two channel structs
From: Paolo Abeni @ 2026-05-05 11:16 UTC (permalink / raw)
To: Qingfang Deng, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Jiri Kosina, David Sterba, Greg Kroah-Hartman,
Jiri Slaby, Mitchell Blank Jr, Chas Williams, Simon Horman,
James Chapman, Kees Cook, Sebastian Andrzej Siewior, Taegu Ha,
Guillaume Nault, Eric Woudstra, Arnd Bergmann, Dawid Osuchowski,
Breno Leitao, linux-ppp, netdev, linux-kernel, linux-serial,
linux-atm-general
In-Reply-To: <20260430090532.244758-2-qingfang.deng@linux.dev>
On 4/30/26 11:05 AM, Qingfang Deng wrote:
> Historically, PPP maintained two separate structures for a channel:
> 'struct channel' was internal to ppp_generic.c, while 'struct ppp_channel'
> was the public interface that drivers were required to embed. This
> duplication was redundant and forced drivers to manage the lifecycle of
> the public structure.
>
> Unify these two structures into a single 'struct ppp_channel', which is
> now internal to ppp_generic.c. Drivers now use a 'ppp_channel_conf'
> structure to specify registration parameters and receive an opaque
> pointer to the allocated channel.
>
> Key changes:
> - ppp_register_channel() and ppp_register_net_channel() now return
> a 'struct ppp_channel *' instead of taking a pointer to a driver-
> embedded structure.
> - 'struct ppp_channel_ops' methods now take the driver's 'private'
> pointer directly as their first argument, simplifying driver logic.
> - ppp_unregister_channel() now takes the opaque pointer.
> - Multilink-specific fields are unified and handled via the new
> configuration structure.
>
> This cleanup simplifies the driver interface and makes the channel
> lifecycle management more robust by centralizing allocation in the PPP
> generic layer.
>
> Assisted-by: Gemini:gemini-3-flash
> Signed-off-by: Qingfang Deng <qingfang.deng@linux.dev>
> ---
> drivers/net/ppp/ppp_async.c | 51 +++++-----
> drivers/net/ppp/ppp_generic.c | 161 +++++++++++++++----------------
> drivers/net/ppp/ppp_synctty.c | 51 +++++-----
> drivers/net/ppp/pppoe.c | 34 ++++---
> drivers/net/ppp/pppox.c | 4 +-
> drivers/net/ppp/pptp.c | 40 ++++----
> drivers/tty/ipwireless/network.c | 30 +++---
> include/linux/if_pppox.h | 2 +-
> include/linux/ppp_channel.h | 49 ++++++----
> net/atm/pppoatm.c | 61 ++++++------
> net/l2tp/l2tp_ppp.c | 34 ++++---
> 11 files changed, 271 insertions(+), 246 deletions(-)
This patch is IMHO a bit too big and should be split. Also this kind of
refactor looks very invasive and potentially regression prone. I think
it should include a signficant self-test coverage increase.
> @@ -391,9 +396,9 @@ ppp_async_init(void)
> * The following routines provide the PPP channel interface.
> */
> static int
> -ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
> +ppp_async_ioctl(void *private, unsigned int cmd, unsigned long arg)
> {
> - struct asyncppp *ap = chan->private;
> + struct asyncppp *ap = private;
> void __user *argp = (void __user *)arg;
> int __user *p = argp;
> int err, val;
Minor nit: reverse christmas tree above
> @@ -2985,16 +2983,13 @@ char *ppp_dev_name(struct ppp_channel *chan)
> * This must be called in process context.
> */
> void
> -ppp_unregister_channel(struct ppp_channel *chan)
> +ppp_unregister_channel(struct ppp_channel *pch)
> {
> - struct channel *pch = chan->ppp;
> struct ppp_net *pn;
>
> if (!pch)
> return; /* should never happen */
>
> - chan->ppp = NULL;
> -
Sashiko says:
Could this specific ordering introduce a race condition that might lead
to a use-after-free?
If userspace has a file descriptor attached to this channel, it can
concurrently invoke the PPPIOCCONNECT ioctl. Because
ppp_disconnect_channel()
clears pch->ppp and removes the channel from its current unit before
pch->file.dead is set to 1, the concurrent ioctl could observe
pch->file.dead == 0.
This would allow ppp_connect_channel() to successfully attach the dying
channel to a new PPP unit. Once ppp_unregister_channel() completes and
frees the channel, the new PPP unit would retain a pointer to the freed
memory in its channels list, which might be accessed during a later
packet transmission via ppp_push().
> @@ -215,7 +210,8 @@ static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
> !memcmp(skb->data, &pppllc[LLC_LEN],
> sizeof(pppllc) - LLC_LEN)) {
> pvcc->encaps = e_vc;
> - pvcc->chan.mtu += LLC_LEN;
> + ppp_channel_update_mtu(pvcc->chan,
> + atmvcc->qos.txtp.max_sdu - PPP_HDRLEN);
Does the above introduce a functional change? At very least some comment
needed. Also possibly better move the update_mtu wrapper to a pre-req patch.
> @@ -221,7 +221,7 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int
> struct pppox_sock *po;
>
> po = pppox_sk(sk);
> - ppp_input(&po->chan, skb);
> + ppp_input(po->chan, skb);
Sashiko says:
Does decoupling the channel lifetime from the driver structure introduce
a use-after-free when receiving packets?
Previously, the struct ppp_channel was embedded in struct pppox_sock,
meaning its lifecycle was safely tied to the socket's refcount. Now that
po->chan is dynamically allocated and freed during pppox_unbind_sock()
via ppp_unregister_channel(), it seems possible for pppol2tp_recv() to
access freed memory.
Since pppol2tp_recv() runs locklessly in softirq context while holding
only rcu_read_lock() and a socket reference, can it observe the
PPPOX_BOUND state and dereference po->chan just after it was freed on
another CPU?
/P
^ permalink raw reply
* Re: [PATCH] serial: 8250_dw: Clean up register macros and error handling
From: Artem Shimko @ 2026-05-05 12:15 UTC (permalink / raw)
To: Andy Shevchenko
Cc: sashal, miquel.raynal, phil.edworthy, Ilpo Järvinen,
Greg Kroah-Hartman, Jiri Slaby, linux-kernel, linux-serial
In-Reply-To: <ae8J6uqgOarcduas@ashevche-desk.local>
HI Andy,
On Mon, Apr 27, 2026 at 10:02 AM Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
> https://lore.kernel.org/linux-serial/20260424-ultrarisc-serial-v4-0-1765a0b4c4a0@ultrarisc.com/
Yes, now I see...
Thank you for review =)
Regards,
Artem
^ permalink raw reply
* Re: [PATCH 1/3] tty: move remaining serial drivers into the serial/ directory
From: Crescent Hsieh @ 2026-05-06 3:15 UTC (permalink / raw)
To: Jiri Slaby
Cc: Ethan Nelson-Moore, linux-serial, Greg Kroah-Hartman,
Ilpo Järvinen, Andy Shevchenko,
Ray Chen (陳松昱), linux-m68k,
Geert Uytterhoeven
In-Reply-To: <ed6dce34-2207-4403-bbcf-080db2614241@kernel.org>
On Tue, May 05, 2026 at 07:59:29AM +0200, Jiri Slaby wrote:
> On 05. 05. 26, 3:20, Ethan Nelson-Moore wrote:
> > A few TTY drivers are outside the serial/ directory despite being for
> > serial devices.
>
> Yes, but serial/ (historically) contains drivers using serial_core. tty/
> contains drivers using tty_driver (which all of three unfortunately do).
>
> There was a patchset from Crescent Hsieh (Moxa) to convert mxser [1].
Yes, I have been working on converting mxser.c into an 8250-based serial
driver for some time, and it is still in progress.
> I am not sure even about users of Moxa Intellio. I think I prompted long
> time ago. Oh yes, Ray Chen (CCed) from Moxa wrote me back in 2021:
> === 8< ===
> For the Intellio cards, we phased them out in 2017.
> You may find the discontinuance notification as attached.
> We will keep the software support for 5 years, to 2023.
> === 8< ===
>
> I believe we can mark it as BROKEN to let someone convert it to serial_core.
> Or drop it for good already.
As for Moxa Intellio (moxa.c), I have confirmed internally that both the
hardware and software support have already been phased out.
Therefore, it would be reasonable to drop it at this point. I can help
with preparing a removal patch if this is the preferred direction.
---
Sincerely,
Crescent Hsieh
^ permalink raw reply
* [PATCH v1] serial: qcom_geni: fix kfifo underflow when flush precedes DMA completion IRQ
From: Viken Dadhaniya @ 2026-05-06 4:45 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Bartosz Golaszewski
Cc: linux-arm-msm, linux-kernel, linux-serial, stable,
Viken Dadhaniya
When uart_flush_buffer() runs before the DMA completion IRQ is delivered,
the following race can occur (all steps serialized by uart_port_lock):
1. DMA starts: tx_remaining = N, kfifo contains N bytes
2. DMA completes in hardware; IRQ is pending but not yet delivered
3. uart_flush_buffer() acquires the port lock and calls kfifo_reset(),
making kfifo_len() = 0 while tx_remaining remains N
4. uart_flush_buffer() releases the port lock
5. DMA IRQ fires; handle_tx_dma() acquires the port lock and calls
uart_xmit_advance(uport, tx_remaining) on an empty kfifo
uart_xmit_advance() increments kfifo->out by tx_remaining. Since
kfifo_reset() already set both in and out to 0, out wraps past in,
causing kfifo_len() to return UART_XMIT_SIZE - tx_remaining. The next
start_tx_dma() call then submits a DMA transfer of stale buffer data.
Fix this by snapshotting kfifo_len() at the start of handle_tx_dma()
and skipping uart_xmit_advance() when fifo_len < tx_remaining, which
indicates the kfifo was reset by a preceding flush.
Fixes: 2aaa43c70778 ("tty: serial: qcom-geni-serial: add support for serial engine DMA")
Cc: stable@vger.kernel.org
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
---
drivers/tty/serial/qcom_geni_serial.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index b365dd5da3cb..3c1be7b21290 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -1031,8 +1031,20 @@ static void qcom_geni_serial_handle_tx_dma(struct uart_port *uport)
{
struct qcom_geni_serial_port *port = to_dev_port(uport);
struct tty_port *tport = &uport->state->port;
+ unsigned int fifo_len = kfifo_len(&tport->xmit_fifo);
+
+ /*
+ * Only advance the kfifo if it still contains the bytes that were
+ * transferred. uart_flush_buffer() may have run before this IRQ
+ * fired: it calls kfifo_reset() under the port lock, making
+ * fifo_len = 0 while tx_remaining remains non-zero. Calling
+ * uart_xmit_advance() in that case would underflow kfifo->out past
+ * kfifo->in, making kfifo_len() wrap to UART_XMIT_SIZE - tx_remaining
+ * and triggering a spurious large DMA transfer of stale data.
+ */
+ if (fifo_len >= port->tx_remaining)
+ uart_xmit_advance(uport, port->tx_remaining);
- uart_xmit_advance(uport, port->tx_remaining);
geni_se_tx_dma_unprep(&port->se, port->tx_dma_addr, port->tx_remaining);
port->tx_dma_addr = 0;
port->tx_remaining = 0;
---
base-commit: 4cd074ae20bbcc293bbbce9163abe99d68ae6ae0
change-id: 20260506-serial-dma-stale-tx-buf-f53db336a13a
Best regards,
--
Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
^ permalink raw reply related
* Re: [PATCH v1] serial: qcom_geni: fix kfifo underflow when flush precedes DMA completion IRQ
From: Bartosz Golaszewski @ 2026-05-06 8:30 UTC (permalink / raw)
To: Viken Dadhaniya
Cc: linux-arm-msm, linux-kernel, linux-serial, stable,
Greg Kroah-Hartman, Jiri Slaby, Bartosz Golaszewski
In-Reply-To: <20260506-serial-dma-stale-tx-buf-v1-1-e3ccb360d719@oss.qualcomm.com>
On Wed, 6 May 2026 06:45:21 +0200, Viken Dadhaniya
<viken.dadhaniya@oss.qualcomm.com> said:
> When uart_flush_buffer() runs before the DMA completion IRQ is delivered,
> the following race can occur (all steps serialized by uart_port_lock):
>
> 1. DMA starts: tx_remaining = N, kfifo contains N bytes
> 2. DMA completes in hardware; IRQ is pending but not yet delivered
> 3. uart_flush_buffer() acquires the port lock and calls kfifo_reset(),
> making kfifo_len() = 0 while tx_remaining remains N
> 4. uart_flush_buffer() releases the port lock
> 5. DMA IRQ fires; handle_tx_dma() acquires the port lock and calls
> uart_xmit_advance(uport, tx_remaining) on an empty kfifo
>
> uart_xmit_advance() increments kfifo->out by tx_remaining. Since
> kfifo_reset() already set both in and out to 0, out wraps past in,
> causing kfifo_len() to return UART_XMIT_SIZE - tx_remaining. The next
> start_tx_dma() call then submits a DMA transfer of stale buffer data.
>
> Fix this by snapshotting kfifo_len() at the start of handle_tx_dma()
> and skipping uart_xmit_advance() when fifo_len < tx_remaining, which
> indicates the kfifo was reset by a preceding flush.
>
> Fixes: 2aaa43c70778 ("tty: serial: qcom-geni-serial: add support for serial engine DMA")
> Cc: stable@vger.kernel.org
> Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
> ---
Make sense, thanks.
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply
* [PATCH tty v4 0/6] 8250: Add console flow control
From: John Ogness @ 2026-05-06 12:15 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: Andy Shevchenko, linux-kernel, linux-serial, Krzysztof Kozlowski,
Alim Akhtar, David S. Miller, Ilpo Järvinen, Andy Shevchenko,
Thomas Fourier, Kees Cook, linux-arm-kernel, linux-samsung-soc,
sparclinux, Biju Das, Geert Uytterhoeven, Lad Prabhakar,
Thierry Bultel, Osama Abdelkader, Ingo Molnar, Xin Zhao,
Joseph Tilahun, Krzysztof Kozlowski, Lukas Wunner,
Dr. David Alan Gilbert
Hi,
This is v4 of a series to implement console flow control for the
8250 serial driver. v3 is here [0].
The 8250 driver already has code in place to support console flow
control. However, there is no way to activate it and it is
incomplete. This series provides the necessary missing pieces while
attempting to be as conservative as possible, so as not to introduce
any side effects into the many 8250 variants or other non-8250 serial
drivers.
For patch 2 I used the following Coccinelle script to perform the
modifications...
===== BEGIN cons_flow.cocci =====
// SPDX-License-Identifier: GPL-2.0-only
// Options: --all-includes
virtual patch
@r1@
type T1;
identifier U;
@@
T1 {
...
struct uart_port U;
...
};
@r2@
r1.T1 *E;
@@
- (E->port.flags & UPF_CONS_FLOW)
+ uart_cons_flow_enabled(&E->port)
@r3@
struct uart_port *U;
@@
- (U->flags & UPF_CONS_FLOW)
+ uart_cons_flow_enabled(U)
@r4@
struct uart_port *U;
@@
- U->flags |= UPF_CONS_FLOW
+ uart_set_cons_flow_enabled(U, true)
===== END cons_flow.cocci =====
Changes for v4:
- Rename uart_get_cons_flow() to uart_cons_flow_enabled().
- Rename uart_set_cons_flow() to uart_set_cons_flow_enabled().
Changes for v3:
- Deprecate UPF_CONS_FLOW. Provide separate boolean with wrappers as
alternative.
- Update all UPF_CONS_FLOW users to new cons_flow wrappers.
- Use irqsave variant of spin lock for status update.
- When 8250 console flow control is not specified, clear the policy.
Changes for v2:
- Prepend a patch to perform an extra LSR wait after CTS assertion if
the initial LSR wait timed out.
- Close a window in serial8250_register_8250_port() where console
flow control was briefly disabled.
- Add port lock synchronization to the port->status RMW update in
uart_set_options().
John Ogness
[0] https://lore.kernel.org/lkml/20260417102423.40984-1-john.ogness@linutronix.de
John Ogness (6):
serial: core: Add dedicated uart_port field for console flow
serial: Replace driver usage of UPF_CONS_FLOW
serial: sh-sci: Avoid deprecated UPF_CONS_FLOW
serial: 8250: Set cons_flow on port registration
serial: 8250: Check LSR timeout on console flow control
serial: 8250: Add support for console flow control
drivers/tty/serial/8250/8250_core.c | 6 ++++++
drivers/tty/serial/8250/8250_port.c | 21 +++++++++++++++++----
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_core.c | 21 ++++++++++++++++++++-
drivers/tty/serial/serial_txx9.c | 4 ++--
drivers/tty/serial/sh-sci.c | 5 ++++-
drivers/tty/serial/sunsu.c | 2 +-
include/linux/serial_core.h | 20 ++++++++++++++++++++
12 files changed, 78 insertions(+), 17 deletions(-)
base-commit: a2083fd1fa7aa0ef5cd8fd92396da0de2d0654b0
--
2.47.3
^ permalink raw reply
* [PATCH tty v4 1/6] serial: core: Add dedicated uart_port field for console flow
From: John Ogness @ 2026-05-06 12:15 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: Andy Shevchenko, linux-kernel, linux-serial
In-Reply-To: <20260506121606.5805-1-john.ogness@linutronix.de>
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. Usually this policy is 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 bit 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 getter/setter wrappers
to allow for adding more policies later and/or locking constraint
validation.
Mark UPF_CONS_FLOW as deprecated.
Signed-off-by: John Ogness <john.ogness@linutronix.de>
---
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..4f7bbdd900176 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_set_cons_flow_enabled()/uart_cons_flow_enabled() 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))
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_port *uport)
return ((uport->status & mask) == UPSTAT_CTS_ENABLE);
}
+static inline void uart_set_cons_flow_enabled(struct uart_port *uport, bool enabled)
+{
+ uport->cons_flow = enabled;
+}
+
+static inline bool uart_cons_flow_enabled(const struct uart_port *uport)
+{
+ return uport->cons_flow;
+}
+
/*
* The following are helper functions for the low level drivers.
*/
--
2.47.3
^ permalink raw reply related
* [PATCH tty v4 2/6] serial: Replace driver usage of UPF_CONS_FLOW
From: John Ogness @ 2026-05-06 12:15 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: Andy Shevchenko, linux-kernel, Krzysztof Kozlowski, Alim Akhtar,
David S. Miller, Ilpo Järvinen, Andy Shevchenko,
Thomas Fourier, Kees Cook, linux-serial, linux-arm-kernel,
linux-samsung-soc, sparclinux
In-Reply-To: <20260506121606.5805-1-john.ogness@linutronix.de>
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 getter/setter 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 for
uart_port.flags. A follow-up commit will address this.
Note2: The samsung_tty driver is using UPF_CONS_FLOW as a platform data
configuration flag. However, the driver explicitly checks for
this configuration flag and thus setting UPF_CONS_FLOW in
uart_port.flags is avoided.
Signed-off-by: John Ogness <john.ogness@linutronix.de>
---
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..dbed5e5767541 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);
/* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
+ if (uart_cons_flow_enabled(&up->port)) {
for (tmout = 1000000; tmout; tmout--) {
unsigned int msr = serial_in(up, UART_MSR);
up->msr_saved_flags |= 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_cons_flow_enabled(&up->port);
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..544695cb184c3 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)
}
/* Wait up to 1s for flow control if necessary */
- if (port->flags & UPF_CONS_FLOW) {
+ if (uart_cons_flow_enabled(port)) {
tmout = 1000000;
while (--tmout) {
unsigned int val;
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 0b85f47ff19e0..a689d190940cf 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));
/* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
+ if (uart_cons_flow_enabled(&up->port)) {
for (tmout = 1000000; tmout; tmout--) {
unsigned int msr = serial_in(up, UART_MSR);
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 6729d8e83c3c5..2f72cd62e2488 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)
}
/* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
+ if (uart_cons_flow_enabled(&up->port)) {
unsigned int tmout;
for (tmout = 1000000; tmout; tmout--) {
unsigned int msr = ioread8(up->membase + UART_MSR);
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index fea0255067ccd..10fc8990579b5 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));
/* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
+ if (uart_cons_flow_enabled(&up->port)) {
tmout = 1000000;
while (--tmout &&
((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
index e27806bf2cf3e..2f94fc798cffb 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 *port)
ourport->tx_enabled = 0;
ourport->tx_in_progress = 0;
- if (port->flags & UPF_CONS_FLOW)
+ if (uart_cons_flow_enabled(port))
s3c24xx_serial_rx_enable(port);
ourport->tx_mode = 0;
@@ -493,7 +493,7 @@ static void s3c24xx_serial_start_tx(struct uart_port *port)
struct tty_port *tport = &port->state->port;
if (!ourport->tx_enabled) {
- if (port->flags & UPF_CONS_FLOW)
+ if (uart_cons_flow_enabled(port))
s3c24xx_serial_rx_disable(port);
ourport->tx_enabled = 1;
@@ -781,7 +781,7 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
uerstat = rd_regl(port, S3C2410_UERSTAT);
ch = rd_reg(port, S3C2410_URXH);
- if (port->flags & UPF_CONS_FLOW) {
+ if (uart_cons_flow_enabled(port)) {
bool txe = s3c24xx_serial_txempty_nofifo(port);
if (ourport->rx_enabled) {
@@ -1830,7 +1830,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
if (cfg->uart_flags & UPF_CONS_FLOW) {
dev_dbg(port->dev, "enabling flow control\n");
- port->flags |= UPF_CONS_FLOW;
+ uart_set_cons_flow_enabled(port, true);
}
/* sort our the physical and virtual addresses for each UART */
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index 436a559234dfe..4ae9a45c8e3a3 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);
/* Wait up to 1s for flow control if necessary */
- if (up->flags & UPF_CONS_FLOW) {
+ if (uart_cons_flow_enabled(up)) {
tmout = 1000000;
while (--tmout &&
(sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS))
@@ -857,7 +857,7 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count)
* Disable flow-control if enabled (and unnecessary)
*/
flcr = sio_in(up, TXX9_SIFLCR);
- if (!(up->flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES))
+ if (!uart_cons_flow_enabled(up) && (flcr & TXX9_SIFLCR_TES))
sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES);
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..4ff3e5c41dab9 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));
/* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
+ if (uart_cons_flow_enabled(&up->port)) {
tmout = 1000000;
while (--tmout &&
((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
--
2.47.3
^ permalink raw reply related
* [PATCH tty v4 3/6] serial: sh-sci: Avoid deprecated UPF_CONS_FLOW
From: John Ogness @ 2026-05-06 12:15 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: Andy Shevchenko, linux-kernel, Biju Das, Geert Uytterhoeven,
Lad Prabhakar, Thierry Bultel, linux-serial
In-Reply-To: <20260506121606.5805-1-john.ogness@linutronix.de>
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 <john.ogness@linutronix.de>
---
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..a1328a3b6638d 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 *dev,
}
port->type = SCI_PUBLIC_PORT_ID(p->type);
- port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags;
+ port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF |
+ (p->flags & ~UPF_CONS_FLOW);
port->fifosize = sci_port->params->fifosize;
+ uart_set_cons_flow_enabled(port, p->flags & UPF_CONS_FLOW);
+
if (p->type == PORT_SCI && !dev->dev.of_node) {
if (sci_port->reg_size >= 0x20)
port->regshift = 2;
--
2.47.3
^ permalink raw reply related
* [PATCH tty v4 4/6] serial: 8250: Set cons_flow on port registration
From: John Ogness @ 2026-05-06 12:15 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: Andy Shevchenko, linux-kernel, Ilpo Järvinen,
Osama Abdelkader, Kees Cook, Ingo Molnar, linux-serial
In-Reply-To: <20260506121606.5805-1-john.ogness@linutronix.de>
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 <john.ogness@linutronix.de>
---
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..b0275204e1167 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_8250_port *up)
uart->lsr_save_mask = up->lsr_save_mask;
uart->dma = up->dma;
+ uart_set_cons_flow_enabled(&uart->port, uart_cons_flow_enabled(&up->port));
+
/* Take tx_loadsz from fifosize if it wasn't set separately */
if (uart->port.fifosize && !uart->tx_loadsz)
uart->tx_loadsz = uart->port.fifosize;
--
2.47.3
^ permalink raw reply related
* [PATCH tty v4 5/6] serial: 8250: Check LSR timeout on console flow control
From: John Ogness @ 2026-05-06 12:16 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: Andy Shevchenko, linux-kernel, Ilpo Järvinen,
Andy Shevchenko, linux-serial
In-Reply-To: <20260506121606.5805-1-john.ogness@linutronix.de>
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 <john.ogness@linutronix.de>
---
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 dbed5e5767541..719789013f6df 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;
- wait_for_lsr(up, bits);
+ tx_ready = wait_for_lsr(up, bits);
/* Wait up to 1s for flow control if necessary */
if (uart_cons_flow_enabled(&up->port)) {
for (tmout = 1000000; tmout; tmout--) {
unsigned int msr = serial_in(up, UART_MSR);
up->msr_saved_flags |= 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();
}
--
2.47.3
^ permalink raw reply related
* [PATCH tty v4 6/6] serial: 8250: Add support for console flow control
From: John Ogness @ 2026-05-06 12:16 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: Andy Shevchenko, linux-kernel, Ilpo Järvinen, Ingo Molnar,
Kees Cook, Xin Zhao, Joseph Tilahun, Krzysztof Kozlowski,
Lukas Wunner, Dr. David Alan Gilbert, linux-serial
In-Reply-To: <20260506121606.5805-1-john.ogness@linutronix.de>
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 <john.ogness@linutronix.de>
---
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 b0275204e1167..1f03da85e3414 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 work_struct *work)
int serial8250_register_8250_port(const struct uart_8250_port *up)
{
struct uart_8250_port *uart;
+ bool cons_flow;
int ret;
if (up->port.uartclk == 0)
@@ -716,6 +717,9 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
if (uart->port.type == PORT_8250_CIR)
return -ENODEV;
+ /* Preserve specified console flow control. */
+ cons_flow = uart_cons_flow_enabled(&uart->port);
+
if (uart->port.dev)
uart_remove_one_port(&serial8250_reg, &uart->port);
@@ -746,7 +750,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
uart->lsr_save_mask = up->lsr_save_mask;
uart->dma = up->dma;
- uart_set_cons_flow_enabled(&uart->port, uart_cons_flow_enabled(&up->port));
+ uart_set_cons_flow_enabled(&uart->port, uart_cons_flow_enabled(&up->port) | cons_flow);
/* 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 719789013f6df..9ba3876bffa50 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 = wait_for_lsr(up, bits);
/* Wait up to 1s for flow control if necessary */
- if (uart_cons_flow_enabled(&up->port)) {
+ if (uart_console_hwflow_active(&up->port)) {
for (tmout = 1000000; tmout; tmout--) {
unsigned int msr = serial_in(up, UART_MSR);
up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
@@ -2786,6 +2786,12 @@ serial8250_do_set_termios(struct uart_port *port, struct 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 |= TIOCM_RTS;
+ }
serial8250_set_mctrl(port, port->mctrl);
}
@@ -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_cons_flow_enabled(&up->port);
+ !uart_console_hwflow_active(&up->port);
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;
+ /* Track user-specified console flow control. */
+ uart_set_cons_flow_enabled(port, flow == 'r');
+
if (port->dev)
pm_runtime_get_sync(port->dev);
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.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 console *co,
port->mctrl |= TIOCM_DTR;
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 == 'r' && (termios.c_cflag & CRTSCTS)) {
+ /* Synchronize @status RMW update against the console. */
+ guard(uart_port_lock_irqsave)(port);
+ port->status |= 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 &= TIOCM_DTR;
+ unsigned int mask = TIOCM_DTR;
+
+ /* Console hardware flow control polls CTS. */
+ if (uart_console_hwflow_active(port))
+ mask |= TIOCM_RTS;
+
+ port->mctrl &= 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 4f7bbdd900176..17fcff466e301 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -1175,6 +1175,14 @@ static inline bool uart_cons_flow_enabled(const struct uart_port *uport)
return uport->cons_flow;
}
+static inline bool uart_console_hwflow_active(struct uart_port *uport)
+{
+ return uart_console(uport) &&
+ !(uport->rs485.flags & SER_RS485_ENABLED) &&
+ uart_cons_flow_enabled(uport) &&
+ uart_cts_enabled(uport);
+}
+
/*
* The following are helper functions for the low level drivers.
*/
--
2.47.3
^ permalink raw reply related
* Re: [PATCH tty v4 3/6] serial: sh-sci: Avoid deprecated UPF_CONS_FLOW
From: Geert Uytterhoeven @ 2026-05-06 12:39 UTC (permalink / raw)
To: John Ogness
Cc: Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko, linux-kernel,
Biju Das, Lad Prabhakar, Thierry Bultel, linux-serial,
Linux-sh list
In-Reply-To: <20260506121606.5805-4-john.ogness@linutronix.de>
Hi John,
On Wed, 6 May 2026 at 14:16, John Ogness <john.ogness@linutronix.de> wrote:
> 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 <john.ogness@linutronix.de>
Thanks for your patch!
> --- 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 *dev,
> }
>
> port->type = SCI_PUBLIC_PORT_ID(p->type);
> - port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags;
> + port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF |
> + (p->flags & ~UPF_CONS_FLOW);
This seems over-cautious to me.
The last setter of p->flags was removed in commit 37744feebc086908
("sh: remove sh5 support") in v5.8. No platform data ever set the
UPF_CONS_FLOW flag before. I would rather remove plat_sci_port.flags
and this "| p->flags", so we don't have to care about UPF_CONS_FLOW
in this driver at all.
> port->fifosize = sci_port->params->fifosize;
>
> + uart_set_cons_flow_enabled(port, p->flags & UPF_CONS_FLOW);
> +
> if (p->type == PORT_SCI && !dev->dev.of_node) {
> if (sci_port->reg_size >= 0x20)
> port->regshift = 2;
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH] tty: add missing tty_driver include to tty_port.h
From: Johan Hovold @ 2026-05-06 12:43 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: linux-serial, linux-kernel, Johan Hovold, Xin Zhao
Include the definition of struct tty_driver in tty_port.h to keep the
header self-contained and avoid build breakage in case anyone includes
it before tty_driver.h.
Fixes: eb3b0d92c9c3 ("tty: tty_port: add workqueue to flip TTY buffer")
Cc: Xin Zhao <jackzxcui1989@163.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
---
The offending commit went into 7.1-rc1 so this could go into tty-linus.
Johan
include/linux/tty_port.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/tty_port.h b/include/linux/tty_port.h
index d2a7882c0b58..23cad403bb8f 100644
--- a/include/linux/tty_port.h
+++ b/include/linux/tty_port.h
@@ -6,10 +6,10 @@
#include <linux/kref.h>
#include <linux/mutex.h>
#include <linux/tty_buffer.h>
+#include <linux/tty_driver.h>
#include <linux/wait.h>
struct attribute_group;
-struct tty_driver;
struct tty_port;
struct tty_struct;
--
2.53.0
^ permalink raw reply related
* [PATCH] serial: sh-sci: Remove plat_sci_port.flags
From: Geert Uytterhoeven @ 2026-05-06 12:46 UTC (permalink / raw)
To: John Ogness, Greg Kroah-Hartman, Jiri Slaby, Biju Das,
Lad Prabhakar, Wolfram Sang
Cc: linux-serial, linux-renesas-soc, linux-sh, Geert Uytterhoeven
The last setter of p->flags was removed in commit 37744feebc086908
("sh: remove sh5 support") in v5.8.
Link: https://lore.kernel.org/CAMuHMdXs94k3-7YD-yO7p2=+u8waYGAz8mpP5LDbMf3szt4V-w@mail.gmail.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/tty/serial/sh-sci.c | 2 +-
include/linux/serial_sci.h | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 6c819b6b24258d36..a35230d57540384c 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -3369,7 +3369,7 @@ static int sci_init_single(struct platform_device *dev,
}
port->type = SCI_PUBLIC_PORT_ID(p->type);
- port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags;
+ port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF;
port->fifosize = sci_port->params->fifosize;
if (p->type == PORT_SCI && !dev->dev.of_node) {
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
index 0f2f50b8d28e2743..36c795d61f7e8457 100644
--- a/include/linux/serial_sci.h
+++ b/include/linux/serial_sci.h
@@ -51,7 +51,6 @@ struct plat_sci_port_ops {
*/
struct plat_sci_port {
unsigned int type; /* SCI / SCIF / IRDA / HSCIF */
- upf_t flags; /* UPF_* flags */
unsigned int sampling_rate;
unsigned int scscr; /* SCSCR initialization */
--
2.43.0
^ permalink raw reply related
* Re: [PATCH tty v4 3/6] serial: sh-sci: Avoid deprecated UPF_CONS_FLOW
From: Geert Uytterhoeven @ 2026-05-06 12:50 UTC (permalink / raw)
To: John Ogness
Cc: Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko, linux-kernel,
Biju Das, Lad Prabhakar, Thierry Bultel, linux-serial,
Linux-sh list
In-Reply-To: <CAMuHMdXs94k3-7YD-yO7p2=+u8waYGAz8mpP5LDbMf3szt4V-w@mail.gmail.com>
On Wed, 6 May 2026 at 14:39, Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> On Wed, 6 May 2026 at 14:16, John Ogness <john.ogness@linutronix.de> wrote:
> > 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 <john.ogness@linutronix.de>
>
> Thanks for your patch!
>
> > --- 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 *dev,
> > }
> >
> > port->type = SCI_PUBLIC_PORT_ID(p->type);
> > - port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags;
> > + port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF |
> > + (p->flags & ~UPF_CONS_FLOW);
>
> This seems over-cautious to me.
> The last setter of p->flags was removed in commit 37744feebc086908
> ("sh: remove sh5 support") in v5.8. No platform data ever set the
> UPF_CONS_FLOW flag before. I would rather remove plat_sci_port.flags
> and this "| p->flags", so we don't have to care about UPF_CONS_FLOW
> in this driver at all.
I have sent a patch to remove it:
https://lore.kernel.org/20260506124643.128021-1-geert+renesas@glider.be/
Builds on Renesas ARM/ARM64/RISCV/SH, and boots on QEMU
(rts7751)r2d.
>
> > port->fifosize = sci_port->params->fifosize;
> >
> > + uart_set_cons_flow_enabled(port, p->flags & UPF_CONS_FLOW);
> > +
> > if (p->type == PORT_SCI && !dev->dev.of_node) {
> > if (sci_port->reg_size >= 0x20)
> > port->regshift = 2;
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH tty v4 3/6] serial: sh-sci: Avoid deprecated UPF_CONS_FLOW
From: John Ogness @ 2026-05-06 12:53 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko, linux-kernel,
Biju Das, Lad Prabhakar, Thierry Bultel, linux-serial,
Linux-sh list
In-Reply-To: <CAMuHMdXs94k3-7YD-yO7p2=+u8waYGAz8mpP5LDbMf3szt4V-w@mail.gmail.com>
Hi Geert,
On 2026-05-06, Geert Uytterhoeven <geert@linux-m68k.org> wrote:
>> --- 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 *dev,
>> }
>>
>> port->type = SCI_PUBLIC_PORT_ID(p->type);
>> - port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags;
>> + port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF |
>> + (p->flags & ~UPF_CONS_FLOW);
>
> This seems over-cautious to me.
> The last setter of p->flags was removed in commit 37744feebc086908
> ("sh: remove sh5 support") in v5.8. No platform data ever set the
> UPF_CONS_FLOW flag before. I would rather remove plat_sci_port.flags
> and this "| p->flags", so we don't have to care about UPF_CONS_FLOW
> in this driver at all.
If there is a v5, I will drop this patch. If v4 is acceptable, the
maintainer can just drop this patch.
I will leave the plat_sci_port.flags removal as an excercise for the sh
folks.
Thanks for your feedback.
John
^ permalink raw reply
* Re: [PATCH] serial: sh-sci: Remove plat_sci_port.flags
From: John Ogness @ 2026-05-06 14:01 UTC (permalink / raw)
To: Geert Uytterhoeven, Greg Kroah-Hartman, Jiri Slaby, Biju Das,
Lad Prabhakar, Wolfram Sang
Cc: linux-serial, linux-renesas-soc, linux-sh, Geert Uytterhoeven
In-Reply-To: <20260506124643.128021-1-geert+renesas@glider.be>
On 2026-05-06, Geert Uytterhoeven <geert+renesas@glider.be> wrote:
> The last setter of p->flags was removed in commit 37744feebc086908
> ("sh: remove sh5 support") in v5.8.
>
> Link: https://lore.kernel.org/CAMuHMdXs94k3-7YD-yO7p2=+u8waYGAz8mpP5LDbMf3szt4V-w@mail.gmail.com
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Aside from manually inspecting possible users, I also checked using a
coccinelle script.
Reviewed-by: John Ogness <john.ogness@linutronix.de>
===== BEGIN flags.cocci =====
// SPDX-License-Identifier: GPL-2.0-only
// Options: --all-includes
virtual patch
@r1@
struct plat_sci_port *U;
@@
- U->flags
+ FLAGS_USER
@r2@
struct plat_sci_port U;
@@
- U.flags
+ FLAGS_USER
@r3@
identifier U;
expression E;
@@
static struct plat_sci_port U = {
- .flags = E
+ FLAGS_USER
};
===== END flags.cocci =====
^ permalink raw reply
* [PATCH 0/2] Add tracepoints support for Qualcomm GENI Serial drivers
From: Praveen Talari @ 2026-05-06 17:24 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
Greg Kroah-Hartman, Jiri Slaby, Konrad Dybcio
Cc: linux-kernel, linux-trace-kernel, linux-arm-msm, linux-serial,
Mukesh Kumar Savaliya, Aniket Randive, chandana.chiluveru,
jyothi.seerapu, Praveen Talari
Add tracepoints to the Qualcomm GENI (Generic Interface) serial driver.
These trace events enable runtime debugging and performance analysis of
UART operations.
The trace events cover UART termios configuration, clock setup, manual
control state, interrupt status, and actual transmitted/received data in
hexadecimal format.
Usage examples:
Enable all serial traces:
echo 1 > /sys/kernel/debug/tracing/events/qcom_geni_serial/enable
cat /sys/kernel/debug/tracing/trace_pipe
Example trace output:
2517.938432: geni_serial_clk_cfg: a94000.serial: desired_rate=1843200
clk_rate=7372800 clk_div=4 clk_idx=0
2517.938753: geni_serial_irq: a94000.serial: m_irq=0x88800000
s_irq=0x08000111 dma_tx=0x00000000 dma_rx=0x00000000
2517.938803: geni_serial_set_termios: a94000.serial: baud=115200 bpc=8
tx_trans=0x00000002 tx_par=0x00000000 rx_trans=0x00000000
rx_par=0x00000000 stop=0
2517.938807: geni_serial_set_mctrl: a94000.serial: mctrl=0x8006
uart_manual_rfr=0x00000000
2517.938818: geni_serial_get_mctrl: a94000.serial: mctrl=0x0160
geni_ios=0x00000001
2517.939165: geni_serial_irq: a94000.serial: m_irq=0x00400000
s_irq=0x00000000 dma_tx=0x00000000 dma_rx=0x00000000
2517.939592: geni_serial_tx_data: a94000.serial: tx_len=8 data=61 62 63
64 65 66 67 68
2517.940610: geni_serial_irq: a94000.serial: m_irq=0x00000001
s_irq=0x00000000 dma_tx=0x00000003 dma_rx=0x00000000
2517.942174: geni_serial_irq: a94000.serial: m_irq=0x08000000
s_irq=0x08000100 dma_tx=0x00000000 dma_rx=0x00000003
2517.942323: geni_serial_rx_data: a94000.serial: rx_len=8 data=61 62 63
64 65 66 67 68
2517.942680: geni_serial_set_mctrl: a94000.serial: mctrl=0x8000
uart_manual_rfr=0x80000002
Signed-off-by: Praveen Talari <praveen.talari@oss.qualcomm.com>
---
Praveen Talari (2):
serial: qcom-geni: trace: Add tracepoint support for Qualcomm GENI serial
serial: qcom-geni: Add tracepoints for Qualcomm GENI serial driver
drivers/tty/serial/qcom_geni_serial.c | 27 ++++-
include/trace/events/qcom_geni_serial.h | 173 ++++++++++++++++++++++++++++++++
2 files changed, 196 insertions(+), 4 deletions(-)
---
base-commit: 1f5ffc672165ff851063a5fd044b727ab2517ae3
change-id: 20260427-add-tracepoints-for-qcom-geni-serial-948777218b7b
Best regards,
--
Praveen Talari <praveen.talari@oss.qualcomm.com>
^ permalink raw reply
* [PATCH v1 1/2] serial: qcom-geni: trace: Add tracepoint support for Qualcomm GENI serial
From: Praveen Talari @ 2026-05-06 17:24 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
Greg Kroah-Hartman, Jiri Slaby, Konrad Dybcio
Cc: linux-kernel, linux-trace-kernel, linux-arm-msm, linux-serial,
Mukesh Kumar Savaliya, Aniket Randive, chandana.chiluveru,
jyothi.seerapu, Praveen Talari
In-Reply-To: <20260506-add-tracepoints-for-qcom-geni-serial-v1-0-544b22612e08@oss.qualcomm.com>
Add tracepoint support to the Qualcomm GENI serial driver to provide
runtime visibility into driver behavior without requiring invasive debug
patches.
The trace events cover UART termios configuration, clock setup, modem
control state, interrupt status, and TX/RX data, making it easier to
diagnose communication issues in the field.
Signed-off-by: Praveen Talari <praveen.talari@oss.qualcomm.com>
---
include/trace/events/qcom_geni_serial.h | 173 ++++++++++++++++++++++++++++++++
1 file changed, 173 insertions(+)
diff --git a/include/trace/events/qcom_geni_serial.h b/include/trace/events/qcom_geni_serial.h
new file mode 100644
index 000000000000..f386d163907a
--- /dev/null
+++ b/include/trace/events/qcom_geni_serial.h
@@ -0,0 +1,173 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM qcom_geni_serial
+
+#if !defined(_TRACE_QCOM_GENI_SERIAL_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_QCOM_GENI_SERIAL_H
+
+#include <linux/device.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(geni_serial_set_termios,
+ TP_PROTO(struct device *dev, unsigned int baud,
+ unsigned int bits_per_char, u32 tx_trans_cfg,
+ u32 tx_parity_cfg, u32 rx_trans_cfg,
+ u32 rx_parity_cfg, u32 stop_bit_len),
+ TP_ARGS(dev, baud, bits_per_char, tx_trans_cfg, tx_parity_cfg,
+ rx_trans_cfg, rx_parity_cfg, stop_bit_len),
+
+ TP_STRUCT__entry(__string(name, dev_name(dev))
+ __field(unsigned int, baud)
+ __field(unsigned int, bits_per_char)
+ __field(u32, tx_trans_cfg)
+ __field(u32, tx_parity_cfg)
+ __field(u32, rx_trans_cfg)
+ __field(u32, rx_parity_cfg)
+ __field(u32, stop_bit_len)
+ ),
+
+ TP_fast_assign(__assign_str(name);
+ __entry->baud = baud;
+ __entry->bits_per_char = bits_per_char;
+ __entry->tx_trans_cfg = tx_trans_cfg;
+ __entry->tx_parity_cfg = tx_parity_cfg;
+ __entry->rx_trans_cfg = rx_trans_cfg;
+ __entry->rx_parity_cfg = rx_parity_cfg;
+ __entry->stop_bit_len = stop_bit_len;
+ ),
+
+ TP_printk("%s: baud=%u bpc=%u tx_trans=0x%08x tx_par=0x%08x rx_trans=0x%08x rx_par=0x%08x stop=%u",
+ __get_str(name), __entry->baud, __entry->bits_per_char,
+ __entry->tx_trans_cfg, __entry->tx_parity_cfg,
+ __entry->rx_trans_cfg, __entry->rx_parity_cfg,
+ __entry->stop_bit_len)
+);
+
+TRACE_EVENT(geni_serial_clk_cfg,
+ TP_PROTO(struct device *dev, unsigned int desired_rate,
+ unsigned long clk_rate, unsigned int clk_div,
+ unsigned int clk_idx),
+ TP_ARGS(dev, desired_rate, clk_rate, clk_div, clk_idx),
+
+ TP_STRUCT__entry(__string(name, dev_name(dev))
+ __field(unsigned int, desired_rate)
+ __field(unsigned long, clk_rate)
+ __field(unsigned int, clk_div)
+ __field(unsigned int, clk_idx)
+ ),
+
+ TP_fast_assign(__assign_str(name);
+ __entry->desired_rate = desired_rate;
+ __entry->clk_rate = clk_rate;
+ __entry->clk_div = clk_div;
+ __entry->clk_idx = clk_idx;
+ ),
+
+ TP_printk("%s: desired_rate=%u clk_rate=%lu clk_div=%u clk_idx=%u",
+ __get_str(name), __entry->desired_rate, __entry->clk_rate,
+ __entry->clk_div, __entry->clk_idx)
+);
+
+TRACE_EVENT(geni_serial_irq,
+ TP_PROTO(struct device *dev, u32 m_irq, u32 s_irq,
+ u32 dma_tx, u32 dma_rx),
+ TP_ARGS(dev, m_irq, s_irq, dma_tx, dma_rx),
+
+ TP_STRUCT__entry(__string(name, dev_name(dev))
+ __field(u32, m_irq)
+ __field(u32, s_irq)
+ __field(u32, dma_tx)
+ __field(u32, dma_rx)
+ ),
+
+ TP_fast_assign(__assign_str(name);
+ __entry->m_irq = m_irq;
+ __entry->s_irq = s_irq;
+ __entry->dma_tx = dma_tx;
+ __entry->dma_rx = dma_rx;
+ ),
+
+ TP_printk("%s: m_irq=0x%08x s_irq=0x%08x dma_tx=0x%08x dma_rx=0x%08x",
+ __get_str(name), __entry->m_irq, __entry->s_irq,
+ __entry->dma_tx, __entry->dma_rx)
+);
+
+TRACE_EVENT(geni_serial_tx_data,
+ TP_PROTO(struct device *dev, const u8 *buf, unsigned int len),
+ TP_ARGS(dev, buf, len),
+
+ TP_STRUCT__entry(__string(name, dev_name(dev))
+ __field(unsigned int, len)
+ __dynamic_array(u8, data, len)
+ ),
+
+ TP_fast_assign(__assign_str(name);
+ __entry->len = len;
+ memcpy(__get_dynamic_array(data), buf, len);
+ ),
+
+ TP_printk("%s: tx_len=%u data=%s",
+ __get_str(name), __entry->len,
+ __print_hex(__get_dynamic_array(data), __entry->len))
+);
+
+TRACE_EVENT(geni_serial_rx_data,
+ TP_PROTO(struct device *dev, const u8 *buf, unsigned int len),
+ TP_ARGS(dev, buf, len),
+
+ TP_STRUCT__entry(__string(name, dev_name(dev))
+ __field(unsigned int, len)
+ __dynamic_array(u8, data, len)
+ ),
+
+ TP_fast_assign(__assign_str(name);
+ __entry->len = len;
+ memcpy(__get_dynamic_array(data), buf, len);
+ ),
+
+ TP_printk("%s: rx_len=%u data=%s",
+ __get_str(name), __entry->len,
+ __print_hex(__get_dynamic_array(data), __entry->len))
+);
+
+TRACE_EVENT(geni_serial_set_mctrl,
+ TP_PROTO(struct device *dev, unsigned int mctrl,
+ u32 uart_manual_rfr),
+ TP_ARGS(dev, mctrl, uart_manual_rfr),
+
+ TP_STRUCT__entry(__string(name, dev_name(dev))
+ __field(unsigned int, mctrl)
+ __field(u32, uart_manual_rfr)
+ ),
+
+ TP_fast_assign(__assign_str(name);
+ __entry->mctrl = mctrl;
+ __entry->uart_manual_rfr = uart_manual_rfr;
+ ),
+
+ TP_printk("%s: mctrl=0x%04x uart_manual_rfr=0x%08x",
+ __get_str(name), __entry->mctrl, __entry->uart_manual_rfr)
+);
+
+TRACE_EVENT(geni_serial_get_mctrl,
+ TP_PROTO(struct device *dev, unsigned int mctrl, u32 geni_ios),
+ TP_ARGS(dev, mctrl, geni_ios),
+
+ TP_STRUCT__entry(__string(name, dev_name(dev))
+ __field(unsigned int, mctrl)
+ __field(u32, geni_ios)
+ ),
+
+ TP_fast_assign(__assign_str(name);
+ __entry->mctrl = mctrl;
+ __entry->geni_ios = geni_ios;
+ ),
+
+ TP_printk("%s: mctrl=0x%04x geni_ios=0x%08x",
+ __get_str(name), __entry->mctrl, __entry->geni_ios)
+);
+
+#endif /* _TRACE_QCOM_GENI_SERIAL_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
--
2.34.1
^ permalink raw reply related
* [PATCH v1 2/2] serial: qcom-geni: Add tracepoints for Qualcomm GENI serial driver
From: Praveen Talari @ 2026-05-06 17:24 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
Greg Kroah-Hartman, Jiri Slaby, Konrad Dybcio
Cc: linux-kernel, linux-trace-kernel, linux-arm-msm, linux-serial,
Mukesh Kumar Savaliya, Aniket Randive, chandana.chiluveru,
jyothi.seerapu, Praveen Talari
In-Reply-To: <20260506-add-tracepoints-for-qcom-geni-serial-v1-0-544b22612e08@oss.qualcomm.com>
Add tracing to the Qualcomm GENI serial driver to improve runtime
observability.
Trace hooks are added at key points including termios and clock
configuration, manual control get/set, interrupt handling, and data
TX/RX paths.
Usage examples:
Enable all serial traces:
echo 1 > /sys/kernel/debug/tracing/events/qcom_geni_serial/enable
cat /sys/kernel/debug/tracing/trace_pipe
Example trace output:
2517.938432: geni_serial_clk_cfg: a94000.serial: desired_rate=1843200
clk_rate=7372800 clk_div=4 clk_idx=0
2517.938753: geni_serial_irq: a94000.serial: m_irq=0x88800000
s_irq=0x08000111 dma_tx=0x00000000 dma_rx=0x00000000
2517.938803: geni_serial_set_termios: a94000.serial: baud=115200 bpc=8
tx_trans=0x00000002 tx_par=0x00000000 rx_trans=0x00000000
rx_par=0x00000000 stop=0
2517.938807: geni_serial_set_mctrl: a94000.serial: mctrl=0x8006
uart_manual_rfr=0x00000000
2517.938818: geni_serial_get_mctrl: a94000.serial: mctrl=0x0160
geni_ios=0x00000001
2517.939165: geni_serial_irq: a94000.serial: m_irq=0x00400000
s_irq=0x00000000 dma_tx=0x00000000 dma_rx=0x00000000
2517.939592: geni_serial_tx_data: a94000.serial: tx_len=8 data=61 62 63
64 65 66 67 68
2517.940610: geni_serial_irq: a94000.serial: m_irq=0x00000001
s_irq=0x00000000 dma_tx=0x00000003 dma_rx=0x00000000
2517.942174: geni_serial_irq: a94000.serial: m_irq=0x08000000
s_irq=0x08000100 dma_tx=0x00000000 dma_rx=0x00000003
2517.942323: geni_serial_rx_data: a94000.serial: rx_len=8 data=61 62 63
64 65 66 67 68
2517.942680: geni_serial_set_mctrl: a94000.serial: mctrl=0x8000
uart_manual_rfr=0x80000002
Signed-off-by: Praveen Talari <praveen.talari@oss.qualcomm.com>
---
drivers/tty/serial/qcom_geni_serial.c | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index e6b0a55f0cfb..9e2de074d799 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -7,6 +7,9 @@
/* Disable MMIO tracing to prevent excessive logging of unwanted MMIO traces */
#define __DISABLE_TRACE_MMIO__
+#define CREATE_TRACE_POINTS
+#include <trace/events/qcom_geni_serial.h>
+
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/io.h>
@@ -225,7 +228,7 @@ static void qcom_geni_serial_config_port(struct uart_port *uport, int cfg_flags)
static unsigned int qcom_geni_serial_get_mctrl(struct uart_port *uport)
{
unsigned int mctrl = TIOCM_DSR | TIOCM_CAR;
- u32 geni_ios;
+ u32 geni_ios = 0;
if (uart_console(uport)) {
mctrl |= TIOCM_CTS;
@@ -235,6 +238,8 @@ static unsigned int qcom_geni_serial_get_mctrl(struct uart_port *uport)
mctrl |= TIOCM_CTS;
}
+ trace_geni_serial_get_mctrl(uport->dev, mctrl, geni_ios);
+
return mctrl;
}
@@ -253,6 +258,8 @@ static void qcom_geni_serial_set_mctrl(struct uart_port *uport,
if (!(mctrl & TIOCM_RTS) && !uport->suspended)
uart_manual_rfr = UART_MANUAL_RFR_EN | UART_RFR_NOT_READY;
writel(uart_manual_rfr, uport->membase + SE_UART_MANUAL_RFR);
+
+ trace_geni_serial_set_mctrl(uport->dev, mctrl, uart_manual_rfr);
}
static const char *qcom_geni_serial_get_type(struct uart_port *uport)
@@ -683,6 +690,8 @@ static void qcom_geni_serial_start_tx_dma(struct uart_port *uport)
xmit_size = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail,
UART_XMIT_SIZE);
+ trace_geni_serial_tx_data(uport->dev, tail, xmit_size);
+
qcom_geni_set_rs485_mode(uport, SER_RS485_RTS_ON_SEND);
qcom_geni_serial_setup_tx(uport, xmit_size);
@@ -909,8 +918,10 @@ static void qcom_geni_serial_handle_rx_dma(struct uart_port *uport, bool drop)
return;
}
- if (!drop)
+ if (!drop) {
+ trace_geni_serial_rx_data(uport->dev, port->rx_buf, rx_in);
handle_rx_uart(uport, rx_in);
+ }
ret = geni_se_rx_dma_prep(&port->se, port->rx_buf,
DMA_RX_BUF_SIZE,
@@ -1069,6 +1080,10 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
geni_status = readl(uport->membase + SE_GENI_STATUS);
dma = readl(uport->membase + SE_GENI_DMA_MODE_EN);
m_irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
+
+ trace_geni_serial_irq(uport->dev, m_irq_status, s_irq_status,
+ dma_tx_status, dma_rx_status);
+
writel(m_irq_status, uport->membase + SE_GENI_M_IRQ_CLEAR);
writel(s_irq_status, uport->membase + SE_GENI_S_IRQ_CLEAR);
writel(dma_tx_status, uport->membase + SE_DMA_TX_IRQ_CLR);
@@ -1281,8 +1296,8 @@ static int geni_serial_set_rate(struct uart_port *uport, unsigned int baud)
return -EINVAL;
}
- dev_dbg(port->se.dev, "desired_rate = %u, clk_rate = %lu, clk_div = %u\n, clk_idx = %u\n",
- baud * sampling_rate, clk_rate, clk_div, clk_idx);
+ trace_geni_serial_clk_cfg(uport->dev, baud * sampling_rate, clk_rate,
+ clk_div, clk_idx);
uport->uartclk = clk_rate;
port->clk_rate = clk_rate;
@@ -1432,6 +1447,10 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
writel(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN);
writel(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN);
writel(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN);
+
+ trace_geni_serial_set_termios(uport->dev, baud, bits_per_char,
+ tx_trans_cfg, tx_parity_cfg, rx_trans_cfg,
+ rx_parity_cfg, stop_bit_len);
}
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v7 6/6] ARM: zte: defconfig: Add a zx29 defconfig file
From: Stefan Dösinger @ 2026-05-06 17:39 UTC (permalink / raw)
To: Linus Walleij
Cc: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Drew Fustini,
Greg Kroah-Hartman, Jiri Slaby, linux-doc, linux-kernel,
linux-arm-kernel, devicetree, soc, linux-serial
In-Reply-To: <CAD++jL=S6DSOuC-PXFn76SA7e-Lgueu9Z2wuF7icXCVX7MBpJw@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 765 bytes --]
Hi,
Am Dienstag, 5. Mai 2026, 12:54:29 Ostafrikanische Zeit schrieb Linus Walleij:
> On Wed, Apr 29, 2026 at 9:14 PM Stefan Dösinger
> I'm in favor of this, mainly because multi_v7 is pretty useless
> for this board, it is absolutely too big to boot on the machine,
> the board is odd and need some ARM64 stuff.
I added it more out of cluenessness, thought that every board should have a
defconfig and Sashiko let me know that multi_v7 is the preferred. But I like
your reasoning. I'll send a v8 with some of Sashiko's (very impressive)
findings but keep the defconfig.
> Reviewed-by: Linus Walleij <linusw@kernel.org>
Thanks for the reviews as always, and thanks to Krzysztof for the yeoman's
work of guiding noobs over and over again!
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 870 bytes --]
^ permalink raw reply
* [PATCH v8 0/6] Add support for ZTE zx297520v3
From: Stefan Dösinger @ 2026-05-06 19:33 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger, Krzysztof Kozlowski
Hi,
This is a follow-up on my RFC patches from January [0] for ZTE's
zx297520v3 chipset. This chipset is popular in cheap LTE-to-wifi routers
sold in developing countries. My goal is to run OpenWRT on them. I made
more progress in more work on this SoC and it is time to get serious
about code review and upstreaming.
Since my version in January I managed to get more hardware running: SPI,
I2C, PMIC with real time clock and voltage regulators, Watchdog. LTE is
not working yet, but I am able to start the coprocessor that handles it
and talk to it via mailbox + shared memory. Wifi is working on a few
more devices. Since WiFi, USB and Ethernet are working, the devices can
have actual use with OpenWRT even without LTE.
Another hacker created a free software program to talk to the USB loader
[1] and boot U-Boot and Linux without modifying the on disk files. At
the moment it needs a proprietary blob, so my documentation is
emphasising booting with the on-device U-Boot.
This patchset here is mostly unmodified from the version I sent in
January. It is the bare minimum to get an interactive shell working on
the UART. Future patches can be found on my git repository [2] for those
curious to peek ahead. The first 30 patches are in reasonable shape, but
the further you go the more cleanup is necessary. I expect all of the
patches go require a few rounds of feedback though.
My plan for upstreaming is largly this:
1) This bare minimum boot patchset
2) Add clock and pinctrl drivers
3) Add standard hardware to the device tree
4) Add zx29 specific drivers one by one: Watchdog, spi, i2c, DMA, PMIC,
battery
5) SDIO backend for rtl8xxxu
6) rproc, mailbox and rpmsg
I am willing to maintain support for the SoC within reason. My patches
add myself as maintainer. This is a hobby project for me though, keep
that in mind if you want to ship a commercial product with these SoCs
and upstreaming Linux.
Cheers,
Stefan
0: https://lists.infradead.org/pipermail/linux-arm-kernel/2026-January/1099306.html
1: https://github.com/zx297520v3-mainline/zx297520v3-loader
2: https://gitlab.com/stefandoesinger/zx297520-kernel/
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
Changes in v8: A number of Sashiko suggestions:
Add new documentation files to the documentation index
Add new documentation directory to MAINTAINERS
Remove a redundant "if ARCH_ZTE"
Set ARM_PSCI_FW because ARM_GIC_V3 needs it
Use the correct UART01x_FR_BUSY flag in lldebug asm
Remove an accidentally duplicated label from the DTSI file, properly use
"arm,pl011", "arm,primecell" for all UARTs
Remove BINFMT_FLAT from defconfig. I have no idea how that got enabled.
Point to a sane (but not yet upstream) U-Boot that sets up the GIC
correctly for this board. Improve the provided example GIC setup code to
detect this for reusing one binary for both boot chains.
Changes in v7:
Fix line order in mach-zte/Kconfig
Use "zx297520v3 SoC" as the option name for CONFIG_SOC_ZX297520V3
Changes in v6:
Squashed DT commits into one
Removed for-now unused board DT bindings
Add "zte" to DT patch subject
Regenerate the defconfig with make savedefconfig
- Link to v5: https://lore.kernel.org/r/20260421-send-v5-0-ace038e63515@gmail.com
v5:
Spelling fixes
Renamed dlink-dwr-932m.dts to zx297520v3-dlink-dwr932m.dts
DT binding indentation fixes
Use a manufacturer 0x8b for the UART, fix patch prefix
Declare all UARTs, remove uart aliases for now
Consistent license declarations. I made every new file except the DT
binding GPL-2.0-only but I don't particularly mind GPL-2.0-or-later
either.
- Link to v4: https://lore.kernel.org/r/20260416-send-v4-0-e19d02b944ec@gmail.com
v4: rename zx29.yaml to zte.yaml and add board enums
v3: Remove [RFC] tag, add defconfig
v2: checkpatch.pl fixes
---
Stefan Dösinger (6):
dt-bindings: arm: zte: Add D-Link DWR932M board based on zx297520v3 SoC
ARM: zte: Add zx297520v3 platform support
ARM: zte: Add support for zx29 low level debug
amba/serial: amba-pl011: Bring back zx29 UART support
ARM: dts: zte: Add D-Link DWR-932M support
ARM: zte: defconfig: Add a zx29 defconfig file
Documentation/arch/arm/index.rst | 2 +
Documentation/arch/arm/zte/index.rst | 10 ++
Documentation/arch/arm/zte/zx297520v3.rst | 167 +++++++++++++++++++++
Documentation/devicetree/bindings/arm/zte.yaml | 26 ++++
MAINTAINERS | 8 +
arch/arm/Kconfig | 2 +
arch/arm/Kconfig.debug | 12 ++
arch/arm/Makefile | 1 +
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/zte/Makefile | 3 +
arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts | 22 +++
arch/arm/boot/dts/zte/zx297520v3.dtsi | 103 +++++++++++++
arch/arm/configs/zx29_defconfig | 53 +++++++
arch/arm/include/debug/pl01x.S | 9 ++
arch/arm/mach-zte/Kconfig | 29 ++++
arch/arm/mach-zte/Makefile | 2 +
arch/arm/mach-zte/zx297520v3.c | 16 ++
drivers/tty/serial/amba-pl011.c | 42 ++++++
18 files changed, 508 insertions(+)
---
base-commit: 028ef9c96e96197026887c0f092424679298aae8
change-id: 20260416-send-5c08e095e5c9
Best regards,
--
Stefan Dösinger <stefandoesinger@gmail.com>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox