Linux Serial subsystem development
 help / color / mirror / Atom feed
* [PATCH v4 1/2] serial: qcom-geni: trace: Add tracepoint support for Qualcomm GENI serial
From: Praveen Talari @ 2026-05-26 17:37 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Greg Kroah-Hartman, Jiri Slaby, konrad.dybcio
  Cc: Praveen Talari, linux-kernel, linux-trace-kernel, linux-arm-msm,
	linux-serial, mukesh.savaliya, aniket.randive, chandana.chiluveru
In-Reply-To: <20260526-add-tracepoints-for-qcom-geni-serial-v4-0-e94fbaec0232@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.

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Praveen Talari <praveen.talari@oss.qualcomm.com>
---
v2->v3:
- Removed \n from geni_serial_tx_data and geni_serial_rx_data events.
- Resolved aligment issues in geni_serial_data, geni_serial_tx_data and
  geni_serial_rx_data events.

v1->v2:
- Removed multiple TX/RX trace events, instead used
  DECLARE_EVENT_CLASS and DEFINE_EVENT.
---
 include/trace/events/qcom_geni_serial.h | 164 ++++++++++++++++++++++++++++++++
 1 file changed, 164 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..417ec01f9fc8
--- /dev/null
+++ b/include/trace/events/qcom_geni_serial.h
@@ -0,0 +1,164 @@
+/* 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)
+);
+
+DECLARE_EVENT_CLASS(geni_serial_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: len=%u data=%s",
+			      __get_str(name), __entry->len,
+			      __print_hex(__get_dynamic_array(data), __entry->len))
+);
+
+DEFINE_EVENT(geni_serial_data, geni_serial_tx_data,
+	     TP_PROTO(struct device *dev, const u8 *buf, unsigned int len),
+	     TP_ARGS(dev, buf, len)
+);
+
+DEFINE_EVENT(geni_serial_data, geni_serial_rx_data,
+	     TP_PROTO(struct device *dev, const u8 *buf, unsigned int len),
+	     TP_ARGS(dev, buf, 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 v4 2/2] serial: qcom-geni: Add tracepoints for Qualcomm GENI serial driver
From: Praveen Talari @ 2026-05-26 17:37 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Greg Kroah-Hartman, Jiri Slaby, konrad.dybcio
  Cc: Praveen Talari, linux-kernel, linux-trace-kernel, linux-arm-msm,
	linux-serial, mukesh.savaliya, aniket.randive, chandana.chiluveru
In-Reply-To: <20260526-add-tracepoints-for-qcom-geni-serial-v4-0-e94fbaec0232@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.

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Praveen Talari <praveen.talari@oss.qualcomm.com>
---
v2->v3:
- Updated commit text(removed example as it was available on cover
  letter).
---
 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 d81b539cff7f..4b62e58d4918 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>
@@ -226,7 +229,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;
@@ -236,6 +239,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;
 }
 
@@ -254,6 +259,8 @@ static void qcom_geni_serial_set_mctrl(struct uart_port *uport,
 	if (port->manual_flow && !(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)
@@ -684,6 +691,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);
@@ -910,8 +919,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,
@@ -1082,6 +1093,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);
@@ -1294,8 +1309,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, 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;
@@ -1455,6 +1470,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

* [PATCH v4 0/2] Add tracepoints support for Qualcomm GENI Serial drivers
From: Praveen Talari @ 2026-05-26 17:37 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Greg Kroah-Hartman, Jiri Slaby, konrad.dybcio
  Cc: Praveen Talari, linux-kernel, linux-trace-kernel, linux-arm-msm,
	linux-serial, mukesh.savaliya, aniket.randive, chandana.chiluveru

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>
---
Changes in v4:
- Rebased patch(02/02) on latest linux-next.
- Link to v3: https://lore.kernel.org/all/20260518-add-tracepoints-for-qcom-geni-serial-v3-0-b4addb151376@oss.qualcomm.com

Changes in v3:
- Removed \n from geni_serial_tx_data and geni_serial_rx_data events.
- Resolved aligment issues in geni_serial_data, geni_serial_tx_data and
  geni_serial_rx_data events.
- Link to v2: https://lore.kernel.org/r/20260512-add-tracepoints-for-qcom-geni-serial-v2-0-a5726421b3af@oss.qualcomm.com

Changes in v2:
- removed multiple trace events for TX/RX events, instead used
  DECLARE_EVENT_CLASS and DEFINE_EVENT.
- Link to v1: https://lore.kernel.org/r/20260506-add-tracepoints-for-qcom-geni-serial-v1-0-544b22612e08@oss.qualcomm.com

To: Steven Rostedt <rostedt@goodmis.org>
To: Masami Hiramatsu <mhiramat@kernel.org>
To: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: Jiri Slaby <jirislaby@kernel.org>
To: konrad.dybcio@oss.qualcomm.com
Cc: linux-kernel@vger.kernel.org
Cc: linux-trace-kernel@vger.kernel.org
Cc: linux-arm-msm@vger.kernel.org
Cc: linux-serial@vger.kernel.org
Cc: mukesh.savaliya@oss.qualcomm.com
Cc: aniket.randive@oss.qualcomm.com
Cc: chandana.chiluveru@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 | 164 ++++++++++++++++++++++++++++++++
 2 files changed, 187 insertions(+), 4 deletions(-)
---
base-commit: d387b06f7c15b4639244ad66b4b0900c6a02b430
change-id: 20260427-add-tracepoints-for-qcom-geni-serial-948777218b7b

Best regards,
--  
Praveen Talari <praveen.talari@oss.qualcomm.com>


^ permalink raw reply

* Re: [PATCH v3] serial: max310x: fix compile errors if CONFIG_SPI_MASTER is disabled
From: Randy Dunlap @ 2026-05-26 16:19 UTC (permalink / raw)
  To: Hugo Villeneuve
  Cc: Greg Kroah-Hartman, Jiri Slaby, Hugo Villeneuve,
	kernel test robot, linux-kernel, linux-serial
In-Reply-To: <20260526093410.6162be940a20372bf766db46@hugovil.com>



On 5/26/26 6:34 AM, Hugo Villeneuve wrote:
> On Mon, 25 May 2026 10:43:40 -0700
> Randy Dunlap <rdunlap@infradead.org> wrote:
> 
>>
>>
>> On 5/21/26 8:33 AM, Hugo Villeneuve wrote:
>>> From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
>>>
>>> Since commit 20ffe4b3330a8 ("serial: max310x: allow driver to be built with
>>> SPI or I2C"), if I2C is enabled and SPI_MASTER is disabled, we have these
>>> compile errors:
>>>
>>>   drivers/tty/serial/max310x.c: In function 'max310x_uart_init':
>>>   drivers/tty/serial/max310x.c: error: 'max310x_spi_driver' undeclared...
>>>   drivers/tty/serial/max310x.c: In function ‘max310x_uart_init’:
>>>   drivers/tty/serial/max310x.c: error: label ‘err_spi_register’
>>>   defined but not used...
>>>   drivers/tty/serial/max310x.c: error: ‘regcfg’ defined but not used
>>>
>>> Fix by properly encapsulating i2c/spi code/variables in their respective
>>> context with IS_ENABLED() macros for CONFIG_I2C and CONFIG_SPI_MASTER.
>>>
>>> Also fix link failure with SERIAL_MAX310X=y and I2C=m by modifying Kconfig
>>> depends.
>>>
>>> Fixes: 20ffe4b3330a8 ("serial: max310x: allow driver to be built with SPI or I2C")
>>> Reported-by: kernel test robot <lkp@intel.com>
>>> Closes: https://lore.kernel.org/oe-kbuild-all/202605121847.N9DVLNg2-lkp@intel.com/
>>> Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
>>> ---
>>> note: not Cc-ing stable as the commit is still in tty-next, and even if the
>>> errors originate from original commit that added I2C support, they were not
>>> trigerred because the driver could not be selected/compiled if
>>> CONFIG_SPI_MASTER was disabled.
>>>
>>> Changes for v3:
>>> - Fix link failure with SERIAL_MAX310X=y and I2C=m (Arnd Bergmann)
>>>
>>> Changes for v2:
>>> - replace #ifdef with #if IS_ENABLED() to suppoirt both built-in and modules
>>>   options
>>> ---
>>>  drivers/tty/serial/Kconfig   |  2 +-
>>>  drivers/tty/serial/max310x.c | 48 +++++++++++++++++++-----------------
>>>  2 files changed, 27 insertions(+), 23 deletions(-)
>>>
>>> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
>>> index f834e5d292fd7..4accbfa75074c 100644
>>> --- a/drivers/tty/serial/Kconfig
>>> +++ b/drivers/tty/serial/Kconfig
>>> @@ -321,7 +321,7 @@ config SERIAL_MAX3100
>>>  
>>>  config SERIAL_MAX310X
>>>  	tristate "MAX310X support"
>>> -	depends on SPI_MASTER || I2C
>>> +	depends on (SPI_MASTER && !I2C) || I2C
>>>  	select SERIAL_CORE
>>>  	select REGMAP_SPI if SPI_MASTER
>>>  	select REGMAP_I2C if I2C
>>
>> Other than preferring Arnd's Kconfig dependencies (easier to
>> read/understand IMO), this is all good.
>> Thanks.
> 
> Hi Randy,
> thank you for testing this.
> 
> I personnaly think both syntaxes are confusing :)
> 
> I have a long term goal of converting this driver to core and
> I2C/SPI parts eventually, like I did for the sc16is7xx...

Yes, I've noticed that some similar drivers are actually 2 drivers.

For the Kconfig, another option is:

	depends on SPI_MASTER || I2C
	depends on I2C if I2C	# limits this config to m if I2C=m

(not tested :)
but it's not necessarily better, just different.

-- 
~Randy


^ permalink raw reply

* RE: [PATCH RFT] tty: serial: fsl_lpuart: Add register dump
From: Sherry Sun @ 2026-05-26 15:21 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman, Jiri Slaby
  Cc: Christophe JAILLET, Ingo Molnar, Frank Li,
	linux-serial@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <20260526140113.50372-1-wahrenst@gmx.net>

> Subject: [PATCH RFT] tty: serial: fsl_lpuart: Add register dump
> 
> Dumping the registers from userspace for debug purposes isn't trivial,
> because runtime PM can gate the required clocks and any read access to
> these registers would result in a lockup.
> 
> So implement a register dump via debugfs, which deals with the runtime PM.

No need, you can disable runtime pm from user space before dump the registers.
For example: echo on > /sys/bus/platform/devices/29860000.serial/power/control

Best Regards
Sherry
> 
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
> ---
> 
> Hi, I only have access to a board (i.MX93) with 32 bit registers, so it would be
> great if someone could test it for 8 bit registers.
> 
> Thanks
> 
>  drivers/tty/serial/fsl_lpuart.c | 69 +++++++++++++++++++++++++++++++++
>  1 file changed, 69 insertions(+)
> 
> diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index
> 1bd7ec9c81ea..7e4b3e59414a 100644
> --- a/drivers/tty/serial/fsl_lpuart.c
> +++ b/drivers/tty/serial/fsl_lpuart.c
> @@ -10,6 +10,7 @@
>  #include <linux/circ_buf.h>
>  #include <linux/clk.h>
>  #include <linux/console.h>
> +#include <linux/debugfs.h>
>  #include <linux/delay.h>
>  #include <linux/dma-mapping.h>
>  #include <linux/dmaengine.h>
> @@ -23,6 +24,7 @@
>  #include <linux/pinctrl/consumer.h>
>  #include <linux/platform_device.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/seq_file.h>
>  #include <linux/serial_core.h>
>  #include <linux/slab.h>
>  #include <linux/tty_flip.h>
> @@ -291,6 +293,8 @@ struct lpuart_port {
>  	bool			is_cs7; /* Set to true when character size is 7
> */
>  					/* and the parity is enabled
> 	*/
>  	bool			dma_idle_int;
> +
> +	struct dentry		*debugfs_dir;
>  };
> 
>  struct lpuart_soc_data {
> @@ -1031,6 +1035,7 @@ static void lpuart32_rxint(struct lpuart_port *sport)
>  	}
> 
>  out:
> +
>  	uart_unlock_and_check_sysrq(&sport->port);
> 
>  	tty_flip_buffer_push(port);
> @@ -2860,6 +2865,67 @@ static int lpuart_global_reset(struct lpuart_port
> *sport)
>  	return 0;
>  }
> 
> +#ifdef CONFIG_DEBUG_FS
> +
> +#define dump_register_hex(_seq, _reg, _sport) \ seq_printf((_seq),
> +"%-12s: 0x%02x\n", #_reg, readb((_sport)->port.membase + (_reg)))
> +
> +#define dump_register32_hex(_seq, _reg, _sport) \ seq_printf((_seq),
> +"%-12s: 0x%08x\n", #_reg, lpuart32_read(&(_sport)->port, _reg))
> +
> +static int regs_show(struct seq_file *s, void *p) {
> +	struct lpuart_port *sport = s->private;
> +
> +	pm_runtime_get_sync(sport->port.dev);
> +
> +	if (lpuart_is_32(sport)) {
> +		dump_register32_hex(s, UARTBAUD, sport);
> +		dump_register32_hex(s, UARTSTAT, sport);
> +		dump_register32_hex(s, UARTCTRL, sport);
> +		dump_register32_hex(s, UARTMATCH, sport);
> +		dump_register32_hex(s, UARTMODIR, sport);
> +		dump_register32_hex(s, UARTFIFO, sport);
> +		dump_register32_hex(s, UARTWATER, sport);
> +	} else {
> +		dump_register_hex(s, UARTBDH, sport);
> +		dump_register_hex(s, UARTBDL, sport);
> +		dump_register_hex(s, UARTCR1, sport);
> +		dump_register_hex(s, UARTCR2, sport);
> +		dump_register_hex(s, UARTSR1, sport);
> +		dump_register_hex(s, UARTCR3, sport);
> +		dump_register_hex(s, UARTDR, sport);
> +		dump_register_hex(s, UARTCR4, sport);
> +		dump_register_hex(s, UARTCR5, sport);
> +		dump_register_hex(s, UARTMODEM, sport);
> +		dump_register_hex(s, UARTPFIFO, sport);
> +		dump_register_hex(s, UARTCFIFO, sport);
> +		dump_register_hex(s, UARTSFIFO, sport);
> +		dump_register_hex(s, UARTTWFIFO, sport);
> +		dump_register_hex(s, UARTTCFIFO, sport);
> +		dump_register_hex(s, UARTRWFIFO, sport);
> +	}
> +
> +	pm_runtime_mark_last_busy(sport->port.dev);
> +	pm_runtime_put_autosuspend(sport->port.dev);
> +
> +	return 0;
> +}
> +
> +DEFINE_SHOW_ATTRIBUTE(regs);
> +
> +static void lpuart_init_debugfs(struct lpuart_port *sport) {
> +	sport->debugfs_dir = debugfs_create_dir(dev_name(sport-
> >port.dev),
> +						NULL);
> +
> +	debugfs_create_file("regs", 0400, sport->debugfs_dir, sport,
> +&regs_fops); }
> +
> +#else
> +static inline void lpuart_init_debugfs(struct lpuart_port *sport) {}
> +#endif
> +
>  static int lpuart_probe(struct platform_device *pdev)  {
>  	const struct lpuart_soc_data *sdata =
> of_device_get_match_data(&pdev->dev);
> @@ -2969,6 +3035,8 @@ static int lpuart_probe(struct platform_device
> *pdev)
>  	if (ret)
>  		goto failed_irq_request;
> 
> +	lpuart_init_debugfs(sport);
> +
>  	return 0;
> 
>  failed_irq_request:
> @@ -2987,6 +3055,7 @@ static void lpuart_remove(struct platform_device
> *pdev)  {
>  	struct lpuart_port *sport = platform_get_drvdata(pdev);
> 
> +	debugfs_remove_recursive(sport->debugfs_dir);
>  	uart_remove_one_port(&lpuart_reg, &sport->port);
> 
>  	lpuart_disable_clks(sport);
> --
> 2.43.0


^ permalink raw reply

* Re: [PATCH v3 00/10] MIPS: DEC: Fix serial device regressions + RTC cleanup
From: Maciej W. Rozycki @ 2026-05-26 15:08 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Greg Kroah-Hartman, Jiri Slaby, linux-mips, linux-serial
In-Reply-To: <ahWyuPUMe7XQ9fZp@alpha.franken.de>

On Tue, 26 May 2026, Thomas Bogendoerfer wrote:

> >  Will you be able to get these two changes merged sometime soon now that 
> > Greg has queued changes 03/10 through 09/10, so that these prerequisites 
> > land ahead and there's no 64-bit regression in mainline?
> 
> I've applied 01/10 and 02/10. 10/10 doesn't apply to my tree, because it
> depends on the platform.c changes from dz/zs driver change not yet present
> in my tree. So either Greg takes it via his tree or I'll pick it up in
> a second pull request during the merge window

 Fine with me either way, thanks for taking care of this stuff!  I'm glad 
I was able to find time and momentum to get these issues finally sorted, 
as I was aware of them for quite a while now, but there's so much to pick 
from.  More to come.

  Maciej

^ permalink raw reply

* Re: [PATCH RFC] serial: core: Don't clobber the baud rate on hangup via B0
From: Maciej W. Rozycki @ 2026-05-26 15:03 UTC (permalink / raw)
  To: Hugo Villeneuve
  Cc: Theodore Tso, Greg Kroah-Hartman, Jiri Slaby, Randy Dunlap,
	Dr. David Alan Gilbert, Krzysztof Kozlowski, Gerhard Engleder,
	Jiayuan Chen, Joseph Tilahun, linux-serial, linux-kernel
In-Reply-To: <20260526102915.c0dc51579182c0aeb1390bc4@hugovil.com>

On Tue, 26 May 2026, Hugo Villeneuve wrote:

> Please rebase your patch on greg's tty-next branch, because there have
> been some changes by me lately [1] to uart_get_baud_rate() and your
> patch will not apply.

 Sure, if this does get beyond RFC.  Thanks for the heads-up!

  Maciej

^ permalink raw reply

* Re: [PATCH v3 02/10] MIPS: DEC: Prevent initial console buffer from landing in XKPHYS
From: Thomas Bogendoerfer @ 2026-05-26 14:46 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Greg Kroah-Hartman, Jiri Slaby, linux-mips, linux-serial
In-Reply-To: <alpine.DEB.2.21.2605062253010.46195@angie.orcam.me.uk>

On Wed, May 06, 2026 at 11:42:27PM +0100, Maciej W. Rozycki wrote:
> In 64-bit configurations calling the initial console output handler from 
> a kernel thread other than the initial one will result in a situation 
> where the stack has been placed in the XKPHYS 64-bit memory segment and 
> consequently so has been the buffer allocated there that is used as the 
> argument corresponding to the `%s' output conversion specifier for the 
> firmware's printf() entry point.
> 
> This 64-bit address will then be truncated by 32-bit firmware, resulting 
> in an attempt to access the wrong memory location, which in turn will 
> cause all kinds of unpredictable behaviour, such as a kernel crash:
> 
>   Console: colour dummy device 160x64
>   Calibrating delay loop... 49.36 BogoMIPS (lpj=192512)
>   pid_max: default: 32768 minimum: 301
>   CPU 0 Unable to handle kernel paging request at virtual address 000000000203bd00, epc == ffffffffbfc08364, ra == ffffffffbfc08800
>   Oops[#1]:
>   CPU: 0 PID: 0 Comm: swapper Not tainted 5.18.0-rc2-00254-gfb649bda6f56-dirty #121
>   $ 0   : 0000000000000000 0000000000000001 0000000000000023 ffffffff80684ba0
>   $ 4   : 000000000203bd00 ffffffffbfc0f3b4 ffffffffffffffff 0000000000000073
>   $ 8   : 0a303d7469000000 0000000000000000 0000000000000073 ffffffffbfc0f473
>   $12   : 0000000000000002 0000000000000000 ffffffff80684c1c 0000000000000000
>   $16   : 0000000000000000 ffffffff80596dc9 0000000000000000 ffffffffbfc09240
>   $20   : ffffffff80684c40 ffffffffbfc0f400 000000000000002d 000000000000002b
>   $24   : ffffffffffffffbf 000000000203bd00                                  
>   $28   : ffffffff805f0000 ffffffff80684b58 0000000000000030 ffffffffbfc08800
>   Hi    : 0000000000000000
>   Lo    : 0000000000000aa8
>   epc   : ffffffffbfc08364 0xffffffffbfc08364
>   ra    : ffffffffbfc08800 0xffffffffbfc08800
>   Status: 140120e2        KX SX UX KERNEL EXL 
>   Cause : 00000008 (ExcCode 02)
>   BadVA : 000000000203bd00
>   PrId  : 00000430 (R4000SC)
>   Modules linked in:
>   Process swapper (pid: 0, threadinfo=(____ptrval____), task=(____ptrval____), tls=0000000000000000)
>   Stack : 0000000000000000 0000000000000000 0000000000000000 0000004d0000004d
>           80684cc0806a2a40 80596dc80000004d 8061000000000000 bfc0850c80684c38
>           0000000000000000 000000000203bd00 0000000000000000 0000000000000000
>           0000000000000000 00000000bfc0f3b4 0000000000000000 0000000000000000
>           0000000000000000 0000000000000000 0000000000000000 0000000000000000
>           0000000000000000 0000000000000000 0000000000000000 0000000000000000
>           0000002500000000 0000000000000000 0000000000000000 802c1a7400000000
>           0203bd0080596dc8 0203bd4d69000000 6c61632000000018 5f746567646e6172
>           6c616320625f6d6f 5f736e5f6d6f7266 206361323778302b 303d74696e726320
>           806a0a38806b0000 806a0a38806b0000 00000000806b0000 80683c58806b0000
>           ...
>   Call Trace:
>   
>   
>   Code: a082ffff  03e00008  00601021 <80820000> 00001821  10400005  24840001  80820000  24630001 
>   
>   ---[ end trace 0000000000000000 ]---
>   Kernel panic - not syncing: Fatal exception in interrupt
>   
>   KN04 V2.1k    (PC: 0xa0026768, SP: 0x806848e8)
>   >>
> 
> In this case the pointer in $4 was truncated from 0x980000000203bd00 to 
> 0x000000000203bd00.
> 
> This may happen when no final console driver has been enabled in the 
> configuration and consequently the initial console continues being used 
> late into bootstrap or with an upcoming change that will switch the zs 
> driver to use a platform device, which in turn will make the console 
> handover happen only after other kernel threads have already been 
> started.
> 
> Fix the issue by making the buffer static and initdata, and therefore 
> placed in the CKSEG0 32-bit compatibility segment, observing that the 
> console output handler is called with the console lock held, implying 
> no need for this code to be reentrant.  Add an assertion to verify the 
> buffer actually has been placed in a compatibility segment.
> 
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
> Cc: stable@vger.kernel.org # v2.6.12+
> ---
> Changes from v2, 
> <https://lore.kernel.org/r/alpine.DEB.2.21.2605010059310.38805@angie.orcam.me.uk/>:
> 
> - Cast `buf' to `long' before casting to `int', fixing:
> 
>   In file included from ./include/linux/bug.h:5,
>                    from arch/mips/dec/prom/console.c:7:
>   arch/mips/dec/prom/console.c: In function 'prom_console_write':
>   arch/mips/dec/prom/console.c:21:29: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
>      21 |         BUG_ON((long)buf != (int)buf);
>         |                             ^
>   ./arch/mips/include/asm/bug.h:34:44: note: in definition of macro 'BUG_ON'
>      34 | #define BUG_ON(C) __BUG_ON((unsigned long)(C))
>         |                                            ^
> 
> New change in v2.
> ---
>  arch/mips/dec/prom/console.c |    7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)

applied to mips-next

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

^ permalink raw reply

* Re: [PATCH v3 01/10] MIPS: DEC: Ensure 32-bit stack location for o32 prom_printf()
From: Thomas Bogendoerfer @ 2026-05-26 14:45 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Greg Kroah-Hartman, Jiri Slaby, linux-mips, linux-serial
In-Reply-To: <alpine.DEB.2.21.2605062249160.46195@angie.orcam.me.uk>

On Wed, May 06, 2026 at 11:42:23PM +0100, Maciej W. Rozycki wrote:
> In 64-bit configurations calling any firmware entry points from a kernel 
> thread other than the initial one will result in a situation where the 
> stack has been placed in the XKPHYS 64-bit memory segment.
> 
> Consequently the stack pointer is no longer a 32-bit value and when the 
> 32-bit firmware code called uses 32-bit ALU operations to manipulate the 
> stack pointer, the calculated result is incorrect (in fact in the 64-bit 
> MIPS ISA almost all 32-bit ALU operations will produce an unpredictable 
> result when executed on 64-bit data) and control goes astray.
> 
> This may happen when no final console driver has been enabled in the
> configuration and consequently the initial console continues being used
> late into bootstrap, or with an upcoming change that will switch the zs
> driver to use a platform device, which in turn will make the console
> handover happen only after other kernel threads have already been
> started, and the kernel will hang at:
> 
>   pid_max: default: 32768 minimum: 301
> 
> or somewhat later, but always before:
> 
>   cblist_init_generic: Setting adjustable number of callback queues.
> 
> has been printed.
> 
> It seems that only the prom_printf() entry point is affected.  Of all 
> the other entry points wired only rex_slot_address() and rex_gettcinfo() 
> are called from a kernel thread other than the initial one, specifically 
> kernel_init(), and they are leaf functions that do no business with the 
> stack, having worked with no issue ever since 64-bit support was added 
> for the platform back in 2002.
> 
> To address this issue then, arrange for the stack to be switched in the 
> o32 wrapper as required for prom_printf() only, by supplying call_o32() 
> with a pointer to a chunk of initdata space, which is placed in the 
> CKSEG0 32-bit compatibility segment, observing that prom_printf() is 
> only called from console output handler and therefore with the console 
> lock held, implying no need for this code to be reentrant.
> 
> Other firmware entry points may be called with interrupts enabled and no 
> lock held, and may therefore require that call_o32() be reentrant.  They 
> trigger no issue at this point and "if it ain't broke, don't fix it," so 
> just leave them alone.
> 
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
> Cc: stable@vger.kernel.org # v2.6.12+
> ---
> No change from v2, 
> <https://lore.kernel.org/r/alpine.DEB.2.21.2605010132340.38805@angie.orcam.me.uk/>.
> 
> New change in v2.
> ---
>  arch/mips/dec/prom/init.c        |    6 +++++-
>  arch/mips/include/asm/dec/prom.h |   15 +++++++++++++--
>  2 files changed, 18 insertions(+), 3 deletions(-)

applied to mips-next

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

^ permalink raw reply

* Re: [PATCH v3 10/10] MIPS: DEC: Ensure RTC platform device deregistration upon failure
From: Thomas Bogendoerfer @ 2026-05-26 14:49 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Greg Kroah-Hartman, Jiri Slaby, linux-mips, linux-serial
In-Reply-To: <alpine.DEB.2.21.2605062333190.46195@angie.orcam.me.uk>

On Wed, May 06, 2026 at 11:43:00PM +0100, Maciej W. Rozycki wrote:
> Switch RTC platform device registration from platform_device_register() 
> to platform_add_devices() so as to make sure any failure will result in 
> automatic device unregistration.
> 
> Fixes: fae67ad43114 ("arch/mips/dec: switch DECstation systems to rtc-cmos")
> Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
> ---
> Change from v2,
> <https://lore.kernel.org/r/alpine.DEB.2.21.2605012105320.11074@angie.orcam.me.uk/>:
> 
> - Fix a minor style issue in the commit description.
> 
> No change from v1 (8/8),
> <https://lore.kernel.org/r/alpine.DEB.2.21.2604110042130.29980@angie.orcam.me.uk/>.
> ---
>  arch/mips/dec/platform.c |    6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> linux-mips-dec-platform-rtc-unregister.diff
> Index: linux-macro/arch/mips/dec/platform.c
> ===================================================================
> --- linux-macro.orig/arch/mips/dec/platform.c
> +++ linux-macro/arch/mips/dec/platform.c
> @@ -38,6 +38,10 @@ static struct platform_device dec_rtc_de
>  	.num_resources = ARRAY_SIZE(dec_rtc_resources),
>  };
>  
> +static struct platform_device *dec_rtc_devices[] __initdata = {
> +	&dec_rtc_device,
> +};
> +
>  static struct resource dec_dz_resources[] = {
>  	{ .name = "dz", .flags = IORESOURCE_MEM, },
>  	{ .name = "dz", .flags = IORESOURCE_IRQ, },
> @@ -137,7 +141,7 @@ static int __init dec_add_devices(void)
>  	}
>  	num_zs = i;
>  
> -	ret1 = platform_device_register(&dec_rtc_device);
> +	ret1 = platform_add_devices(dec_rtc_devices, 1);
>  	ret2 = IS_ENABLED(CONFIG_32BIT) ?
>  	       platform_add_devices(dec_dz_devices, num_dz) : 0;
>  	ret3 = platform_add_devices(dec_zs_devices, num_zs);

Acked-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>

Greg,

since this only applies with the DZ/ZS changes, could you take this patch
via the serial tree ?

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

^ permalink raw reply

* Re: [PATCH v3 00/10] MIPS: DEC: Fix serial device regressions + RTC cleanup
From: Thomas Bogendoerfer @ 2026-05-26 14:48 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Greg Kroah-Hartman, Jiri Slaby, linux-mips, linux-serial
In-Reply-To: <alpine.DEB.2.21.2605221609220.1450@angie.orcam.me.uk>

On Fri, May 22, 2026 at 04:15:06PM +0100, Maciej W. Rozycki wrote:
> Hi Thomas,
> 
> On Wed, 6 May 2026, Maciej W. Rozycki wrote:
> 
> >  Two extra introductory changes, 01/10 and 02/10 have now been added to 
> > platform code.  No modification has been made to original changes.  The 
> > original description follows, updated for patch renumbering.
> 
>  Will you be able to get these two changes merged sometime soon now that 
> Greg has queued changes 03/10 through 09/10, so that these prerequisites 
> land ahead and there's no 64-bit regression in mainline?

I've applied 01/10 and 02/10. 10/10 doesn't apply to my tree, because it
depends on the platform.c changes from dz/zs driver change not yet present
in my tree. So either Greg takes it via his tree or I'll pick it up in
a second pull request during the merge window

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

^ permalink raw reply

* Re: [PATCH RFC] serial: core: Don't clobber the baud rate on hangup via B0
From: Hugo Villeneuve @ 2026-05-26 14:29 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Theodore Tso, Greg Kroah-Hartman, Jiri Slaby, Randy Dunlap,
	Dr. David Alan Gilbert, Krzysztof Kozlowski, Gerhard Engleder,
	Jiayuan Chen, Joseph Tilahun, linux-serial, linux-kernel
In-Reply-To: <alpine.DEB.2.21.2605242242330.1450@angie.orcam.me.uk>

Hi Maciej,

On Mon, 25 May 2026 00:14:03 +0100 (BST)
"Maciej W. Rozycki" <macro@orcam.me.uk> wrote:

> Requesting hangup via the B0 baud rate has this nasty side effect of 
> clobbering the previously set rate for the port unless it happens to be 
> 9600bps.  Consequently if there's a consumer still active at the other 
> end, then it receives garbled data from any other producers outputting 
> messages to the port, such as init(8) or the kernel console.
> 
> There doesn't appear to be any particular reason for this clobbering 
> other than that we have been doing it since 2.1.131, so take a saner 
> approach and try to retain the old baud rate where available before 
> resorting to 9600bps.
> 
> Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
> ---
> Ted,
> 
>  This code ultimately evolved from a patch of yours[1], so would you be 
> able by any chance to recreate your rationale beyond resetting the baud 
> rate to 9600bps rather than just keeping the old one for B0?
> 
>  Otherwise, does anyone know or can come up with any actual use case for 
> this baud rate setting?  There seems no sensible way to restore the baud 
> rate required by init(8) and the kernel console other than by hand, while 
> I can't see a way for software that actually issued a hangup request via 
> the B0 artificial baud rate to withdraw the request other than by choosing 
> another explicit baud rate.  So there appears to me to be no usable way 
> there of relying on the implicit 9600bps baud rate set via the B0 baud 
> rate.
> 
>  Have I missed anything?
> 
>  I have dug into this having been irritated by the occasional clobbering 
> of init(8)/console output observed and now finding a reproducible way to 
> clobber the port in the course of working on a recent set of changes for 
> the sb1250-duart driver.  This change has made messages get through with 
> no damage.  Many of my systems in the lab actually use the baud rate of 
> 9600bps, which covers the issue, but the CFE firmware sets the baud rate 
> to 115200bps for systems that use the sb1250-duart driver.
> 
>   Maciej
> 
> References:
> 
> [1] "Was: patch to drivers/char/serial.c to fix kernel lock-up", 
>     <https://lkml.org/lkml/1998/12/5/126>
> ---
>  drivers/tty/serial/serial_core.c |    6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> linux-serial-uart-get-baud-rate-hup.diff
> Index: linux-macro/drivers/tty/serial/serial_core.c
> ===================================================================
> --- linux-macro.orig/drivers/tty/serial/serial_core.c
> +++ linux-macro/drivers/tty/serial/serial_core.c
> @@ -461,8 +461,8 @@ EXPORT_SYMBOL(uart_update_timeout);
>   * @max: maximum acceptable baud rate
>   *
>   * Decode the termios structure into a numeric baud rate, taking account of the
> - * magic 38400 baud rate (with spd_* flags), and mapping the %B0 rate to 9600
> - * baud.
> + * magic 38400 baud rate (with spd_* flags), and mapping the %B0 rate to the
> + * rate provided by the @old termios setting if available, otherwise 9600 baud.
>   *
>   * If the new baud rate is invalid, try the @old termios setting. If it's still
>   * invalid, we try 9600 baud. If that is also invalid 0 is returned.
> @@ -516,7 +516,7 @@ uart_get_baud_rate(struct uart_port *por
>  		 */
>  		if (baud == 0) {
>  			hung_up = 1;
> -			baud = 9600;
> +			baud = old ? tty_termios_baud_rate(old) : 9600;
>  		}

Please rebase your patch on greg's tty-next branch, because there have
been some changes by me lately [1] to uart_get_baud_rate() and your
patch will not apply.

Hugo.

[1] https://lore.kernel.org/all/20260410152022.2146488-1-hugo@hugovil.com/raw


>  
>  		if (baud >= min && baud <= max)
> 


-- 
Hugo Villeneuve

^ permalink raw reply

* [PATCH RFT] tty: serial: fsl_lpuart: Add register dump
From: Stefan Wahren @ 2026-05-26 14:01 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby, Sherry Sun
  Cc: Christophe JAILLET, Ingo Molnar, Frank Li, linux-serial,
	linux-arm-kernel, Stefan Wahren

Dumping the registers from userspace for debug purposes isn't trivial,
because runtime PM can gate the required clocks and any read access
to these registers would result in a lockup.

So implement a register dump via debugfs, which deals with the
runtime PM.

Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---

Hi, I only have access to a board (i.MX93) with 32 bit registers, so it
would be great if someone could test it for 8 bit registers.

Thanks

 drivers/tty/serial/fsl_lpuart.c | 69 +++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 1bd7ec9c81ea..7e4b3e59414a 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -10,6 +10,7 @@
 #include <linux/circ_buf.h>
 #include <linux/clk.h>
 #include <linux/console.h>
+#include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
@@ -23,6 +24,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/seq_file.h>
 #include <linux/serial_core.h>
 #include <linux/slab.h>
 #include <linux/tty_flip.h>
@@ -291,6 +293,8 @@ struct lpuart_port {
 	bool			is_cs7; /* Set to true when character size is 7 */
 					/* and the parity is enabled		*/
 	bool			dma_idle_int;
+
+	struct dentry		*debugfs_dir;
 };
 
 struct lpuart_soc_data {
@@ -1031,6 +1035,7 @@ static void lpuart32_rxint(struct lpuart_port *sport)
 	}
 
 out:
+
 	uart_unlock_and_check_sysrq(&sport->port);
 
 	tty_flip_buffer_push(port);
@@ -2860,6 +2865,67 @@ static int lpuart_global_reset(struct lpuart_port *sport)
 	return 0;
 }
 
+#ifdef CONFIG_DEBUG_FS
+
+#define dump_register_hex(_seq, _reg, _sport) \
+seq_printf((_seq), "%-12s: 0x%02x\n", #_reg, readb((_sport)->port.membase + (_reg)))
+
+#define dump_register32_hex(_seq, _reg, _sport) \
+seq_printf((_seq), "%-12s: 0x%08x\n", #_reg, lpuart32_read(&(_sport)->port, _reg))
+
+static int regs_show(struct seq_file *s, void *p)
+{
+	struct lpuart_port *sport = s->private;
+
+	pm_runtime_get_sync(sport->port.dev);
+
+	if (lpuart_is_32(sport)) {
+		dump_register32_hex(s, UARTBAUD, sport);
+		dump_register32_hex(s, UARTSTAT, sport);
+		dump_register32_hex(s, UARTCTRL, sport);
+		dump_register32_hex(s, UARTMATCH, sport);
+		dump_register32_hex(s, UARTMODIR, sport);
+		dump_register32_hex(s, UARTFIFO, sport);
+		dump_register32_hex(s, UARTWATER, sport);
+	} else {
+		dump_register_hex(s, UARTBDH, sport);
+		dump_register_hex(s, UARTBDL, sport);
+		dump_register_hex(s, UARTCR1, sport);
+		dump_register_hex(s, UARTCR2, sport);
+		dump_register_hex(s, UARTSR1, sport);
+		dump_register_hex(s, UARTCR3, sport);
+		dump_register_hex(s, UARTDR, sport);
+		dump_register_hex(s, UARTCR4, sport);
+		dump_register_hex(s, UARTCR5, sport);
+		dump_register_hex(s, UARTMODEM, sport);
+		dump_register_hex(s, UARTPFIFO, sport);
+		dump_register_hex(s, UARTCFIFO, sport);
+		dump_register_hex(s, UARTSFIFO, sport);
+		dump_register_hex(s, UARTTWFIFO, sport);
+		dump_register_hex(s, UARTTCFIFO, sport);
+		dump_register_hex(s, UARTRWFIFO, sport);
+	}
+
+	pm_runtime_mark_last_busy(sport->port.dev);
+	pm_runtime_put_autosuspend(sport->port.dev);
+
+	return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(regs);
+
+static void lpuart_init_debugfs(struct lpuart_port *sport)
+{
+	sport->debugfs_dir = debugfs_create_dir(dev_name(sport->port.dev),
+						NULL);
+
+	debugfs_create_file("regs", 0400, sport->debugfs_dir, sport, &regs_fops);
+}
+
+#else
+static inline void lpuart_init_debugfs(struct lpuart_port *sport) {}
+#endif
+
 static int lpuart_probe(struct platform_device *pdev)
 {
 	const struct lpuart_soc_data *sdata = of_device_get_match_data(&pdev->dev);
@@ -2969,6 +3035,8 @@ static int lpuart_probe(struct platform_device *pdev)
 	if (ret)
 		goto failed_irq_request;
 
+	lpuart_init_debugfs(sport);
+
 	return 0;
 
 failed_irq_request:
@@ -2987,6 +3055,7 @@ static void lpuart_remove(struct platform_device *pdev)
 {
 	struct lpuart_port *sport = platform_get_drvdata(pdev);
 
+	debugfs_remove_recursive(sport->debugfs_dir);
 	uart_remove_one_port(&lpuart_reg, &sport->port);
 
 	lpuart_disable_clks(sport);
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v3] serial: max310x: fix compile errors if CONFIG_SPI_MASTER is disabled
From: Hugo Villeneuve @ 2026-05-26 13:34 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Greg Kroah-Hartman, Jiri Slaby, Hugo Villeneuve,
	kernel test robot, linux-kernel, linux-serial
In-Reply-To: <48b0e694-e75c-4d0a-8698-b0848ccaefeb@infradead.org>

On Mon, 25 May 2026 10:43:40 -0700
Randy Dunlap <rdunlap@infradead.org> wrote:

> 
> 
> On 5/21/26 8:33 AM, Hugo Villeneuve wrote:
> > From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> > 
> > Since commit 20ffe4b3330a8 ("serial: max310x: allow driver to be built with
> > SPI or I2C"), if I2C is enabled and SPI_MASTER is disabled, we have these
> > compile errors:
> > 
> >   drivers/tty/serial/max310x.c: In function 'max310x_uart_init':
> >   drivers/tty/serial/max310x.c: error: 'max310x_spi_driver' undeclared...
> >   drivers/tty/serial/max310x.c: In function ‘max310x_uart_init’:
> >   drivers/tty/serial/max310x.c: error: label ‘err_spi_register’
> >   defined but not used...
> >   drivers/tty/serial/max310x.c: error: ‘regcfg’ defined but not used
> > 
> > Fix by properly encapsulating i2c/spi code/variables in their respective
> > context with IS_ENABLED() macros for CONFIG_I2C and CONFIG_SPI_MASTER.
> > 
> > Also fix link failure with SERIAL_MAX310X=y and I2C=m by modifying Kconfig
> > depends.
> > 
> > Fixes: 20ffe4b3330a8 ("serial: max310x: allow driver to be built with SPI or I2C")
> > Reported-by: kernel test robot <lkp@intel.com>
> > Closes: https://lore.kernel.org/oe-kbuild-all/202605121847.N9DVLNg2-lkp@intel.com/
> > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> > ---
> > note: not Cc-ing stable as the commit is still in tty-next, and even if the
> > errors originate from original commit that added I2C support, they were not
> > trigerred because the driver could not be selected/compiled if
> > CONFIG_SPI_MASTER was disabled.
> > 
> > Changes for v3:
> > - Fix link failure with SERIAL_MAX310X=y and I2C=m (Arnd Bergmann)
> > 
> > Changes for v2:
> > - replace #ifdef with #if IS_ENABLED() to suppoirt both built-in and modules
> >   options
> > ---
> >  drivers/tty/serial/Kconfig   |  2 +-
> >  drivers/tty/serial/max310x.c | 48 +++++++++++++++++++-----------------
> >  2 files changed, 27 insertions(+), 23 deletions(-)
> > 
> > diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> > index f834e5d292fd7..4accbfa75074c 100644
> > --- a/drivers/tty/serial/Kconfig
> > +++ b/drivers/tty/serial/Kconfig
> > @@ -321,7 +321,7 @@ config SERIAL_MAX3100
> >  
> >  config SERIAL_MAX310X
> >  	tristate "MAX310X support"
> > -	depends on SPI_MASTER || I2C
> > +	depends on (SPI_MASTER && !I2C) || I2C
> >  	select SERIAL_CORE
> >  	select REGMAP_SPI if SPI_MASTER
> >  	select REGMAP_I2C if I2C
> 
> Other than preferring Arnd's Kconfig dependencies (easier to
> read/understand IMO), this is all good.
> Thanks.

Hi Randy,
thank you for testing this.

I personnaly think both syntaxes are confusing :)

I have a long term goal of converting this driver to core and
I2C/SPI parts eventually, like I did for the sc16is7xx...

Hugo.


> 
> Acked-by: Randy Dunlap <rdunlap@infradead.org>
> Tested-by: Randy Dunlap <rdunlap@infradead.org> # build-tested
> 
> -- 
> ~Randy

^ permalink raw reply

* [PATCH tty] tty: n_gsm: fix use-after-free in gsm_queue vs gsm_cleanup_mux race
From: Zhenghang Xiao @ 2026-05-26 10:29 UTC (permalink / raw)
  To: gregkh, jirislaby; +Cc: linux-serial, Zhenghang Xiao

gsm_queue() reads gsm->dlci[address] into a local pointer in the
flush_to_ldisc workqueue without any lock. Concurrently,
gsm_cleanup_mux() (triggered by GSMIOC_SETCONF ioctl) frees DLCIs under
gsm->mutex — which the receive path never holds. The cached pointer in
gsm_queue() becomes dangling, and the subsequent dlci->data() call
dereferences freed memory.

Fix this by:
1. Checking gsm->dead at the start of gsmld_receive_buf() to reject
   frame processing after cleanup has begun.
2. Moving tty_ldisc_flush() before the DLCI release loop in
   gsm_cleanup_mux(). tty_ldisc_flush() acquires the tty buffer lock
   (buf->lock), which serializes against any in-flight flush_to_ldisc
   work. After it returns, in-flight receive processing has completed,
   and subsequent calls see gsm->dead and return early.

Fixes: e1eaea46bb40 ("tty: n_gsm line discipline")
Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
---
 drivers/tty/n_gsm.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index c13e050de83b..8322fffbaeba 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -3156,12 +3156,18 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
 		gsm_unregister_devices(gsm_tty_driver, gsm->num);
 		gsm->has_devices = false;
 	}
+	/*
+	 * Flush the ldisc before releasing DLCIs. tty_ldisc_flush() waits
+	 * for any in-flight flush_to_ldisc work to complete via buf->lock,
+	 * and the gsm->dead check added to gsmld_receive_buf() rejects any
+	 * future receive processing. This ensures gsm_queue() cannot access
+	 * a DLCI being freed.
+	 */
+	tty_ldisc_flush(gsm->tty);
 	for (i = NUM_DLCI - 1; i >= 0; i--)
 		if (gsm->dlci[i])
 			gsm_dlci_release(gsm->dlci[i]);
 	mutex_unlock(&gsm->mutex);
-	/* Now wipe the queues */
-	tty_ldisc_flush(gsm->tty);
 
 	guard(spinlock_irqsave)(&gsm->tx_lock);
 	list_for_each_entry_safe(txq, ntxq, &gsm->tx_ctrl_list, list)
@@ -3604,6 +3610,9 @@ static void gsmld_receive_buf(struct tty_struct *tty, const u8 *cp,
 	struct gsm_mux *gsm = tty->disc_data;
 	u8 flags = TTY_NORMAL;
 
+	if (gsm->dead)
+		return;
+
 	if (debug & DBG_DATA)
 		gsm_hex_dump_bytes(__func__, cp, count);
 
-- 
2.50.1 (Apple Git-155)


^ permalink raw reply related

* [PATCH v5] serial: 8250_omap: clear rx_running on zero-length DMA completes
From: Matthias Feser @ 2026-05-26  7:35 UTC (permalink / raw)
  To: Moteen Shah, linux-serial@vger.kernel.org,
	gregkh@linuxfoundation.org, jirislaby@kernel.org
  Cc: linux-kernel@vger.kernel.org, k-willis@ti.com, msp@baylibre.com,
	andriy.shevchenko@linux.intel.com
In-Reply-To: <ede98ffc-9e34-46a5-8d8f-87894fbf9d12@ti.com>

On AM33xx RX DMA only triggers when the FIFO reaches the
configured threshold (typically 48 bytes). For smaller bursts
no DMA request is issued and the FIFO is drained by RX timeout.

In this case __dma_rx_do_complete() can legitimately see count == 0.

The current code exits early in this case and does not clear
dma->rx_running, leaving the DMA state inconsistent. This can
prevent RX DMA from restarting and may cause
omap_8250_rx_dma_flush() to fail, marking DMA as broken.

Fix this by clearing dma->rx_running once the DMA transfer has
completed or been terminated, even if no data was transferred.

Fixes: a5fd8945a478 ("serial: 8250: 8250_omap.c: Clear DMA RX running status only after DMA termination is done")
Cc: stable@vger.kernel.org
Signed-off-by: Matthias Feser <mfe@KBSgmbhfr.onmicrosoft.com>
Reviewed-by: Moteen Shah <m-shah@ti.com>
---
Changes in v5:
- Add missing metadata (Fixes tag and Cc: stable)

Changes in v4:
- Add blank line before dma->rx_running as suggested

Changes in v3:
- Move "Changes in v2" below the tear line as suggested

Changes in v2:
- Move dma->rx_running clear before the count check

 drivers/tty/serial/8250/8250_omap.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index c552c6b9a037..3c7775df27ef 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -944,11 +944,12 @@ static void __dma_rx_do_complete(struct uart_8250_port *p)
 				dev_err(p->port.dev, "teardown incomplete\n");
 		}
 	}
+
+	dma->rx_running = 0;
 	if (!count)
 		goto out;
 	ret = tty_insert_flip_string(tty_port, dma->rx_buf, count);
 
-	dma->rx_running = 0;
 	p->port.icount.rx += ret;
 	p->port.icount.buf_overrun += count - ret;
 out:
-- 
2.39.5


^ permalink raw reply related

* Re: [PATCH 00/11] Convert moduleparams to seq_buf
From: Petr Pavlu @ 2026-05-26  6:53 UTC (permalink / raw)
  To: Kees Cook
  Cc: Luis Chamberlain, Pengpeng Hou, Richard Weinberger, Anton Ivanov,
	Johannes Berg, Rafael J. Wysocki, Len Brown, Corey Minyard,
	Gabriel Somlo, Michael S. Tsirkin, Jani Nikula, Joonas Lahtinen,
	Rodrigo Vivi, Tvrtko Ursulin, David Airlie, Simona Vetter,
	Bart Van Assche, Jason Gunthorpe, Leon Romanovsky,
	Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab,
	Bjorn Helgaas, Hannes Reinecke, James E.J. Bottomley,
	Martin K. Petersen, Daniel Lezcano, Zhang Rui, Lukasz Luba,
	Greg Kroah-Hartman, Jiri Slaby, Alan Stern, Jason Wang, Xuan Zhuo,
	Eugenio Pérez, Jason Baron, Jim Cromie, Tiwei Bie,
	Benjamin Berg, Ilpo Järvinen, David E. Box,
	Maciej W. Rozycki, Srinivas Pandruvada, Peter Zijlstra,
	Heiko Carstens, Vasily Gorbik, Sean Christopherson, Paolo Bonzini,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vinod Koul, Frank Li, Daniel Gomez, Sami Tolvanen,
	Aaron Tomlin, Alexander Potapenko, Marco Elver, Dmitry Vyukov,
	Andrew Morton, John Johansen, Paul Moore, James Morris,
	Serge E. Hallyn, Andy Shevchenko, Georgia Garcia, kvm, dmaengine,
	linux-modules, kasan-dev, linux-mm, apparmor,
	linux-security-module, linux-um, linux-acpi, openipmi-developer,
	qemu-devel, intel-gfx, dri-devel, linux-rdma, linux-media,
	linux-pci, linux-scsi, linux-pm, linuxppc-dev, linux-serial,
	linux-usb, usb-storage, virtualization, linux-kernel, linux-arch,
	netdev, linux-fsdevel, linux-hardening
In-Reply-To: <20260521133315.work.845-kees@kernel.org>

On 5/21/26 3:33 PM, Kees Cook wrote:
> Hi,
> 
> I tried to trim the CC list here, but it's still pretty huge...
> 
> We've had a long-standing issue with "write to a string pointer" callbacks
> that don't bounds check the destination (and for which the bounds is
> also not part of the callback prototype, even if it is "known" to be
> PAGE_SIZE, which sysfs_emit() depends on). Both moduleparams and sysfs
> use this pattern. As a first step, and to test the migration method,
> migrate moduleparams first.
> 
> There are 2 "mechanical" treewide patches that are handled by Coccinelle:
> - treewide: Convert struct kernel_param_ops initializers to DEFINE_KERNEL_PARAM_OPS
> - treewide: Convert custom kernel_param_ops .get callbacks to seq_buf via cocci
> 
> The last treewide patch is manual, and may need to be broken up into
> per-subsystem patches, though I'd prefer to avoid this, as it would
> extend the migration from 1 relase to at least 2 releases. (1 to
> release the migration infrastructure, then 1 release to collect all the
> subsystem changes, and possibly 1 more release to remove the migration
> infrastructure.)
> 
> Thoughts, questions?

This looks reasonable to me. I added a few minor comments on the patches
but they already look solid.

-- 
Thanks,
Petr

^ permalink raw reply

* Re: [PATCH v3 2/2] serial: qcom-geni: Add tracepoints for Qualcomm GENI serial driver
From: Praveen Talari @ 2026-05-26  5:06 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, Jiri Slaby,
	Konrad Dybcio, linux-kernel, linux-trace-kernel, linux-arm-msm,
	linux-serial, Mukesh Kumar Savaliya, Aniket Randive,
	chandana.chiluveru, jyothi.seerapu
In-Reply-To: <2026052258-scrooge-friction-fe21@gregkh>

Hi

On 22-05-2026 15:17, Greg Kroah-Hartman wrote:
> On Mon, May 18, 2026 at 11:26:56PM +0530, Praveen Talari wrote:
>> 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.
>>
>> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>> Signed-off-by: Praveen Talari <praveen.talari@oss.qualcomm.com>
>> ---
>> v2->v3:
>> - Updated commit text(removed example as it was available on cover
>>    letter).
>> ---
>>   drivers/tty/serial/qcom_geni_serial.c | 27 +++++++++++++++++++++++----
>>   1 file changed, 23 insertions(+), 4 deletions(-)
> This patch did not apply to my tree :(
Do you mean these patches are not applied cleanly?If yes, i will push on 
linux-next tip.


Thanks,

Praveen Talari


^ permalink raw reply

* Re: [PATCH v3] serial: max310x: fix compile errors if CONFIG_SPI_MASTER is disabled
From: Randy Dunlap @ 2026-05-25 17:43 UTC (permalink / raw)
  To: Hugo Villeneuve, Greg Kroah-Hartman, Jiri Slaby, Hugo Villeneuve
  Cc: kernel test robot, linux-kernel, linux-serial
In-Reply-To: <20260521153333.2336642-1-hugo@hugovil.com>



On 5/21/26 8:33 AM, Hugo Villeneuve wrote:
> From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> 
> Since commit 20ffe4b3330a8 ("serial: max310x: allow driver to be built with
> SPI or I2C"), if I2C is enabled and SPI_MASTER is disabled, we have these
> compile errors:
> 
>   drivers/tty/serial/max310x.c: In function 'max310x_uart_init':
>   drivers/tty/serial/max310x.c: error: 'max310x_spi_driver' undeclared...
>   drivers/tty/serial/max310x.c: In function ‘max310x_uart_init’:
>   drivers/tty/serial/max310x.c: error: label ‘err_spi_register’
>   defined but not used...
>   drivers/tty/serial/max310x.c: error: ‘regcfg’ defined but not used
> 
> Fix by properly encapsulating i2c/spi code/variables in their respective
> context with IS_ENABLED() macros for CONFIG_I2C and CONFIG_SPI_MASTER.
> 
> Also fix link failure with SERIAL_MAX310X=y and I2C=m by modifying Kconfig
> depends.
> 
> Fixes: 20ffe4b3330a8 ("serial: max310x: allow driver to be built with SPI or I2C")
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202605121847.N9DVLNg2-lkp@intel.com/
> Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> ---
> note: not Cc-ing stable as the commit is still in tty-next, and even if the
> errors originate from original commit that added I2C support, they were not
> trigerred because the driver could not be selected/compiled if
> CONFIG_SPI_MASTER was disabled.
> 
> Changes for v3:
> - Fix link failure with SERIAL_MAX310X=y and I2C=m (Arnd Bergmann)
> 
> Changes for v2:
> - replace #ifdef with #if IS_ENABLED() to suppoirt both built-in and modules
>   options
> ---
>  drivers/tty/serial/Kconfig   |  2 +-
>  drivers/tty/serial/max310x.c | 48 +++++++++++++++++++-----------------
>  2 files changed, 27 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index f834e5d292fd7..4accbfa75074c 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -321,7 +321,7 @@ config SERIAL_MAX3100
>  
>  config SERIAL_MAX310X
>  	tristate "MAX310X support"
> -	depends on SPI_MASTER || I2C
> +	depends on (SPI_MASTER && !I2C) || I2C
>  	select SERIAL_CORE
>  	select REGMAP_SPI if SPI_MASTER
>  	select REGMAP_I2C if I2C

Other than preferring Arnd's Kconfig dependencies (easier to
read/understand IMO), this is all good.
Thanks.

Acked-by: Randy Dunlap <rdunlap@infradead.org>
Tested-by: Randy Dunlap <rdunlap@infradead.org> # build-tested

-- 
~Randy

^ permalink raw reply

* Re: [PATCH 08/11] params: Convert generic kernel_param_ops .get helpers to seq_buf
From: Petr Pavlu @ 2026-05-25 17:10 UTC (permalink / raw)
  To: Kees Cook
  Cc: Luis Chamberlain, Pengpeng Hou, Richard Weinberger, Anton Ivanov,
	Johannes Berg, Rafael J. Wysocki, Len Brown, Corey Minyard,
	Gabriel Somlo, Michael S. Tsirkin, Jani Nikula, Joonas Lahtinen,
	Rodrigo Vivi, Tvrtko Ursulin, David Airlie, Simona Vetter,
	Bart Van Assche, Jason Gunthorpe, Leon Romanovsky,
	Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab,
	Bjorn Helgaas, Hannes Reinecke, James E.J. Bottomley,
	Martin K. Petersen, Daniel Lezcano, Zhang Rui, Lukasz Luba,
	Greg Kroah-Hartman, Jiri Slaby, Alan Stern, Jason Wang, Xuan Zhuo,
	Eugenio Pérez, Jason Baron, Jim Cromie, Tiwei Bie,
	Benjamin Berg, Ilpo Järvinen, David E. Box,
	Maciej W. Rozycki, Srinivas Pandruvada, Peter Zijlstra,
	Heiko Carstens, Vasily Gorbik, Sean Christopherson, Paolo Bonzini,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vinod Koul, Frank Li, Daniel Gomez, Sami Tolvanen,
	Aaron Tomlin, Alexander Potapenko, Marco Elver, Dmitry Vyukov,
	Andrew Morton, John Johansen, Paul Moore, James Morris,
	Serge E. Hallyn, Andy Shevchenko, Georgia Garcia, kvm, dmaengine,
	linux-modules, kasan-dev, linux-mm, apparmor,
	linux-security-module, linux-um, linux-acpi, openipmi-developer,
	qemu-devel, intel-gfx, dri-devel, linux-rdma, linux-media,
	linux-pci, linux-scsi, linux-pm, linuxppc-dev, linux-serial,
	linux-usb, usb-storage, virtualization, linux-kernel, linux-arch,
	netdev, linux-fsdevel, linux-hardening
In-Reply-To: <20260521133326.2465264-8-kees@kernel.org>

On 5/21/26 3:33 PM, Kees Cook wrote:
> Convert the generic struct kernel_param_ops .get helpers in
> kernel/params.c directly to the seq_buf signature, drop their legacy
> "char *" form, and refresh prototypes in <linux/moduleparam.h>:
> 
>   param_get_byte/short/ushort/int/uint/long/ulong/ullong/hexint
>   param_get_charp/bool/invbool/string
>   param_array_get
> 
> The STANDARD_PARAM_DEF() macro expands to a seq_buf body for every
> numeric helper. param_array_get() now writes element output directly
> into the parent seq_buf when the element ops provide .get; it only
> allocates the per-call PAGE_SIZE bounce buffer when the element ops
> still use the legacy .get_str path. The common "rewrite the prior
> element's trailing newline as a comma" step lives outside both
> branches so the two paths share it.
> 
> The non-core changes in this commit (arch/x86/kvm, mm/kfence,
> drivers/dma/dmatest, security/apparmor) are the small set of callers that
> directly invoke one of the converted generic helpers from their own .get
> callback (e.g. an apparmor wrapper that adds a capability check and then
> delegates to param_get_bool()). Because the helpers' signature changes
> here, these wrappers must move in lockstep. Each of them is updated
> to take "struct seq_buf *" and pass it through; param_get_debug() in
> apparmor also pulls aa_print_debug_params() (and its val_mask_to_str()
> helper, in security/apparmor/lib.c) over to seq_buf, since that is the
> only consumer. No other behavioural change is intended.
> 
> Custom .get callbacks that do not delegate to a generic helper (and
> therefore still match the .get_str signature) are routed automatically
> to the .get_str field by the DEFINE_KERNEL_PARAM_OPS _Generic dispatcher
> and are deliberately left alone here, to be changed separately within
> their respective subsystems.
> 
> Signed-off-by: Kees Cook <kees@kernel.org>
> ---
> [...]
> @@ -453,36 +457,46 @@ static int param_array_set(const char *val, const struct kernel_param *kp)
>  			   arr->num ?: &temp_num);
>  }
>  
> -static int param_array_get(char *buffer, const struct kernel_param *kp)
> +static int param_array_get(struct seq_buf *s, const struct kernel_param *kp)
>  {
> -	int i, off, ret;
> -	char *elem_buf;
>  	const struct kparam_array *arr = kp->arr;
>  	struct kernel_param p = *kp;
> +	char *elem_buf = NULL;
> +	int i, ret = 0;
>  
> -	elem_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
> -	if (!elem_buf)
> -		return -ENOMEM;
> +	for (i = 0; i < (arr->num ? *arr->num : arr->max); i++) {
> +		size_t before = s->len;
>  
> -	for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) {
>  		p.arg = arr->elem + arr->elemsize * i;
>  		check_kparam_locked(p.mod);
> -		ret = arr->ops->get_str(elem_buf, &p);
> -		if (ret < 0)
> -			goto out;
> -		ret = min(ret, (int)(PAGE_SIZE - 1 - off));
> -		if (!ret)
> +
> +		if (arr->ops->get) {
> +			ret = arr->ops->get(s, &p);
> +			if (ret < 0)
> +				goto out;
> +		} else {
> +			if (!elem_buf) {
> +				elem_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
> +				if (!elem_buf) {
> +					ret = -ENOMEM;
> +					goto out;
> +				}
> +			}
> +			ret = arr->ops->get_str(elem_buf, &p);
> +			if (ret < 0)
> +				goto out;
> +			seq_buf_putmem(s, elem_buf, ret);
> +		}
> +
> +		/* Nothing got written (e.g. overflow) — stop. */
> +		if (s->len == before)
>  			break;
> +
>  		/* Replace the previous element's trailing newline with a comma. */
> -		if (i)
> -			buffer[off - 1] = ',';
> -		memcpy(buffer + off, elem_buf, ret);
> -		off += ret;
> -		if (off == PAGE_SIZE - 1)
> -			break;
> +		if (i && s->buffer[before - 1] == '\n')
> +			s->buffer[before - 1] = ',';
>  	}
> -	buffer[off] = '\0';
> -	ret = off;
> +	ret = 0;
>  out:
>  	kfree(elem_buf);
>  	return ret;

Since you're almost completely rewriting the logic in param_array_get(),
I suggest tightening it up a bit. The function could warn or return an
error when a kernel_param_ops::get/get_str() call adds a string that
doesn't terminate with '\n', specifically, when the call adds either
a zero-length string or a non-zero-length string that ends with
a different character (unless an overflow occurred).

The updated code silently stops the loop when a get call returns
a zero-length string. Similarly, handling of a string not terminated by
'\n' is halfway there because of the added check
"s->buffer[before - 1] == '\n'".

-- 
Thanks,
Petr

^ permalink raw reply

* Re: [PATCH 07/11] moduleparam: Route DEFINE_KERNEL_PARAM_OPS get pointer via _Generic
From: Petr Pavlu @ 2026-05-25 16:24 UTC (permalink / raw)
  To: Kees Cook
  Cc: Luis Chamberlain, Pengpeng Hou, Richard Weinberger, Anton Ivanov,
	Johannes Berg, Rafael J. Wysocki, Len Brown, Corey Minyard,
	Gabriel Somlo, Michael S. Tsirkin, Jani Nikula, Joonas Lahtinen,
	Rodrigo Vivi, Tvrtko Ursulin, David Airlie, Simona Vetter,
	Bart Van Assche, Jason Gunthorpe, Leon Romanovsky,
	Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab,
	Bjorn Helgaas, Hannes Reinecke, James E.J. Bottomley,
	Martin K. Petersen, Daniel Lezcano, Zhang Rui, Lukasz Luba,
	Greg Kroah-Hartman, Jiri Slaby, Alan Stern, Jason Wang, Xuan Zhuo,
	Eugenio Pérez, Jason Baron, Jim Cromie, Tiwei Bie,
	Benjamin Berg, Ilpo Järvinen, David E. Box,
	Maciej W. Rozycki, Srinivas Pandruvada, Peter Zijlstra,
	Heiko Carstens, Vasily Gorbik, Sean Christopherson, Paolo Bonzini,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vinod Koul, Frank Li, Daniel Gomez, Sami Tolvanen,
	Aaron Tomlin, Alexander Potapenko, Marco Elver, Dmitry Vyukov,
	Andrew Morton, John Johansen, Paul Moore, James Morris,
	Serge E. Hallyn, Andy Shevchenko, Georgia Garcia, kvm, dmaengine,
	linux-modules, kasan-dev, linux-mm, apparmor,
	linux-security-module, linux-um, linux-acpi, openipmi-developer,
	qemu-devel, intel-gfx, dri-devel, linux-rdma, linux-media,
	linux-pci, linux-scsi, linux-pm, linuxppc-dev, linux-serial,
	linux-usb, usb-storage, virtualization, linux-kernel, linux-arch,
	netdev, linux-fsdevel, linux-hardening
In-Reply-To: <20260521133326.2465264-7-kees@kernel.org>

On 5/21/26 3:33 PM, Kees Cook wrote:
> Make the DEFINE_KERNEL_PARAM_OPS family route their _get argument to
> either .get (struct seq_buf *) or .get_str (char *) at compile time
> based on the pointer's actual function signature. Two helper macros
> do the routing:
> 
>   _KERNEL_PARAM_OPS_GET     - return the pointer if it has the seq_buf
>                               signature, otherwise NULL of that type
>   _KERNEL_PARAM_OPS_GET_STR - mirror image for the char * signature
> 
> Both use _Generic; only the two valid function-pointer types are
> listed, so any third-party type is a compile error rather than
> silently falling through.
> 
> Now a callback whose body has been migrated from char * to struct
> seq_buf * needs no change at its kernel_param_ops initialization site,
> because the macro picks up the new type automatically and assigns to
> the correct field.
> 
> Signed-off-by: Kees Cook <kees@kernel.org>
> ---
>  include/linux/moduleparam.h | 33 ++++++++++++++++++++++++++-------
>  1 file changed, 26 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
> index c52120f6ac28..795bc7c654ef 100644
> --- a/include/linux/moduleparam.h
> +++ b/include/linux/moduleparam.h
> @@ -85,15 +85,32 @@ struct kernel_param_ops {
>   *
>   *   static DEFINE_KERNEL_PARAM_OPS(my_ops, my_set, my_get);
>   *
> - * Routing the @_set and @_get function pointers through the macro
> - * (rather than naming the struct fields at every call site) lets the
> - * field layout change in one place when callbacks are migrated to a
> - * new signature.
> + * @_get may be either of:
> + *   int (*)(struct seq_buf *, const struct kernel_param *) (seq_buf)
> + *   int (*)(char *, const struct kernel_param *)           (legacy)
> + *
> + * The macro uses _Generic to route the function pointer to the
> + * matching field (.get or .get_str) at compile time, leaving the
> + * other field NULL. Each helper matches the wrong prototype signature
> + * and returns NULL, falling through to the default branch otherwise;
> + * if @_get has neither expected signature the assignment to the
> + * fields gets a normal compile-time type-mismatch error.
>   */
> +#define _KERNEL_PARAM_OPS_GET(_get)					\
> +	_Generic((_get),						\
> +	    int (*)(char *, const struct kernel_param *): NULL,		\
> +	    default: (_get))
> +
> +#define _KERNEL_PARAM_OPS_GET_STR(_get)					\
> +	_Generic((_get),						\
> +	    int (*)(struct seq_buf *, const struct kernel_param *): NULL, \
> +	    default: (_get))
> +
>  #define DEFINE_KERNEL_PARAM_OPS(_name, _set, _get)			\
>  	const struct kernel_param_ops _name = {				\
>  		.set = (_set),						\
> -		.get_str = (_get),					\
> +		.get = _KERNEL_PARAM_OPS_GET(_get),			\
> +		.get_str = _KERNEL_PARAM_OPS_GET_STR(_get),		\
>  	}
>  
>  /* As DEFINE_KERNEL_PARAM_OPS, with KERNEL_PARAM_OPS_FL_NOARG set. */
> @@ -101,14 +118,16 @@ struct kernel_param_ops {
>  	const struct kernel_param_ops _name = {				\
>  		.flags = KERNEL_PARAM_OPS_FL_NOARG,			\
>  		.set = (_set),						\
> -		.get_str = (_get),					\
> +		.get = _KERNEL_PARAM_OPS_GET(_get),			\
> +		.get_str = _KERNEL_PARAM_OPS_GET_STR(_get),		\
>  	}
>  
>  /* As DEFINE_KERNEL_PARAM_OPS, with an additional .free callback. */
>  #define DEFINE_KERNEL_PARAM_OPS_FREE(_name, _set, _get, _free)		\
>  	const struct kernel_param_ops _name = {				\
>  		.set = (_set),						\
> -		.get_str = (_get),					\
> +		.get = _KERNEL_PARAM_OPS_GET(_get),			\
> +		.get_str = _KERNEL_PARAM_OPS_GET_STR(_get),		\
>  		.free = (_free),					\
>  	}
>  

Reviewed-by: Petr Pavlu <petr.pavlu@suse.com>

-- Petr

^ permalink raw reply

* Re: [PATCH 06/11] moduleparam: Add seq_buf-based .get callback alongside .get_str
From: Petr Pavlu @ 2026-05-25 16:19 UTC (permalink / raw)
  To: Kees Cook
  Cc: Luis Chamberlain, Pengpeng Hou, Richard Weinberger, Anton Ivanov,
	Johannes Berg, Rafael J. Wysocki, Len Brown, Corey Minyard,
	Gabriel Somlo, Michael S. Tsirkin, Jani Nikula, Joonas Lahtinen,
	Rodrigo Vivi, Tvrtko Ursulin, David Airlie, Simona Vetter,
	Bart Van Assche, Jason Gunthorpe, Leon Romanovsky,
	Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab,
	Bjorn Helgaas, Hannes Reinecke, James E.J. Bottomley,
	Martin K. Petersen, Daniel Lezcano, Zhang Rui, Lukasz Luba,
	Greg Kroah-Hartman, Jiri Slaby, Alan Stern, Jason Wang, Xuan Zhuo,
	Eugenio Pérez, Jason Baron, Jim Cromie, Tiwei Bie,
	Benjamin Berg, Ilpo Järvinen, David E. Box,
	Maciej W. Rozycki, Srinivas Pandruvada, Peter Zijlstra,
	Heiko Carstens, Vasily Gorbik, Sean Christopherson, Paolo Bonzini,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vinod Koul, Frank Li, Daniel Gomez, Sami Tolvanen,
	Aaron Tomlin, Alexander Potapenko, Marco Elver, Dmitry Vyukov,
	Andrew Morton, John Johansen, Paul Moore, James Morris,
	Serge E. Hallyn, Andy Shevchenko, Georgia Garcia, kvm, dmaengine,
	linux-modules, kasan-dev, linux-mm, apparmor,
	linux-security-module, linux-um, linux-acpi, openipmi-developer,
	qemu-devel, intel-gfx, dri-devel, linux-rdma, linux-media,
	linux-pci, linux-scsi, linux-pm, linuxppc-dev, linux-serial,
	linux-usb, usb-storage, virtualization, linux-kernel, linux-arch,
	netdev, linux-fsdevel, linux-hardening
In-Reply-To: <20260521133326.2465264-6-kees@kernel.org>

On 5/21/26 3:33 PM, Kees Cook wrote:
> Add a new struct kernel_param_ops::get callback whose signature
> takes a struct seq_buf instead of a raw char buffer:
> 
>   int (*get)(struct seq_buf *sb, const struct kernel_param *kp);
> 
> The previously-legacy .get field is now .get_str (char *buffer);
> .get is the new seq_buf-aware form.  param_attr_show() prefers .get
> when set, otherwise falls back to .get_str.  WARN_ON_ONCE() if both
> are set.  Return contract for .get:
> 
>   < 0 : errno propagated to userspace; seq_buf contents discarded
>   = 0 : success; length derived from seq_buf_used()
>   > 0 : forbidden; the dispatcher WARN_ON_ONCE()s and treats as 0
> 
> The default policy on seq_buf_has_overflowed() is silent truncation,
> matching scnprintf()/sysfs_emit() behaviour.  Callbacks that want a
> specific overflow errno can check seq_buf_has_overflowed() and
> return their preferred error.
> 
> No callbacks use .get yet; the legacy path is still the only one in use
> after this commit. A subsequent commit teaches DEFINE_KERNEL_PARAM_OPS
> to route initializers by type.
> 
> Signed-off-by: Kees Cook <kees@kernel.org>

Reviewed-by: Petr Pavlu <petr.pavlu@suse.com>

-- Petr

^ permalink raw reply

* Re: [PATCH 04/11] treewide: Convert struct kernel_param_ops initializers to DEFINE_KERNEL_PARAM_OPS
From: Petr Pavlu @ 2026-05-25 13:35 UTC (permalink / raw)
  To: Kees Cook
  Cc: Luis Chamberlain, Pengpeng Hou, Richard Weinberger, Anton Ivanov,
	Johannes Berg, Rafael J. Wysocki, Len Brown, Corey Minyard,
	Gabriel Somlo, Michael S. Tsirkin, Jani Nikula, Joonas Lahtinen,
	Rodrigo Vivi, Tvrtko Ursulin, David Airlie, Simona Vetter,
	Bart Van Assche, Jason Gunthorpe, Leon Romanovsky,
	Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab,
	Bjorn Helgaas, Hannes Reinecke, James E.J. Bottomley,
	Martin K. Petersen, Daniel Lezcano, Zhang Rui, Lukasz Luba,
	Greg Kroah-Hartman, Jiri Slaby, Alan Stern, Jason Wang, Xuan Zhuo,
	Eugenio Pérez, Jason Baron, Jim Cromie, Tiwei Bie,
	Benjamin Berg, Ilpo Järvinen, David E. Box,
	Maciej W. Rozycki, Srinivas Pandruvada, Peter Zijlstra,
	Heiko Carstens, Vasily Gorbik, Sean Christopherson, Paolo Bonzini,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vinod Koul, Frank Li, Daniel Gomez, Sami Tolvanen,
	Aaron Tomlin, Alexander Potapenko, Marco Elver, Dmitry Vyukov,
	Andrew Morton, John Johansen, Paul Moore, James Morris,
	Serge E. Hallyn, Andy Shevchenko, Georgia Garcia, kvm, dmaengine,
	linux-modules, kasan-dev, linux-mm, apparmor,
	linux-security-module, linux-um, linux-acpi, openipmi-developer,
	qemu-devel, intel-gfx, dri-devel, linux-rdma, linux-media,
	linux-pci, linux-scsi, linux-pm, linuxppc-dev, linux-serial,
	linux-usb, usb-storage, virtualization, linux-kernel, linux-arch,
	netdev, linux-fsdevel, linux-hardening
In-Reply-To: <20260521133326.2465264-4-kees@kernel.org>

On 5/21/26 3:33 PM, Kees Cook wrote:
> Using Coccinelle, rewrite every struct kernel_param_ops initializer that
> sets .get into a DEFINE_KERNEL_PARAM_OPS-family macro invocation,
> for example:
> 
> @@
> declarer name DEFINE_KERNEL_PARAM_OPS;
> identifier OPS;
> expression SET, GET;
> @@
> - const struct kernel_param_ops OPS = {
> -       .set = SET,
> -       .get = GET,
> - };
> + DEFINE_KERNEL_PARAM_OPS(OPS, SET, GET);
> 
> Using the macro for initialization means future changes can manipulate
> the struct layout and callback prototypes without having to change every
> initializer.

Nit: For consistency, I suggest also converting the few remaining
kernel_param_ops instances that specify only .set and no .get, such as
simdisk_param_ops_filename.

-- 
Thanks,
Petr

^ permalink raw reply

* Re: [PATCH 03/11] moduleparam: Add DEFINE_KERNEL_PARAM_OPS macro family
From: Petr Pavlu @ 2026-05-25 13:27 UTC (permalink / raw)
  To: Kees Cook
  Cc: Luis Chamberlain, Pengpeng Hou, Richard Weinberger, Anton Ivanov,
	Johannes Berg, Rafael J. Wysocki, Len Brown, Corey Minyard,
	Gabriel Somlo, Michael S. Tsirkin, Jani Nikula, Joonas Lahtinen,
	Rodrigo Vivi, Tvrtko Ursulin, David Airlie, Simona Vetter,
	Bart Van Assche, Jason Gunthorpe, Leon Romanovsky,
	Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab,
	Bjorn Helgaas, Hannes Reinecke, James E.J. Bottomley,
	Martin K. Petersen, Daniel Lezcano, Zhang Rui, Lukasz Luba,
	Greg Kroah-Hartman, Jiri Slaby, Alan Stern, Jason Wang, Xuan Zhuo,
	Eugenio Pérez, Jason Baron, Jim Cromie, Tiwei Bie,
	Benjamin Berg, Ilpo Järvinen, David E. Box,
	Maciej W. Rozycki, Srinivas Pandruvada, Peter Zijlstra,
	Heiko Carstens, Vasily Gorbik, Sean Christopherson, Paolo Bonzini,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vinod Koul, Frank Li, Daniel Gomez, Sami Tolvanen,
	Aaron Tomlin, Alexander Potapenko, Marco Elver, Dmitry Vyukov,
	Andrew Morton, John Johansen, Paul Moore, James Morris,
	Serge E. Hallyn, Andy Shevchenko, Georgia Garcia, kvm, dmaengine,
	linux-modules, kasan-dev, linux-mm, apparmor,
	linux-security-module, linux-um, linux-acpi, openipmi-developer,
	qemu-devel, intel-gfx, dri-devel, linux-rdma, linux-media,
	linux-pci, linux-scsi, linux-pm, linuxppc-dev, linux-serial,
	linux-usb, usb-storage, virtualization, linux-kernel, linux-arch,
	netdev, linux-fsdevel, linux-hardening
In-Reply-To: <20260521133326.2465264-3-kees@kernel.org>

On 5/21/26 3:33 PM, Kees Cook wrote:
> Add macros that define a struct kernel_param_ops initializer through a
> macro so the underlying field layout can evolve without touching every
> call site. Three variants cover the three cases:
> 
>  DEFINE_KERNEL_PARAM_OPS(name, set, get) // basic
>  DEFINE_KERNEL_PARAM_OPS_NOARG(name, set, get) // set KERNEL_PARAM_OPS_FL_NOARG
>  DEFINE_KERNEL_PARAM_OPS_FREE(name, set, get, free) // also set .free
> 
> Callers prefix their own visibility qualifiers, e.g.:
> 
>   static DEFINE_KERNEL_PARAM_OPS(my_ops, my_set, my_get);
> 
> Also update module_param_call() and STANDARD_PARAM_DEF() to use
> DEFINE_KERNEL_PARAM_OPS internally so the generated ops table will go
> through the same macro as everything else.
> 
> Subsequent commits convert all open-coded struct kernel_param_ops
> definitions to use these macros, in preparation for migrating to a
> seq_buf .get API.
> 
> Signed-off-by: Kees Cook <kees@kernel.org>
> ---
>  include/linux/moduleparam.h | 36 ++++++++++++++++++++++++++++++++++--
>  kernel/params.c             |  6 ++----
>  2 files changed, 36 insertions(+), 6 deletions(-)
> 
> diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
> index 075f28585074..26bf45b36d02 100644
> --- a/include/linux/moduleparam.h
> +++ b/include/linux/moduleparam.h
> @@ -68,6 +68,39 @@ struct kernel_param_ops {
>  	void (*free)(void *arg);
>  };
>  
> +/*
> + * Define a const struct kernel_param_ops initializer. Callers prefix with
> + * any required visibility qualifiers (typically "static"):
> + *
> + *   static DEFINE_KERNEL_PARAM_OPS(my_ops, my_set, my_get);
> + *
> + * Routing the @_set and @_get function pointers through the macro
> + * (rather than naming the struct fields at every call site) lets the
> + * field layout change in one place when callbacks are migrated to a
> + * new signature.
> + */

Nit: The newly introduced DEFINE_KERNEL_PARAM_OPS*() macros remain in
place at the end of the series after the migration is complete and this
comment is removed in patch 7. It would be helpful to describe in the
commit message why these macros are generally preferable to defining
kernel_param_ops instances directly.

I assume the motivation is that the structure is simple enough and using
macros then makes defining kernel_param_ops instances a bit more
concise. A minor disadvantage is that some analysis tools, such as
ctags, may no longer see the generated definition, but that is also the
case for DEFINE_MUTEX() and other similar macros.

-- 
Thanks,
Petr

^ permalink raw reply

* [PATCH 3/3] serial: max310x: honour rs485 properties from per-port DT subnode
From: Tapio Reijonen @ 2026-05-25  9:43 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Hugo Villeneuve
  Cc: linux-kernel, linux-serial, devicetree, Tapio Reijonen
In-Reply-To: <20260525-b4-max310x-rs485-dt-v1-0-e6c19b4d5592@vaisala.com>

The MAX310x DT binding pulls in /schemas/serial/rs485.yaml via its
allOf list, advertising the rs485-* properties defined there - none
of which were honoured at runtime, because the driver never called
uart_get_rs485_mode().

All ports share the parent SPI/I2C device, so uart_get_rs485_mode()
called directly on each port would read the same chip-level fwnode
for every call. Walk dev->of_node's children for the one named "port"
with matching reg, and temporarily retarget the parent device's
fwnode while uart_get_rs485_mode() runs, so each port picks up its
own subnode's properties. Probe is serialised, so the swap is safe.

For single-port variants (max3107, max3108), fall back to the chip's
own fwnode when no port@0 subnode is present, so existing DTs that
declare rs485 properties at the top level keep working.

Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com>
---
 drivers/tty/serial/max310x.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 5cb7d01e404663dc25b88bc7b4f8df61be2135ec..745498034293cf74c8b4d25b45739e787f1843de 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1426,6 +1426,9 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
 #endif
 
 	for (i = 0; i < devtype->nr; i++) {
+		struct fwnode_handle *saved_fwnode = dev_fwnode(dev);
+		struct device_node *port_np = NULL;
+		struct device_node *child;
 		unsigned int line;
 
 		line = find_first_zero_bit(max310x_lines, MAX310X_UART_NRMAX);
@@ -1435,6 +1438,40 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
 		}
 		s->p[i].port.line = line;
 
+		/* Locate the matching "port@i" DT subnode, if any. */
+		for_each_available_child_of_node(dev->of_node, child) {
+			u32 reg;
+
+			if (!of_node_name_eq(child, "port"))
+				continue;
+			if (of_property_read_u32(child, "reg", &reg))
+				continue;
+			if (reg == i) {
+				port_np = child;
+				break;
+			}
+		}
+
+		/*
+		 * Temporarily retarget dev's fwnode to the per-port subnode
+		 * so uart_get_rs485_mode() picks up the per-port properties.
+		 * For single-port variants, fall back to the chip's own
+		 * fwnode so legacy DTs that declare rs485 properties at the
+		 * top level keep working.
+		 */
+		if (port_np) {
+			device_set_node(dev, of_fwnode_handle(port_np));
+			ret = uart_get_rs485_mode(&s->p[i].port);
+			device_set_node(dev, saved_fwnode);
+			of_node_put(port_np);
+			if (ret)
+				goto out_uart;
+		} else if (devtype->nr == 1) {
+			ret = uart_get_rs485_mode(&s->p[i].port);
+			if (ret)
+				goto out_uart;
+		}
+
 		/* Register port */
 		ret = uart_add_one_port(&max310x_uart, &s->p[i].port);
 		if (ret)

-- 
2.47.3


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox