* [PATCH v2 4/7] serial: 8250_dw: Rework dw8250_handle_irq() locking and IIR handling
From: Ilpo Järvinen @ 2026-01-28 10:52 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, linux-serial, Andy Shevchenko,
qianfan Zhao, Adriana Nicolae, Ilpo Järvinen, linux-kernel
Cc: Bandal, Shankar, Murthy, Shanth, stable
In-Reply-To: <20260128105301.1869-1-ilpo.jarvinen@linux.intel.com>
dw8250_handle_irq() takes port's lock multiple times with no good
reason to release it in between and calls serial8250_handle_irq()
that also takes port's lock.
Take port's lock only once in dw8250_handle_irq() and use
serial8250_handle_irq_locked() to avoid releasing port's lock in
between.
As IIR_NO_INT check in serial8250_handle_irq() was outside of port's
lock, it has to be done already in dw8250_handle_irq().
DW UART can, in addition to IIR_NO_INT, report BUSY_DETECT (0x7) which
collided with the IIR_NO_INT (0x1) check in serial8250_handle_irq()
(because & is used instead of ==) meaning that no other work is done by
serial8250_handle_irq() during an BUSY_DETECT interrupt.
This allows reorganizing code in dw8250_handle_irq() to do both
IIR_NO_INT and BUSY_DETECT handling right at the start simplifying
the logic.
Tested-by: "Bandal, Shankar" <shankar.bandal@intel.com>
Tested-by: "Murthy, Shanth" <shanth.murthy@intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
drivers/tty/serial/8250/8250_dw.c | 37 ++++++++++++++++++-------------
1 file changed, 21 insertions(+), 16 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 7500b1ff1ac1..964750d17186 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -9,6 +9,9 @@
* LCR is written whilst busy. If it is, then a busy detect interrupt is
* raised, the LCR needs to be rewritten and the uart status register read.
*/
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
@@ -40,6 +43,8 @@
#define RZN1_UART_RDMACR 0x110 /* DMA Control Register Receive Mode */
/* DesignWare specific register fields */
+#define DW_UART_IIR_IID GENMASK(3, 0)
+
#define DW_UART_MCR_SIRE BIT(6)
/* Renesas specific register fields */
@@ -312,7 +317,19 @@ static int dw8250_handle_irq(struct uart_port *p)
bool rx_timeout = (iir & 0x3f) == UART_IIR_RX_TIMEOUT;
unsigned int quirks = d->pdata->quirks;
unsigned int status;
- unsigned long flags;
+
+ switch (FIELD_GET(DW_UART_IIR_IID, iir)) {
+ case UART_IIR_NO_INT:
+ return 0;
+
+ case UART_IIR_BUSY:
+ /* Clear the USR */
+ serial_port_in(p, d->pdata->usr_reg);
+
+ return 1;
+ }
+
+ guard(uart_port_lock_irqsave)(p);
/*
* There are ways to get Designware-based UARTs into a state where
@@ -325,20 +342,15 @@ static int dw8250_handle_irq(struct uart_port *p)
* so we limit the workaround only to non-DMA mode.
*/
if (!up->dma && rx_timeout) {
- uart_port_lock_irqsave(p, &flags);
status = serial_lsr_in(up);
if (!(status & (UART_LSR_DR | UART_LSR_BI)))
serial_port_in(p, UART_RX);
-
- uart_port_unlock_irqrestore(p, flags);
}
/* Manually stop the Rx DMA transfer when acting as flow controller */
if (quirks & DW_UART_QUIRK_IS_DMA_FC && up->dma && up->dma->rx_running && rx_timeout) {
- uart_port_lock_irqsave(p, &flags);
status = serial_lsr_in(up);
- uart_port_unlock_irqrestore(p, flags);
if (status & (UART_LSR_DR | UART_LSR_BI)) {
dw8250_writel_ext(p, RZN1_UART_RDMACR, 0);
@@ -346,17 +358,9 @@ static int dw8250_handle_irq(struct uart_port *p)
}
}
- if (serial8250_handle_irq(p, iir))
- return 1;
-
- if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
- /* Clear the USR */
- serial_port_in(p, d->pdata->usr_reg);
+ serial8250_handle_irq_locked(p, iir);
- return 1;
- }
-
- return 0;
+ return 1;
}
static void dw8250_clk_work_cb(struct work_struct *work)
@@ -858,6 +862,7 @@ static struct platform_driver dw8250_platform_driver = {
module_platform_driver(dw8250_platform_driver);
+MODULE_IMPORT_NS("SERIAL_8250");
MODULE_AUTHOR("Jamie Iles");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
--
2.39.5
^ permalink raw reply related
* [PATCH v2 3/7] serial: 8250: Add serial8250_handle_irq_locked()
From: Ilpo Järvinen @ 2026-01-28 10:52 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, linux-serial, Andy Shevchenko,
qianfan Zhao, Adriana Nicolae, linux-kernel
Cc: Bandal, Shankar, Murthy, Shanth, Ilpo Järvinen, stable
In-Reply-To: <20260128105301.1869-1-ilpo.jarvinen@linux.intel.com>
8250_port exports serial8250_handle_irq() to HW specific 8250 drivers.
It takes port's lock within but a HW specific 8250 driver may want to
take port's lock itself, do something, and then call the generic
handler in 8250_port but to do that, the caller has to release port's
lock for no good reason.
Introduce serial8250_handle_irq_locked() which a HW specific driver can
call while already holding port's lock.
As this is new export, put it straight into a namespace (where all 8250
exports should eventually be moved).
Tested-by: "Bandal, Shankar" <shankar.bandal@intel.com>
Tested-by: "Murthy, Shanth" <shanth.murthy@intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
drivers/tty/serial/8250/8250_port.c | 24 ++++++++++++++++--------
include/linux/serial_8250.h | 1 +
2 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index f7a3c5555204..bc223eb1f474 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -18,6 +18,7 @@
#include <linux/irq.h>
#include <linux/console.h>
#include <linux/gpio/consumer.h>
+#include <linux/lockdep.h>
#include <linux/sysrq.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
@@ -1782,20 +1783,16 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
}
/*
- * This handles the interrupt from one port.
+ * Context: port's lock must be held by the caller.
*/
-int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+void serial8250_handle_irq_locked(struct uart_port *port, unsigned int iir)
{
struct uart_8250_port *up = up_to_u8250p(port);
struct tty_port *tport = &port->state->port;
bool skip_rx = false;
- unsigned long flags;
u16 status;
- if (iir & UART_IIR_NO_INT)
- return 0;
-
- uart_port_lock_irqsave(port, &flags);
+ lockdep_assert_held_once(&port->lock);
status = serial_lsr_in(up);
@@ -1828,8 +1825,19 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
else if (!up->dma->tx_running)
__stop_tx(up);
}
+}
+EXPORT_SYMBOL_NS_GPL(serial8250_handle_irq_locked, "SERIAL_8250");
- uart_unlock_and_check_sysrq_irqrestore(port, flags);
+/*
+ * This handles the interrupt from one port.
+ */
+int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+{
+ if (iir & UART_IIR_NO_INT)
+ return 0;
+
+ guard(uart_port_lock_irqsave)(port);
+ serial8250_handle_irq_locked(port, iir);
return 1;
}
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 01efdce0fda0..a95b2d143d24 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -195,6 +195,7 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl);
void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud,
unsigned int quot);
int fsl8250_handle_irq(struct uart_port *port);
+void serial8250_handle_irq_locked(struct uart_port *port, unsigned int iir);
int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr);
void serial8250_read_char(struct uart_8250_port *up, u16 lsr);
--
2.39.5
^ permalink raw reply related
* [PATCH v2 2/7] serial: 8250_dw: Avoid unnecessary LCR writes
From: Ilpo Järvinen @ 2026-01-28 10:52 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, linux-serial, Andy Shevchenko,
qianfan Zhao, Adriana Nicolae, Ilpo Järvinen, linux-kernel
Cc: Bandal, Shankar, Murthy, Shanth, stable
In-Reply-To: <20260128105301.1869-1-ilpo.jarvinen@linux.intel.com>
When DW UART is configured with BUSY flag, LCR writes may not always
succeed which can make any LCR write complex and very expensive.
Performing write directly can trigger IRQ and the driver has to perform
complex and distruptive sequence while retrying the write.
Therefore, it's better to avoid doing LCR write that would not change
the value of the LCR register. Add LCR write avoidance code into the
8250_dw driver's .serial_out() functions.
Reported-by: "Bandal, Shankar" <shankar.bandal@intel.com>
Tested-by: "Bandal, Shankar" <shankar.bandal@intel.com>
Tested-by: "Murthy, Shanth" <shanth.murthy@intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
drivers/tty/serial/8250/8250_dw.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 27af83f0ff46..7500b1ff1ac1 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -181,6 +181,22 @@ static void dw8250_check_lcr(struct uart_port *p, unsigned int offset, u32 value
*/
}
+/*
+ * With BUSY, LCR writes can be very expensive (IRQ + complex retry logic).
+ * If the write does not change the value of the LCR register, skip it entirely.
+ */
+static bool dw8250_can_skip_reg_write(struct uart_port *p, unsigned int offset, u32 value)
+{
+ struct dw8250_data *d = to_dw8250_data(p->private_data);
+ u32 lcr;
+
+ if (offset != UART_LCR || d->uart_16550_compatible)
+ return false;
+
+ lcr = serial_port_in(p, offset);
+ return lcr == value;
+}
+
/* Returns once the transmitter is empty or we run out of retries */
static void dw8250_tx_wait_empty(struct uart_port *p)
{
@@ -207,12 +223,18 @@ static void dw8250_tx_wait_empty(struct uart_port *p)
static void dw8250_serial_out(struct uart_port *p, unsigned int offset, u32 value)
{
+ if (dw8250_can_skip_reg_write(p, offset, value))
+ return;
+
writeb(value, p->membase + (offset << p->regshift));
dw8250_check_lcr(p, offset, value);
}
static void dw8250_serial_out38x(struct uart_port *p, unsigned int offset, u32 value)
{
+ if (dw8250_can_skip_reg_write(p, offset, value))
+ return;
+
/* Allow the TX to drain before we reconfigure */
if (offset == UART_LCR)
dw8250_tx_wait_empty(p);
@@ -237,6 +259,9 @@ static u32 dw8250_serial_inq(struct uart_port *p, unsigned int offset)
static void dw8250_serial_outq(struct uart_port *p, unsigned int offset, u32 value)
{
+ if (dw8250_can_skip_reg_write(p, offset, value))
+ return;
+
value &= 0xff;
__raw_writeq(value, p->membase + (offset << p->regshift));
/* Read back to ensure register write ordering. */
@@ -248,6 +273,9 @@ static void dw8250_serial_outq(struct uart_port *p, unsigned int offset, u32 val
static void dw8250_serial_out32(struct uart_port *p, unsigned int offset, u32 value)
{
+ if (dw8250_can_skip_reg_write(p, offset, value))
+ return;
+
writel(value, p->membase + (offset << p->regshift));
dw8250_check_lcr(p, offset, value);
}
@@ -261,6 +289,9 @@ static u32 dw8250_serial_in32(struct uart_port *p, unsigned int offset)
static void dw8250_serial_out32be(struct uart_port *p, unsigned int offset, u32 value)
{
+ if (dw8250_can_skip_reg_write(p, offset, value))
+ return;
+
iowrite32be(value, p->membase + (offset << p->regshift));
dw8250_check_lcr(p, offset, value);
}
--
2.39.5
^ permalink raw reply related
* [PATCH v2 1/7] serial: 8250: Protect LCR write in shutdown
From: Ilpo Järvinen @ 2026-01-28 10:52 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, linux-serial, Andy Shevchenko,
qianfan Zhao, Adriana Nicolae, linux-kernel
Cc: Bandal, Shankar, Murthy, Shanth, Ilpo Järvinen, stable
In-Reply-To: <20260128105301.1869-1-ilpo.jarvinen@linux.intel.com>
The 8250_dw driver needs to potentially perform very complex operations
during LCR writes because its BUSY handling prevents updates to LCR
while UART is BUSY (which is not fully under our control without those
complex operations). Thus, LCR writes should occur under port's lock.
Move LCR write under port's lock in serial8250_do_shutdown(). Also
split the LCR RMW so that the logic is on a separate line for clarity.
Tested-by: "Bandal, Shankar" <shankar.bandal@intel.com>
Tested-by: "Murthy, Shanth" <shanth.murthy@intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
drivers/tty/serial/8250/8250_port.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 719faf92aa8a..f7a3c5555204 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -2350,6 +2350,7 @@ static int serial8250_startup(struct uart_port *port)
void serial8250_do_shutdown(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
+ u32 lcr;
serial8250_rpm_get(up);
/*
@@ -2376,13 +2377,13 @@ void serial8250_do_shutdown(struct uart_port *port)
port->mctrl &= ~TIOCM_OUT2;
serial8250_set_mctrl(port, port->mctrl);
+
+ /* Disable break condition */
+ lcr = serial_port_in(port, UART_LCR);
+ lcr &= ~UART_LCR_SBC;
+ serial_port_out(port, UART_LCR, lcr);
}
- /*
- * Disable break condition and FIFOs
- */
- serial_port_out(port, UART_LCR,
- serial_port_in(port, UART_LCR) & ~UART_LCR_SBC);
serial8250_clear_fifos(up);
rsa_disable(up);
--
2.39.5
^ permalink raw reply related
* [PATCH v2 0/7] 8250 DW UART fixes when under constant Rx pressure
From: Ilpo Järvinen @ 2026-01-28 10:52 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, linux-serial, Andy Shevchenko,
qianfan Zhao, Adriana Nicolae
Cc: linux-kernel, Bandal, Shankar, Murthy, Shanth, Ilpo Järvinen
Hi all,
Here are fixes to 8250 DW UART conditions that mostly occur in scenarios
under constant Rx pressure which are made complicated by BUSY handling
of DW UARTs (used when !uart_16550_compatible).
A few of the changes touch also 8250_port but it's mostly moving existing
code around (except for the extra synchronize_irq() in shutdown).
I'll do UART_IIR_RX_TIMEOUT move to switch/case separately from this
fix series and a few other cleanups Andy brought up.
v2:
- Added Fixes tags pointing DW & INTC10EE introducing commits
- Added Cc stable to prerequisite patches
- Separate adding serial8250_handle_irq_locked() to own patch
- Put new exports to SERIAL_8250 namespace (eventually all 8250
exports should move there, but out-of-scope for this series)
- Changes to no_int_count
- Change type to u8
- Use modulo in increment, add a define for it
- Perform kick only on 4th NO_INT
- Use serial_port_in/out() throughout the series
- Add FIXME comments to ndelay(frame_time) about very low baud rates
- Add cleanup.h
- Tweak lockdep.h place among misordered includes
- Wording tweaks to changelogs and comments
Ilpo Järvinen (7):
serial: 8250: Protect LCR write in shutdown
serial: 8250_dw: Avoid unnecessary LCR writes
serial: 8250: Add serial8250_handle_irq_locked()
serial: 8250_dw: Rework dw8250_handle_irq() locking and IIR handling
serial: 8250_dw: Rework IIR_NO_INT handling to stop interrupt storm
serial: 8250: Add late synchronize_irq() to shutdown to handle DW UART
BUSY
serial: 8250_dw: Ensure BUSY is deasserted
drivers/tty/serial/8250/8250.h | 25 +++
drivers/tty/serial/8250/8250_dw.c | 309 ++++++++++++++++++++++------
drivers/tty/serial/8250/8250_port.c | 69 ++++---
include/linux/serial_8250.h | 1 +
4 files changed, 313 insertions(+), 91 deletions(-)
base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
--
2.39.5
^ permalink raw reply
* [tty:tty-testing] BUILD SUCCESS 0a15f43b92ddaa2fdb476891a12ac2e207c7fcd2
From: kernel test robot @ 2026-01-28 9:20 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linux-serial
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing
branch HEAD: 0a15f43b92ddaa2fdb476891a12ac2e207c7fcd2 Revert "tty: tty_port: add workqueue to flip TTY buffer"
elapsed time: 1198m
configs tested: 227
configs skipped: 2
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc-15.2.0
alpha allyesconfig gcc-15.2.0
alpha defconfig gcc-15.2.0
arc allmodconfig clang-16
arc allmodconfig gcc-15.2.0
arc allnoconfig gcc-15.2.0
arc allyesconfig clang-22
arc allyesconfig gcc-15.2.0
arc axs103_smp_defconfig gcc-15.2.0
arc defconfig gcc-15.2.0
arc haps_hs_smp_defconfig clang-22
arc hsdk_defconfig clang-22
arc randconfig-001-20260128 gcc-8.5.0
arc randconfig-002-20260128 gcc-8.5.0
arm allnoconfig clang-22
arm allnoconfig gcc-15.2.0
arm allyesconfig clang-16
arm allyesconfig gcc-15.2.0
arm aspeed_g4_defconfig clang-22
arm at91_dt_defconfig clang-22
arm defconfig gcc-15.2.0
arm mvebu_v5_defconfig gcc-15.2.0
arm pxa3xx_defconfig gcc-15.2.0
arm randconfig-001-20260128 gcc-8.5.0
arm randconfig-002-20260128 gcc-8.5.0
arm randconfig-003-20260128 gcc-8.5.0
arm randconfig-004-20260128 gcc-8.5.0
arm64 alldefconfig gcc-15.2.0
arm64 allmodconfig clang-19
arm64 allmodconfig clang-22
arm64 allnoconfig gcc-15.2.0
arm64 defconfig gcc-15.2.0
arm64 randconfig-001-20260128 gcc-14.3.0
arm64 randconfig-002-20260128 gcc-14.3.0
arm64 randconfig-003-20260128 gcc-14.3.0
arm64 randconfig-004-20260128 gcc-14.3.0
csky allmodconfig gcc-15.2.0
csky allnoconfig gcc-15.2.0
csky defconfig gcc-15.2.0
csky randconfig-001-20260128 gcc-14.3.0
csky randconfig-002-20260128 gcc-14.3.0
hexagon allmodconfig clang-17
hexagon allmodconfig gcc-15.2.0
hexagon allnoconfig clang-22
hexagon allnoconfig gcc-15.2.0
hexagon defconfig gcc-15.2.0
hexagon randconfig-001-20260128 clang-22
hexagon randconfig-002-20260128 clang-22
i386 allmodconfig clang-20
i386 allmodconfig gcc-14
i386 allnoconfig gcc-14
i386 allnoconfig gcc-15.2.0
i386 allyesconfig clang-20
i386 allyesconfig gcc-14
i386 buildonly-randconfig-001-20260128 clang-20
i386 buildonly-randconfig-002-20260128 clang-20
i386 buildonly-randconfig-003-20260128 clang-20
i386 buildonly-randconfig-004-20260128 clang-20
i386 buildonly-randconfig-005-20260128 clang-20
i386 buildonly-randconfig-006-20260128 clang-20
i386 defconfig gcc-15.2.0
i386 randconfig-001-20260128 gcc-14
i386 randconfig-002-20260128 gcc-14
i386 randconfig-003-20260128 gcc-14
i386 randconfig-004-20260128 gcc-14
i386 randconfig-005-20260128 gcc-14
i386 randconfig-006-20260128 gcc-14
i386 randconfig-007-20260128 gcc-14
i386 randconfig-011-20260128 clang-20
i386 randconfig-012-20260128 clang-20
i386 randconfig-013-20260128 clang-20
i386 randconfig-014-20260128 clang-20
i386 randconfig-015-20260128 clang-20
i386 randconfig-016-20260128 clang-20
i386 randconfig-017-20260128 clang-20
loongarch allmodconfig clang-19
loongarch allmodconfig clang-22
loongarch allnoconfig clang-22
loongarch allnoconfig gcc-15.2.0
loongarch defconfig clang-19
loongarch randconfig-001-20260128 clang-22
loongarch randconfig-002-20260128 clang-22
m68k allmodconfig gcc-15.2.0
m68k allnoconfig gcc-15.2.0
m68k allyesconfig clang-16
m68k allyesconfig gcc-15.2.0
m68k atari_defconfig gcc-15.2.0
m68k defconfig clang-19
m68k m5275evb_defconfig clang-22
microblaze allnoconfig gcc-15.2.0
microblaze allyesconfig gcc-15.2.0
microblaze defconfig clang-19
mips allmodconfig gcc-15.2.0
mips allnoconfig gcc-15.2.0
mips allyesconfig gcc-15.2.0
mips cavium_octeon_defconfig gcc-15.2.0
mips db1xxx_defconfig gcc-15.2.0
mips ip27_defconfig gcc-15.2.0
mips ip30_defconfig gcc-15.2.0
mips ip32_defconfig gcc-15.2.0
mips loongson3_defconfig gcc-15.2.0
mips malta_defconfig gcc-15.2.0
mips malta_kvm_defconfig gcc-15.2.0
mips maltaup_defconfig gcc-15.2.0
nios2 allmodconfig clang-22
nios2 allmodconfig gcc-11.5.0
nios2 allnoconfig clang-22
nios2 allnoconfig gcc-11.5.0
nios2 defconfig clang-19
nios2 randconfig-001-20260128 clang-22
nios2 randconfig-002-20260128 clang-22
openrisc allmodconfig clang-22
openrisc allmodconfig gcc-15.2.0
openrisc allnoconfig clang-22
openrisc allnoconfig gcc-15.2.0
openrisc defconfig gcc-15.2.0
openrisc or1klitex_defconfig clang-22
openrisc virt_defconfig gcc-15.2.0
parisc allmodconfig gcc-15.2.0
parisc allnoconfig clang-22
parisc allnoconfig gcc-15.2.0
parisc allyesconfig clang-19
parisc allyesconfig gcc-15.2.0
parisc defconfig gcc-15.2.0
parisc randconfig-001-20260128 gcc-11.5.0
parisc randconfig-002-20260128 gcc-11.5.0
parisc64 defconfig clang-19
powerpc allmodconfig gcc-15.2.0
powerpc allnoconfig clang-22
powerpc allnoconfig gcc-15.2.0
powerpc chrp32_defconfig gcc-15.2.0
powerpc fsp2_defconfig gcc-15.2.0
powerpc linkstation_defconfig clang-22
powerpc mgcoge_defconfig gcc-15.2.0
powerpc mpc83xx_defconfig gcc-15.2.0
powerpc mvme5100_defconfig gcc-15.2.0
powerpc randconfig-001-20260128 gcc-11.5.0
powerpc randconfig-002-20260128 gcc-11.5.0
powerpc64 randconfig-001-20260128 gcc-11.5.0
powerpc64 randconfig-002-20260128 gcc-11.5.0
riscv allmodconfig clang-22
riscv allnoconfig clang-22
riscv allnoconfig gcc-15.2.0
riscv allyesconfig clang-16
riscv defconfig gcc-15.2.0
riscv randconfig-001-20260128 gcc-13.4.0
riscv randconfig-002-20260128 gcc-13.4.0
s390 allmodconfig clang-18
s390 allmodconfig clang-19
s390 allnoconfig clang-22
s390 allyesconfig gcc-15.2.0
s390 defconfig gcc-15.2.0
s390 randconfig-001-20260128 gcc-13.4.0
s390 randconfig-002-20260128 gcc-13.4.0
sh allmodconfig gcc-15.2.0
sh allnoconfig clang-22
sh allnoconfig gcc-15.2.0
sh allyesconfig clang-19
sh allyesconfig gcc-15.2.0
sh defconfig gcc-14
sh randconfig-001-20260128 gcc-13.4.0
sh randconfig-002-20260128 gcc-13.4.0
sparc alldefconfig gcc-15.2.0
sparc allnoconfig clang-22
sparc allnoconfig gcc-15.2.0
sparc defconfig gcc-15.2.0
sparc randconfig-001-20260128 gcc-11.5.0
sparc randconfig-002-20260128 gcc-11.5.0
sparc64 allmodconfig clang-22
sparc64 defconfig gcc-14
sparc64 randconfig-001-20260128 gcc-11.5.0
sparc64 randconfig-002-20260128 gcc-11.5.0
um allmodconfig clang-19
um allnoconfig clang-22
um allyesconfig gcc-14
um allyesconfig gcc-15.2.0
um defconfig gcc-14
um i386_defconfig gcc-14
um randconfig-001-20260128 gcc-11.5.0
um randconfig-002-20260128 gcc-11.5.0
um x86_64_defconfig gcc-14
x86_64 allmodconfig clang-20
x86_64 allnoconfig clang-20
x86_64 allnoconfig clang-22
x86_64 allyesconfig clang-20
x86_64 buildonly-randconfig-001-20260128 gcc-14
x86_64 buildonly-randconfig-002-20260128 gcc-14
x86_64 buildonly-randconfig-003-20260128 gcc-14
x86_64 buildonly-randconfig-004-20260128 gcc-14
x86_64 buildonly-randconfig-005-20260128 gcc-14
x86_64 buildonly-randconfig-006-20260128 gcc-14
x86_64 defconfig gcc-14
x86_64 kexec clang-20
x86_64 randconfig-001-20260128 gcc-13
x86_64 randconfig-002-20260128 gcc-13
x86_64 randconfig-003-20260128 gcc-13
x86_64 randconfig-004-20260128 gcc-13
x86_64 randconfig-005-20260128 gcc-13
x86_64 randconfig-006-20260128 gcc-13
x86_64 randconfig-011-20260128 clang-20
x86_64 randconfig-012-20260128 clang-20
x86_64 randconfig-013-20260128 clang-20
x86_64 randconfig-014-20260128 clang-20
x86_64 randconfig-015-20260128 clang-20
x86_64 randconfig-016-20260128 clang-20
x86_64 randconfig-071-20260128 clang-20
x86_64 randconfig-072-20260128 clang-20
x86_64 randconfig-073-20260128 clang-20
x86_64 randconfig-074-20260128 clang-20
x86_64 randconfig-075-20260128 clang-20
x86_64 randconfig-076-20260128 clang-20
x86_64 rhel-9.4 clang-20
x86_64 rhel-9.4-bpf gcc-14
x86_64 rhel-9.4-func clang-20
x86_64 rhel-9.4-kselftests clang-20
x86_64 rhel-9.4-kunit gcc-14
x86_64 rhel-9.4-ltp gcc-14
x86_64 rhel-9.4-rust clang-20
xtensa allnoconfig clang-22
xtensa allnoconfig gcc-15.2.0
xtensa allyesconfig clang-22
xtensa allyesconfig gcc-15.2.0
xtensa cadence_csp_defconfig gcc-15.2.0
xtensa generic_kc705_defconfig gcc-15.2.0
xtensa randconfig-001-20260128 gcc-11.5.0
xtensa randconfig-002-20260128 gcc-11.5.0
xtensa xip_kc705_defconfig clang-22
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH] printk, vt, fbcon: Remove console_conditional_schedule()
From: Petr Mladek @ 2026-01-28 9:02 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: linux-kernel, linux-serial, linux-fbdev, dri-devel,
linux-rt-devel, Steven Rostedt, John Ogness, Sergey Senozhatsky,
Greg Kroah-Hartman, Jiri Slaby, Simona Vetter, Helge Deller
In-Reply-To: <20260126180836.SNCdMW2f@linutronix.de>
On Mon 2026-01-26 19:08:36, Sebastian Andrzej Siewior wrote:
> do_con_write(), fbcon_redraw.*() invoke console_conditional_schedule()
> which is a conditional scheduling point based on printk's internal
> variables console_may_schedule. It may only be used if the console lock
> is acquired for instance via console_lock() or console_trylock().
>
> Prinkt sets the internal variable to 1 (and allows to schedule)
> if the console lock has been acquired via console_lock(). The trylock
> does not allow it.
>
> The console_conditional_schedule() invocation in do_con_write() is
> invoked shortly before console_unlock().
> The console_conditional_schedule() invocation in fbcon_redraw.*()
> original from fbcon_scroll() / vt's con_scroll() which originate from a
> line feed.
>
> In console_unlock() the variable is set to 0 (forbids to schedule) and
> it tries to schedule while making progress printing. This is brand new
> compared to when console_conditional_schedule() was added in v2.4.9.11.
>
> In v2.6.38-rc3, console_unlock() (started its existence) iterated over
> all consoles and flushed them with disabled interrupts. A scheduling
> attempt here was not possible, it relied that a long print scheduled
> before console_unlock().
>
> Since commit 8d91f8b15361d ("printk: do cond_resched() between lines
> while outputting to consoles"), which appeared in v4.5-rc1,
> console_unlock() attempts to schedule if it was allowed to schedule
> while during console_lock(). Each record is idealy one line so after
> every line feed.
>
> This console_conditional_schedule() is also only relevant on
> PREEMPT_NONE and PREEMPT_VOLUNTARY builds. In other configurations
> cond_resched() becomes a nop and has no impact.
>
> I'm bringing this all up just proof that it is not required anymore. It
> becomes a problem on a PREEMPT_RT build with debug code enabled because
> that might_sleep() in cond_resched() remains and triggers a warnings.
> This is due to
>
> legacy_kthread_func-> console_flush_one_record -> vt_console_print-> lf
> -> con_scroll -> fbcon_scroll
>
> and vt_console_print() acquires a spinlock_t which does not allow a
> voluntary schedule. There is no need to fb_scroll() to schedule since
> console_flush_one_record() attempts to schedule after each line.
> !PREEMPT_RT is not affected because the legacy printing thread is only
> enabled on PREEMPT_RT builds.
>
> Therefore I suggest to remove console_conditional_schedule().
>
> Cc: Simona Vetter <simona@ffwll.ch>
> Cc: Helge Deller <deller@gmx.de>
> Cc: linux-fbdev@vger.kernel.org
> Cc: dri-devel@lists.freedesktop.org
> Fixes: 5f53ca3ff83b4 ("printk: Implement legacy printer kthread for PREEMPT_RT")
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Just for record. This change looks OK from printk() POV.
printk() does console_trylock() and calls console_unlock()
with preemption disabled anyway, see vprintk_emit().
VT code still synchronizes some operations using console_lock().
It is possible that some non-printk related operations rely
on this. But it is hard to say. It might actually be a good
idea to find it out.
Also I have seen many printk-related softlockups. But they
were always caused by slow serial consoles. I can't remember
any in VT code.
Feel free to use:
Acked-by: Petr Mladek <pmladek@suse.com> # from printk() POV
Best Regards,
Petr
^ permalink raw reply
* [syzbot] [serial?] general protection fault in fn_enter
From: syzbot @ 2026-01-28 0:35 UTC (permalink / raw)
To: gregkh, jirislaby, linux-kernel, linux-serial, syzkaller-bugs
Hello,
syzbot found the following issue on:
HEAD commit: 615aad0f61e0 Add linux-next specific files for 20260126
git tree: linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=1625a6ef980000
kernel config: https://syzkaller.appspot.com/x/.config?x=d51c584a7396ddf1
dashboard link: https://syzkaller.appspot.com/bug?extid=bbe4d8bcf8e458140bb8
compiler: Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=11747d2a580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=1190d05a580000
Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/5318e5f027be/disk-615aad0f.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/d165e561fa49/vmlinux-615aad0f.xz
kernel image: https://storage.googleapis.com/syzbot-assets/fb0e01c90aa5/bzImage-615aad0f.xz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+bbe4d8bcf8e458140bb8@syzkaller.appspotmail.com
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000038: 0000 [#1] SMP KASAN PTI
KASAN: null-ptr-deref in range [0x00000000000001c0-0x00000000000001c7]
CPU: 1 UID: 0 PID: 6023 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/13/2026
RIP: 0010:__queue_work+0xa2/0xf90 kernel/workqueue.c:2269
Code: 11 31 ff 89 ee e8 4e f4 37 00 85 ed 0f 85 ef 0c 00 00 e8 01 f0 37 00 4d 8d b7 c0 01 00 00 4c 89 f0 48 c1 e8 03 48 89 44 24 28 <42> 0f b6 04 20 84 c0 0f 85 22 0d 00 00 4c 89 34 24 41 8b 2e 89 ee
RSP: 0018:ffffc900036f74b8 EFLAGS: 00010002
RAX: 0000000000000038 RBX: 0000000000000008 RCX: ffff888031643c80
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000000 R08: ffff88813ff72017 R09: 1ffff11027fee402
R10: dffffc0000000000 R11: ffffed1027fee403 R12: dffffc0000000000
R13: ffff88813ff72010 R14: 00000000000001c0 R15: 0000000000000000
FS: 0000555577a96500(0000) GS:ffff8881253b4000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fccc4f840c0 CR3: 000000007b780000 CR4: 00000000003526f0
Call Trace:
<TASK>
queue_work_on+0x106/0x1d0 kernel/workqueue.c:2405
put_queue drivers/tty/vt/keyboard.c:328 [inline]
fn_enter+0x45d/0x900 drivers/tty/vt/keyboard.c:480
kbd_keycode drivers/tty/vt/keyboard.c:1497 [inline]
kbd_event+0x2ec1/0x40d0 drivers/tty/vt/keyboard.c:1515
input_handle_events_default+0xd4/0x1a0 drivers/input/input.c:2541
input_pass_values+0x288/0x890 drivers/input/input.c:128
input_event_dispose+0x330/0x6b0 drivers/input/input.c:342
input_inject_event+0x1dd/0x340 drivers/input/input.c:424
evdev_write+0x325/0x4c0 drivers/input/evdev.c:528
vfs_write+0x29a/0xb90 fs/read_write.c:686
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xe2/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fccc4f9aeb9
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffe15585178 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007fccc5215fa0 RCX: 00007fccc4f9aeb9
RDX: 00000000000012d8 RSI: 0000200000000040 RDI: 0000000000000003
RBP: 00007fccc5008c1f R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fccc5215fac R14: 00007fccc5215fa0 R15: 00007fccc5215fa0
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:__queue_work+0xa2/0xf90 kernel/workqueue.c:2269
Code: 11 31 ff 89 ee e8 4e f4 37 00 85 ed 0f 85 ef 0c 00 00 e8 01 f0 37 00 4d 8d b7 c0 01 00 00 4c 89 f0 48 c1 e8 03 48 89 44 24 28 <42> 0f b6 04 20 84 c0 0f 85 22 0d 00 00 4c 89 34 24 41 8b 2e 89 ee
RSP: 0018:ffffc900036f74b8 EFLAGS: 00010002
RAX: 0000000000000038 RBX: 0000000000000008 RCX: ffff888031643c80
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000000 R08: ffff88813ff72017 R09: 1ffff11027fee402
R10: dffffc0000000000 R11: ffffed1027fee403 R12: dffffc0000000000
R13: ffff88813ff72010 R14: 00000000000001c0 R15: 0000000000000000
FS: 0000555577a96500(0000) GS:ffff8881253b4000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fccc4f840c0 CR3: 000000007b780000 CR4: 00000000003526f0
----------------
Code disassembly (best guess), 1 bytes skipped:
0: 31 ff xor %edi,%edi
2: 89 ee mov %ebp,%esi
4: e8 4e f4 37 00 call 0x37f457
9: 85 ed test %ebp,%ebp
b: 0f 85 ef 0c 00 00 jne 0xd00
11: e8 01 f0 37 00 call 0x37f017
16: 4d 8d b7 c0 01 00 00 lea 0x1c0(%r15),%r14
1d: 4c 89 f0 mov %r14,%rax
20: 48 c1 e8 03 shr $0x3,%rax
24: 48 89 44 24 28 mov %rax,0x28(%rsp)
* 29: 42 0f b6 04 20 movzbl (%rax,%r12,1),%eax <-- trapping instruction
2e: 84 c0 test %al,%al
30: 0f 85 22 0d 00 00 jne 0xd58
36: 4c 89 34 24 mov %r14,(%rsp)
3a: 41 8b 2e mov (%r14),%ebp
3d: 89 ee mov %ebp,%esi
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup
^ permalink raw reply
* [syzbot] [serial?] general protection fault in k_pad
From: syzbot @ 2026-01-28 0:34 UTC (permalink / raw)
To: gregkh, jirislaby, linux-kernel, linux-serial, syzkaller-bugs
Hello,
syzbot found the following issue on:
HEAD commit: 615aad0f61e0 Add linux-next specific files for 20260126
git tree: linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=1504e5ac580000
kernel config: https://syzkaller.appspot.com/x/.config?x=d51c584a7396ddf1
dashboard link: https://syzkaller.appspot.com/bug?extid=4b914439b1ce3f6b1baf
compiler: Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=11b2198a580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=15947d2a580000
Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/5318e5f027be/disk-615aad0f.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/d165e561fa49/vmlinux-615aad0f.xz
kernel image: https://storage.googleapis.com/syzbot-assets/fb0e01c90aa5/bzImage-615aad0f.xz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+4b914439b1ce3f6b1baf@syzkaller.appspotmail.com
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000038: 0000 [#1] SMP KASAN PTI
KASAN: null-ptr-deref in range [0x00000000000001c0-0x00000000000001c7]
CPU: 1 UID: 0 PID: 6021 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/13/2026
RIP: 0010:__queue_work+0xa2/0xf90 kernel/workqueue.c:2269
Code: 11 31 ff 89 ee e8 4e f4 37 00 85 ed 0f 85 ef 0c 00 00 e8 01 f0 37 00 4d 8d b7 c0 01 00 00 4c 89 f0 48 c1 e8 03 48 89 44 24 28 <42> 0f b6 04 20 84 c0 0f 85 22 0d 00 00 4c 89 34 24 41 8b 2e 89 ee
RSP: 0018:ffffc900030174d8 EFLAGS: 00010002
RAX: 0000000000000038 RBX: 0000000000000008 RCX: ffff88802ea33c80
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000000 R08: ffff88813ff72017 R09: 1ffff11027fee402
R10: dffffc0000000000 R11: ffffed1027fee403 R12: dffffc0000000000
R13: ffff88813ff72010 R14: 00000000000001c0 R15: 0000000000000000
FS: 000055558b419500(0000) GS:ffff8881253b4000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000001b30a63fff CR3: 000000003698e000 CR4: 00000000003526f0
Call Trace:
<TASK>
queue_work_on+0x106/0x1d0 kernel/workqueue.c:2405
put_queue drivers/tty/vt/keyboard.c:328 [inline]
k_pad+0x4c4/0xa90 drivers/tty/vt/keyboard.c:832
kbd_keycode drivers/tty/vt/keyboard.c:1497 [inline]
kbd_event+0x2ec1/0x40d0 drivers/tty/vt/keyboard.c:1515
input_handle_events_default+0xd4/0x1a0 drivers/input/input.c:2541
input_pass_values+0x288/0x890 drivers/input/input.c:128
input_event_dispose+0x330/0x6b0 drivers/input/input.c:342
input_inject_event+0x1dd/0x340 drivers/input/input.c:424
evdev_write+0x325/0x4c0 drivers/input/evdev.c:528
vfs_write+0x29a/0xb90 fs/read_write.c:686
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xe2/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fcc5759aeb9
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffc141a1f98 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007fcc57815fa0 RCX: 00007fcc5759aeb9
RDX: 0000000000002250 RSI: 0000200000000040 RDI: 0000000000000003
RBP: 00007fcc57608c1f R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fcc57815fac R14: 00007fcc57815fa0 R15: 00007fcc57815fa0
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:__queue_work+0xa2/0xf90 kernel/workqueue.c:2269
Code: 11 31 ff 89 ee e8 4e f4 37 00 85 ed 0f 85 ef 0c 00 00 e8 01 f0 37 00 4d 8d b7 c0 01 00 00 4c 89 f0 48 c1 e8 03 48 89 44 24 28 <42> 0f b6 04 20 84 c0 0f 85 22 0d 00 00 4c 89 34 24 41 8b 2e 89 ee
RSP: 0018:ffffc900030174d8 EFLAGS: 00010002
RAX: 0000000000000038 RBX: 0000000000000008 RCX: ffff88802ea33c80
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000000 R08: ffff88813ff72017 R09: 1ffff11027fee402
R10: dffffc0000000000 R11: ffffed1027fee403 R12: dffffc0000000000
R13: ffff88813ff72010 R14: 00000000000001c0 R15: 0000000000000000
FS: 000055558b419500(0000) GS:ffff8881253b4000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000001b30a63fff CR3: 000000003698e000 CR4: 00000000003526f0
----------------
Code disassembly (best guess), 1 bytes skipped:
0: 31 ff xor %edi,%edi
2: 89 ee mov %ebp,%esi
4: e8 4e f4 37 00 call 0x37f457
9: 85 ed test %ebp,%ebp
b: 0f 85 ef 0c 00 00 jne 0xd00
11: e8 01 f0 37 00 call 0x37f017
16: 4d 8d b7 c0 01 00 00 lea 0x1c0(%r15),%r14
1d: 4c 89 f0 mov %r14,%rax
20: 48 c1 e8 03 shr $0x3,%rax
24: 48 89 44 24 28 mov %rax,0x28(%rsp)
* 29: 42 0f b6 04 20 movzbl (%rax,%r12,1),%eax <-- trapping instruction
2e: 84 c0 test %al,%al
30: 0f 85 22 0d 00 00 jne 0xd58
36: 4c 89 34 24 mov %r14,(%rsp)
3a: 41 8b 2e mov (%r14),%ebp
3d: 89 ee mov %ebp,%esi
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup
^ permalink raw reply
* [syzbot] [serial?] general protection fault in to_utf8
From: syzbot @ 2026-01-28 0:34 UTC (permalink / raw)
To: gregkh, jirislaby, linux-kernel, linux-serial, syzkaller-bugs
Hello,
syzbot found the following issue on:
HEAD commit: 615aad0f61e0 Add linux-next specific files for 20260126
git tree: linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=147b432a580000
kernel config: https://syzkaller.appspot.com/x/.config?x=d51c584a7396ddf1
dashboard link: https://syzkaller.appspot.com/bug?extid=3f83d97f1d51ddaabd8a
compiler: Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=16201fb3980000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=11bba802580000
Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/5318e5f027be/disk-615aad0f.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/d165e561fa49/vmlinux-615aad0f.xz
kernel image: https://storage.googleapis.com/syzbot-assets/fb0e01c90aa5/bzImage-615aad0f.xz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+3f83d97f1d51ddaabd8a@syzkaller.appspotmail.com
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000038: 0000 [#1] SMP KASAN PTI
KASAN: null-ptr-deref in range [0x00000000000001c0-0x00000000000001c7]
CPU: 1 UID: 0 PID: 6053 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/13/2026
RIP: 0010:__queue_work+0xa2/0xf90 kernel/workqueue.c:2269
Code: 11 31 ff 89 ee e8 4e f4 37 00 85 ed 0f 85 ef 0c 00 00 e8 01 f0 37 00 4d 8d b7 c0 01 00 00 4c 89 f0 48 c1 e8 03 48 89 44 24 28 <42> 0f b6 04 20 84 c0 0f 85 22 0d 00 00 4c 89 34 24 41 8b 2e 89 ee
RSP: 0018:ffffc900036c7318 EFLAGS: 00010002
RAX: 0000000000000038 RBX: 0000000000000008 RCX: ffff88802f848000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000000 R08: ffff88813ff72017 R09: 1ffff11027fee402
R10: dffffc0000000000 R11: ffffed1027fee403 R12: dffffc0000000000
R13: ffff88813ff72010 R14: 00000000000001c0 R15: 0000000000000000
FS: 0000555556b5d500(0000) GS:ffff8881253b4000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000001b31663fff CR3: 0000000075e7c000 CR4: 00000000003526f0
Call Trace:
<TASK>
queue_work_on+0x106/0x1d0 kernel/workqueue.c:2405
put_queue drivers/tty/vt/keyboard.c:328 [inline]
to_utf8+0x872/0x1ad0 drivers/tty/vt/keyboard.c:-1
put_queue_utf8 drivers/tty/vt/keyboard.c:382 [inline]
k_unicode drivers/tty/vt/keyboard.c:683 [inline]
k_self+0x326/0x7e0 drivers/tty/vt/keyboard.c:701
kbd_keycode drivers/tty/vt/keyboard.c:1497 [inline]
kbd_event+0x2ec1/0x40d0 drivers/tty/vt/keyboard.c:1515
input_handle_events_default+0xd4/0x1a0 drivers/input/input.c:2541
input_pass_values+0x288/0x890 drivers/input/input.c:128
input_event_dispose+0x330/0x6b0 drivers/input/input.c:342
input_inject_event+0x1dd/0x340 drivers/input/input.c:424
evdev_write+0x325/0x4c0 drivers/input/evdev.c:528
vfs_write+0x29a/0xb90 fs/read_write.c:686
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xe2/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fa3fd19aeb9
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fffb1030708 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007fa3fd415fa0 RCX: 00007fa3fd19aeb9
RDX: 0000000000002250 RSI: 0000200000000040 RDI: 0000000000000003
RBP: 00007fa3fd208c1f R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fa3fd415fac R14: 00007fa3fd415fa0 R15: 00007fa3fd415fa0
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:__queue_work+0xa2/0xf90 kernel/workqueue.c:2269
Code: 11 31 ff 89 ee e8 4e f4 37 00 85 ed 0f 85 ef 0c 00 00 e8 01 f0 37 00 4d 8d b7 c0 01 00 00 4c 89 f0 48 c1 e8 03 48 89 44 24 28 <42> 0f b6 04 20 84 c0 0f 85 22 0d 00 00 4c 89 34 24 41 8b 2e 89 ee
RSP: 0018:ffffc900036c7318 EFLAGS: 00010002
RAX: 0000000000000038 RBX: 0000000000000008 RCX: ffff88802f848000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000000 R08: ffff88813ff72017 R09: 1ffff11027fee402
R10: dffffc0000000000 R11: ffffed1027fee403 R12: dffffc0000000000
R13: ffff88813ff72010 R14: 00000000000001c0 R15: 0000000000000000
FS: 0000555556b5d500(0000) GS:ffff8881253b4000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000001b31663fff CR3: 0000000075e7c000 CR4: 00000000003526f0
----------------
Code disassembly (best guess), 1 bytes skipped:
0: 31 ff xor %edi,%edi
2: 89 ee mov %ebp,%esi
4: e8 4e f4 37 00 call 0x37f457
9: 85 ed test %ebp,%ebp
b: 0f 85 ef 0c 00 00 jne 0xd00
11: e8 01 f0 37 00 call 0x37f017
16: 4d 8d b7 c0 01 00 00 lea 0x1c0(%r15),%r14
1d: 4c 89 f0 mov %r14,%rax
20: 48 c1 e8 03 shr $0x3,%rax
24: 48 89 44 24 28 mov %rax,0x28(%rsp)
* 29: 42 0f b6 04 20 movzbl (%rax,%r12,1),%eax <-- trapping instruction
2e: 84 c0 test %al,%al
30: 0f 85 22 0d 00 00 jne 0xd58
36: 4c 89 34 24 mov %r14,(%rsp)
3a: 41 8b 2e mov (%r14),%ebp
3d: 89 ee mov %ebp,%esi
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup
^ permalink raw reply
* [PATCH] vt: save/restore unicode screen buffer for alternate screen
From: Nicolas Pitre @ 2026-01-27 22:56 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Calixte Pernot; +Cc: linux-kernel, linux-serial
The alternate screen support added by commit 23743ba64709 ("vt: add
support for smput/rmput escape codes") only saves and restores the
regular screen buffer (vc_origin), but completely ignores the corresponding
unicode screen buffer (vc_uni_lines) creating a messed-up display.
Add vc_saved_uni_lines to save the unicode screen buffer when entering
the alternate screen, and restore it when leaving. Also ensure proper
cleanup in reset_terminal() and vc_deallocate().
Fixes: 23743ba64709 ("vt: add support for smput/rmput escape codes")
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
---
drivers/tty/vt/vt.c | 8 ++++++++
include/linux/console_struct.h | 1 +
2 files changed, 9 insertions(+)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 59b4b5e126ba..83a285577708 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1345,6 +1345,8 @@ struct vc_data *vc_deallocate(unsigned int currcons)
kfree(vc->vc_saved_screen);
vc->vc_saved_screen = NULL;
}
+ vc_uniscr_free(vc->vc_saved_uni_lines);
+ vc->vc_saved_uni_lines = NULL;
}
return vc;
}
@@ -1890,6 +1892,8 @@ static void enter_alt_screen(struct vc_data *vc)
vc->vc_saved_screen = kmemdup((u16 *)vc->vc_origin, size, GFP_KERNEL);
if (vc->vc_saved_screen == NULL)
return;
+ vc->vc_saved_uni_lines = vc->vc_uni_lines;
+ vc->vc_uni_lines = NULL;
vc->vc_saved_rows = vc->vc_rows;
vc->vc_saved_cols = vc->vc_cols;
save_cur(vc);
@@ -1911,6 +1915,8 @@ static void leave_alt_screen(struct vc_data *vc)
dest = ((u16 *)vc->vc_origin) + r * vc->vc_cols;
memcpy(dest, src, 2 * cols);
}
+ vc_uniscr_set(vc, vc->vc_saved_uni_lines);
+ vc->vc_saved_uni_lines = NULL;
restore_cur(vc);
/* Update the entire screen */
if (con_should_update(vc))
@@ -2233,6 +2239,8 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
if (vc->vc_saved_screen != NULL) {
kfree(vc->vc_saved_screen);
vc->vc_saved_screen = NULL;
+ vc_uniscr_free(vc->vc_saved_uni_lines);
+ vc->vc_saved_uni_lines = NULL;
vc->vc_saved_rows = 0;
vc->vc_saved_cols = 0;
}
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index 13b35637bd5a..d5ca855116df 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -160,6 +160,7 @@ struct vc_data {
struct uni_pagedict **uni_pagedict_loc; /* [!] Location of uni_pagedict variable for this console */
u32 **vc_uni_lines; /* unicode screen content */
u16 *vc_saved_screen;
+ u32 **vc_saved_uni_lines;
unsigned int vc_saved_cols;
unsigned int vc_saved_rows;
/* additional information is in vt_kern.h */
--
2.52.0
^ permalink raw reply related
* Re: [PATCH v2] serial: 8250: omap: set out-of-band wakeup if wakeup pinctrl exists
From: Kevin Hilman @ 2026-01-27 20:13 UTC (permalink / raw)
To: Kendall Willis, Greg Kroah-Hartman, Jiri Slaby
Cc: d-gole, vishalm, sebin.francis, msp, linux-kernel, linux-serial,
Kendall Willis
In-Reply-To: <20260116-uart-wakeup-v2-1-0078ae9996e4@ti.com>
Kendall Willis <k-willis@ti.com> writes:
> In TI K3 SoCs, I/O daisy chaining is used to allow wakeup from UART when the
> UART controller is off. Set UART device as wakeup capable using out-of-band
> wakeup if the 'wakeup' pinctrl state exists and the device may wakeup.
>
> Reviewed-by: Dhruva Gole <d-gole@ti.com>
> Signed-off-by: Kendall Willis <k-willis@ti.com>
Reviewed-by: Kevin Hilman <khilman@baylibre.com>
^ permalink raw reply
* Re: [PATCH] printk, vt, fbcon: Remove console_conditional_schedule()
From: Helge Deller @ 2026-01-27 18:05 UTC (permalink / raw)
To: Greg Kroah-Hartman, Sebastian Andrzej Siewior
Cc: linux-kernel, linux-serial, linux-fbdev, dri-devel,
linux-rt-devel, Petr Mladek, Steven Rostedt, John Ogness,
Sergey Senozhatsky, Jiri Slaby, Simona Vetter
In-Reply-To: <2026012757-voting-griminess-ca35@gregkh>
On 1/27/26 15:24, Greg Kroah-Hartman wrote:
> On Mon, Jan 26, 2026 at 07:08:36PM +0100, Sebastian Andrzej Siewior wrote:
>> do_con_write(), fbcon_redraw.*() invoke console_conditional_schedule()
>> which is a conditional scheduling point based on printk's internal
>> variables console_may_schedule. It may only be used if the console lock
>> is acquired for instance via console_lock() or console_trylock().
>>
>> Prinkt sets the internal variable to 1 (and allows to schedule)
>> if the console lock has been acquired via console_lock(). The trylock
>> does not allow it.
>>
>> The console_conditional_schedule() invocation in do_con_write() is
>> invoked shortly before console_unlock().
>> The console_conditional_schedule() invocation in fbcon_redraw.*()
>> original from fbcon_scroll() / vt's con_scroll() which originate from a
>> line feed.
>>
>> In console_unlock() the variable is set to 0 (forbids to schedule) and
>> it tries to schedule while making progress printing. This is brand new
>> compared to when console_conditional_schedule() was added in v2.4.9.11.
>>
>> In v2.6.38-rc3, console_unlock() (started its existence) iterated over
>> all consoles and flushed them with disabled interrupts. A scheduling
>> attempt here was not possible, it relied that a long print scheduled
>> before console_unlock().
>>
>> Since commit 8d91f8b15361d ("printk: do cond_resched() between lines
>> while outputting to consoles"), which appeared in v4.5-rc1,
>> console_unlock() attempts to schedule if it was allowed to schedule
>> while during console_lock(). Each record is idealy one line so after
>> every line feed.
>>
>> This console_conditional_schedule() is also only relevant on
>> PREEMPT_NONE and PREEMPT_VOLUNTARY builds. In other configurations
>> cond_resched() becomes a nop and has no impact.
>>
>> I'm bringing this all up just proof that it is not required anymore. It
>> becomes a problem on a PREEMPT_RT build with debug code enabled because
>> that might_sleep() in cond_resched() remains and triggers a warnings.
>> This is due to
>>
>> legacy_kthread_func-> console_flush_one_record -> vt_console_print-> lf
>> -> con_scroll -> fbcon_scroll
>>
>> and vt_console_print() acquires a spinlock_t which does not allow a
>> voluntary schedule. There is no need to fb_scroll() to schedule since
>> console_flush_one_record() attempts to schedule after each line.
>> !PREEMPT_RT is not affected because the legacy printing thread is only
>> enabled on PREEMPT_RT builds.
>>
>> Therefore I suggest to remove console_conditional_schedule().
>>
>> Cc: Simona Vetter <simona@ffwll.ch>
>> Cc: Helge Deller <deller@gmx.de>
>> Cc: linux-fbdev@vger.kernel.org
>> Cc: dri-devel@lists.freedesktop.org
>> Fixes: 5f53ca3ff83b4 ("printk: Implement legacy printer kthread for PREEMPT_RT")
>> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>> ---
>>
>> A follow-up to
>> https://lore.kernel.org/all/20260114145955.d924Z-zu@linutronix.de/
>>
>> drivers/tty/vt/vt.c | 1 -
>> drivers/video/fbdev/core/fbcon.c | 6 ------
>> include/linux/console.h | 1 -
>> kernel/printk/printk.c | 16 ----------------
>> 4 files changed, 24 deletions(-)
>>
>> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
>> [....]
>
> No objection from me about removing this if it's not needed anymore!
>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
I've added it to the fbdev git tree to get some testing....
Thanks!
Helge
^ permalink raw reply
* Re: [PATCH 6/6] serial: 8250_dw: Ensure BUSY is deasserted
From: John Ogness @ 2026-01-27 16:19 UTC (permalink / raw)
To: Andy Shevchenko, Ilpo Järvinen, Petr Mladek
Cc: Greg Kroah-Hartman, Jiri Slaby, linux-serial, qianfan Zhao,
Adriana Nicolae, Markus Mayer, Tim Kryger, Matt Porter,
Heikki Krogerus, Jamie Iles, LKML, stable, Bandal, Shankar,
Murthy, Shanth
In-Reply-To: <aXjHZQnIFjfPabdU@smile.fi.intel.com>
On 2026-01-27, Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:
>> > > + if (d->in_idle) {
>> >
>> > > + /*
>> > > + * FIXME: this deadlocks if port->lock is already held
>> > > + * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
>> > > + */
>> >
>> > Hmm... That FIXME should gone since we have non-blocking consoles, no?
>>
>> No, lockdep still gets angry if printing is used while holding port's
>> lock.
>
> Hmm... Let's ask PRINTK people about this. John, do we still have a gap
> with nbcon? Or did I misunderstand the scope of its use?
The 8250 has not yet been converted to a nbcon. I am still working on
it. Unfortunately I got side-tracked first fixing the broken 8250
console hardware-flow-control support. :-/
So the comment is correct. Once the driver converts to nbcon, the
dev_err() is fine.
Note that if the message is important, you could use a printk_deferred()
here with a FIXME to say to convert it to dev_err() once the 8250
supports nbcon.
John Ogness
^ permalink raw reply
* Re: [PATCH 6/6] serial: 8250_dw: Ensure BUSY is deasserted
From: Ilpo Järvinen @ 2026-01-27 14:45 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Jiri Slaby, linux-serial, Andy Shevchenko, qianfan Zhao,
Adriana Nicolae, Markus Mayer, Tim Kryger, Matt Porter,
Heikki Krogerus, Jamie Iles, LKML, stable, Bandal, Shankar,
Murthy, Shanth
In-Reply-To: <2026012608-slicing-vehicular-6987@gregkh>
[-- Attachment #1: Type: text/plain, Size: 2662 bytes --]
On Mon, 26 Jan 2026, Greg Kroah-Hartman wrote:
> On Fri, Jan 23, 2026 at 07:27:39PM +0200, Ilpo Järvinen wrote:
> > DW UART cannot write to LCR, DLL, and DLH while BUSY is asserted.
> > Existance of BUSY depends on uart_16550_compatible, if UART HW is
> > configured with 16550 compatible those registers can always be written.
> >
> > There currently is dw8250_force_idle() which attempts to archive
> > non-BUSY state by disabling FIFO, however, the solution is unreliable
> > when Rx keeps getting more and more characters.
> >
> > Create a sequence of operations to enforce that ensures UART cannot
> > keep BUSY asserted indefinitely. The new sequence relies on enabling
> > loopback mode temporarily to prevent incoming Rx characters keeping
> > UART BUSY.
> >
> > Ensure no Tx in ongoing while the UART is switches into the loopback
> > mode (requires exporting serial8250_fifo_wait_for_lsr_thre() and adding
> > DMA Tx pause/resume functions).
> >
> > According to tests performed by Adriana Nicolae <adriana@arista.com>,
> > simply disabling FIFO or clearing FIFOs only once does not always
> > ensure BUSY is deasserted but up to two tries may be needed. This could
> > be related to ongoing Rx of a character (a guess, not known for sure).
> > Therefore, retry FIFO clearing a few times (retry limit 4 is arbitrary
> > number but using, e.g., p->fifosize seems overly large). Tests
> > performed by others did not exhibit similar challenge but it does not
> > seem harmful to leave the FIFO clearing loop in place for all DW UARTs
> > with BUSY functionality.
> >
> > Use the new dw8250_idle_enter/exit() to do divisor writes and LCR
> > writes. In case of plain LCR writes, opportunistically try to update
> > LCR first and only invoke dw8250_idle_enter() if the write did not
> > succeed (it has been observed that in practice most LCR writes do
> > succeed without complications).
> >
> > This issue was first reported by qianfan Zhao who put lots of debugging
> > effort into understanding the solution space.
> >
> > Fixes: c49436b657d0 ("serial: 8250_dw: Improve unwritable LCR workaround")
> > Fixes: 7d4008ebb1c9 ("tty: add a DesignWare 8250 driver")
> > Cc: <stable@vger.kernel.org>
>
> Why is patch 6/6 only marked for stable? If this is needed "now",
> shouldn't this be a separate patch? Do you need all of the first 5 for
> this to work properly?
Some of those are really dependencies but I'll try to improve this
situation for v2 and add a few more Fixes tag to the introducing commits.
> I can't take this series as-is because I don't know how to route it :(
--
i.
^ permalink raw reply
* Re: [PATCH 6/6] serial: 8250_dw: Ensure BUSY is deasserted
From: Ilpo Järvinen @ 2026-01-27 14:40 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Petr Mladek, John Ogness, Greg Kroah-Hartman, Jiri Slaby,
linux-serial, qianfan Zhao, Adriana Nicolae, Markus Mayer,
Tim Kryger, Matt Porter, Heikki Krogerus, Jamie Iles, LKML,
stable, Bandal, Shankar, Murthy, Shanth
In-Reply-To: <aXjHZQnIFjfPabdU@smile.fi.intel.com>
[-- Attachment #1: Type: text/plain, Size: 4266 bytes --]
On Tue, 27 Jan 2026, Andy Shevchenko wrote:
> On Tue, Jan 27, 2026 at 03:35:27PM +0200, Ilpo Järvinen wrote:
> > On Sat, 24 Jan 2026, Andy Shevchenko wrote:
> > > On Fri, Jan 23, 2026 at 07:27:39PM +0200, Ilpo Järvinen wrote:
>
> +Cc: printk people to check on printing from a serial driver routines.
>
> ...
>
> > > > + /* Prevent triggering interrupt from RBR filling */
> > > > + p->serial_out(p, UART_IER, 0);
> > >
> > > Do we specifically use callbacks directly and not wrappers all over the change?
> >
> > I guess it's just a habit, I suppose you meant using serial_port_in/out
> > instead. I can try to change those.
>
> Not (only) me. Jiri updated this driver (and many others) to use callbacks.
> That's why I added comments here and there about possible recursions.
Fair, this patch originated from a time way older than Jiri's conversion
(not an excuse, just stating how it came to be and I've not realized
using an old way until you mentioned).
> > > > + serial8250_fifo_wait_for_lsr_thre(up, p->fifosize);
> > > > + ndelay(p->frame_time);
> > >
> > > Wouldn't be a problem on lowest baud rates (exempli gratia 110)?
> >
> > Perhaps, but until somebody comes with an issue report related to 110, I'm
> > wondering if this really is worth trying to address. Any suggestion how is
> > welcome as well?
>
> Polling work? Timer?
And how do I prevent others messing with the UART during that time? While
IER is zeroed here (and I could make up->ier zero as well, I think), I
can't hold port's lock if I do either of those.
And I can't take the tty_port's mutex here either because the caller
is already holding port's lock (and it wouldn't prevent console writes
anyway as that, I think, only takes port's lock).
Sadly THRE/TEMT are not trustworthy as they are set before all those
non-data bits have been fully blasted on to the wire (we learned this with
rs485 half-duplex scenarios).
Normal behavioral exceptation what I have here is that userspace is sane
and won't do LCR write and tx at the same time but I don't know how to
ensure that. Perhaps using now > last xmit timestamp + frame_time could
avoid this unconditional delay.
> > > > + retries = 4; /* Arbitrary limit, 2 was always enough in tests */
> > > > + do {
> > > > + serial8250_clear_fifos(up);
> > > > + if (!(p->serial_in(p, usr_reg) & DW_UART_USR_BUSY))
> > > > + break;
> > > > + ndelay(p->frame_time);
> > > > + } while (--retries);
> > >
> > > read_poll_timeout_atomic() ? I assume it can't be used due to small frame time?
> >
> > Frame time is in nanoseconds yes. I did consider
> > read_poll_timeout_atomic() but it would have required nsec -> usec
> > conversion so I left this as it is.
>
> Yeah with the same issue on low baud rates. So far I think we need to consider
> 9600 as commonly used by the old HW (which may be connected to a modern PC with
> this new kernel running), so the frame time sounds like close to a millisecond.
> And this can be met in real life.
>
> Maybe put TODO/FIXME around these ndelay() calls?
Seems reasonable, I'll add that.
I'm under impression that all LCR writes occur from contexts that are
non-atomic by nature (except they are holding the port's lock, of course)
so this should never delay an interrupt handler.
> > > > + if (d->in_idle) {
> > >
> > > > + /*
> > > > + * FIXME: this deadlocks if port->lock is already held
> > > > + * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
> > > > + */
> > >
> > > Hmm... That FIXME should gone since we have non-blocking consoles, no?
> >
> > No, lockdep still gets angry if printing is used while holding port's
> > lock.
>
> Hmm... Let's ask PRINTK people about this. John, do we still have a gap
> with nbcon? Or did I misunderstand the scope of its use?
>
> > What would be possible though, is to mark the port's lock critical section
> > for print deferral (but it's outside the scope of this series). In case of
> > serial, it would be justified to use deferred printing (which is only
> > meant for special cases) because serial console and printing are related.
> >
> > > > + return;
> > > > + }
>
>
--
i.
^ permalink raw reply
* Re: [PATCH] printk, vt, fbcon: Remove console_conditional_schedule()
From: Greg Kroah-Hartman @ 2026-01-27 14:24 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: linux-kernel, linux-serial, linux-fbdev, dri-devel,
linux-rt-devel, Petr Mladek, Steven Rostedt, John Ogness,
Sergey Senozhatsky, Jiri Slaby, Simona Vetter, Helge Deller
In-Reply-To: <20260126180836.SNCdMW2f@linutronix.de>
On Mon, Jan 26, 2026 at 07:08:36PM +0100, Sebastian Andrzej Siewior wrote:
> do_con_write(), fbcon_redraw.*() invoke console_conditional_schedule()
> which is a conditional scheduling point based on printk's internal
> variables console_may_schedule. It may only be used if the console lock
> is acquired for instance via console_lock() or console_trylock().
>
> Prinkt sets the internal variable to 1 (and allows to schedule)
> if the console lock has been acquired via console_lock(). The trylock
> does not allow it.
>
> The console_conditional_schedule() invocation in do_con_write() is
> invoked shortly before console_unlock().
> The console_conditional_schedule() invocation in fbcon_redraw.*()
> original from fbcon_scroll() / vt's con_scroll() which originate from a
> line feed.
>
> In console_unlock() the variable is set to 0 (forbids to schedule) and
> it tries to schedule while making progress printing. This is brand new
> compared to when console_conditional_schedule() was added in v2.4.9.11.
>
> In v2.6.38-rc3, console_unlock() (started its existence) iterated over
> all consoles and flushed them with disabled interrupts. A scheduling
> attempt here was not possible, it relied that a long print scheduled
> before console_unlock().
>
> Since commit 8d91f8b15361d ("printk: do cond_resched() between lines
> while outputting to consoles"), which appeared in v4.5-rc1,
> console_unlock() attempts to schedule if it was allowed to schedule
> while during console_lock(). Each record is idealy one line so after
> every line feed.
>
> This console_conditional_schedule() is also only relevant on
> PREEMPT_NONE and PREEMPT_VOLUNTARY builds. In other configurations
> cond_resched() becomes a nop and has no impact.
>
> I'm bringing this all up just proof that it is not required anymore. It
> becomes a problem on a PREEMPT_RT build with debug code enabled because
> that might_sleep() in cond_resched() remains and triggers a warnings.
> This is due to
>
> legacy_kthread_func-> console_flush_one_record -> vt_console_print-> lf
> -> con_scroll -> fbcon_scroll
>
> and vt_console_print() acquires a spinlock_t which does not allow a
> voluntary schedule. There is no need to fb_scroll() to schedule since
> console_flush_one_record() attempts to schedule after each line.
> !PREEMPT_RT is not affected because the legacy printing thread is only
> enabled on PREEMPT_RT builds.
>
> Therefore I suggest to remove console_conditional_schedule().
>
> Cc: Simona Vetter <simona@ffwll.ch>
> Cc: Helge Deller <deller@gmx.de>
> Cc: linux-fbdev@vger.kernel.org
> Cc: dri-devel@lists.freedesktop.org
> Fixes: 5f53ca3ff83b4 ("printk: Implement legacy printer kthread for PREEMPT_RT")
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>
> A follow-up to
> https://lore.kernel.org/all/20260114145955.d924Z-zu@linutronix.de/
>
> drivers/tty/vt/vt.c | 1 -
> drivers/video/fbdev/core/fbcon.c | 6 ------
> include/linux/console.h | 1 -
> kernel/printk/printk.c | 16 ----------------
> 4 files changed, 24 deletions(-)
>
> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> index 59b4b5e126ba1..53daf7614b1af 100644
> --- a/drivers/tty/vt/vt.c
> +++ b/drivers/tty/vt/vt.c
> @@ -3236,7 +3236,6 @@ static int do_con_write(struct tty_struct *tty, const u8 *buf, int count)
> goto rescan_last_byte;
> }
> con_flush(vc, &draw);
> - console_conditional_schedule();
> notify_update(vc);
>
> return n;
No objection from me about removing this if it's not needed anymore!
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
^ permalink raw reply
* Re: [PATCH 6/6] serial: 8250_dw: Ensure BUSY is deasserted
From: Andy Shevchenko @ 2026-01-27 14:10 UTC (permalink / raw)
To: Ilpo Järvinen, Petr Mladek, John Ogness
Cc: Greg Kroah-Hartman, Jiri Slaby, linux-serial, qianfan Zhao,
Adriana Nicolae, Markus Mayer, Tim Kryger, Matt Porter,
Heikki Krogerus, Jamie Iles, LKML, stable, Bandal, Shankar,
Murthy, Shanth
In-Reply-To: <fc09f6fd-013f-25fd-484c-cac59b0a60b6@linux.intel.com>
On Tue, Jan 27, 2026 at 03:35:27PM +0200, Ilpo Järvinen wrote:
> On Sat, 24 Jan 2026, Andy Shevchenko wrote:
> > On Fri, Jan 23, 2026 at 07:27:39PM +0200, Ilpo Järvinen wrote:
+Cc: printk people to check on printing from a serial driver routines.
...
> > > + /* Prevent triggering interrupt from RBR filling */
> > > + p->serial_out(p, UART_IER, 0);
> >
> > Do we specifically use callbacks directly and not wrappers all over the change?
>
> I guess it's just a habit, I suppose you meant using serial_port_in/out
> instead. I can try to change those.
Not (only) me. Jiri updated this driver (and many others) to use callbacks.
That's why I added comments here and there about possible recursions.
...
> > > + serial8250_fifo_wait_for_lsr_thre(up, p->fifosize);
> > > + ndelay(p->frame_time);
> >
> > Wouldn't be a problem on lowest baud rates (exempli gratia 110)?
>
> Perhaps, but until somebody comes with an issue report related to 110, I'm
> wondering if this really is worth trying to address. Any suggestion how is
> welcome as well?
Polling work? Timer?
> > > + retries = 4; /* Arbitrary limit, 2 was always enough in tests */
> > > + do {
> > > + serial8250_clear_fifos(up);
> > > + if (!(p->serial_in(p, usr_reg) & DW_UART_USR_BUSY))
> > > + break;
> > > + ndelay(p->frame_time);
> > > + } while (--retries);
> >
> > read_poll_timeout_atomic() ? I assume it can't be used due to small frame time?
>
> Frame time is in nanoseconds yes. I did consider
> read_poll_timeout_atomic() but it would have required nsec -> usec
> conversion so I left this as it is.
Yeah with the same issue on low baud rates. So far I think we need to consider
9600 as commonly used by the old HW (which may be connected to a modern PC with
this new kernel running), so the frame time sounds like close to a millisecond.
And this can be met in real life.
Maybe put TODO/FIXME around these ndelay() calls?
> > > + if (d->in_idle) {
> >
> > > + /*
> > > + * FIXME: this deadlocks if port->lock is already held
> > > + * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
> > > + */
> >
> > Hmm... That FIXME should gone since we have non-blocking consoles, no?
>
> No, lockdep still gets angry if printing is used while holding port's
> lock.
Hmm... Let's ask PRINTK people about this. John, do we still have a gap
with nbcon? Or did I misunderstand the scope of its use?
> What would be possible though, is to mark the port's lock critical section
> for print deferral (but it's outside the scope of this series). In case of
> serial, it would be justified to use deferred printing (which is only
> meant for special cases) because serial console and printing are related.
>
> > > + return;
> > > + }
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 4/6] serial: 8250_dw: Rework IIR_NO_INT handling to stop interrupt storm
From: Andy Shevchenko @ 2026-01-27 13:57 UTC (permalink / raw)
To: Ilpo Järvinen
Cc: Greg Kroah-Hartman, Jiri Slaby, linux-serial, qianfan Zhao,
Adriana Nicolae, LKML, Bandal, Shankar, Murthy, Shanth
In-Reply-To: <be94eddc-0395-7215-df1e-ba5e718701f8@linux.intel.com>
On Tue, Jan 27, 2026 at 03:01:46PM +0200, Ilpo Järvinen wrote:
> On Sat, 24 Jan 2026, Andy Shevchenko wrote:
> > On Fri, Jan 23, 2026 at 07:27:37PM +0200, Ilpo Järvinen wrote:
...
> > > + d->no_int_count++;
> > > + if (d->no_int_count > 2 && quirks & DW_UART_QUIRK_IER_KICK)
> > > + dw8250_quirk_ier_kick(p);
> >
> > Usual way is to use modulo. And perhaps use 4 for the sake of avoiding
> > division:
> >
> > if (d->no_int_count == 3 && quirks & DW_UART_QUIRK_IER_KICK)
> > dw8250_quirk_ier_kick(p);
> >
> > d->no_int_count = (d->no_int_count + 1) % 4;
>
> This doesn't look equivalent code as it only fires on 4th NO_INT,
Correct, I forgot to clarify this in my original reply. Yes, bumping to
power-of-two for simplicity, but as you noticed it bumps also the loop to
"every 4th". (I was under impression that I wrote it somewhere else in
the reply, but now I see it's not the case.)
> but I guess the difference doesn't matter that much so changing to your
> suggestion so that the kick will only occurs on fourth NO_INT interrupt.
> > where 4 may be defined with meaningful name. With that u8 is more than enough.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 3/6] serial: 8250_dw: Rework dw8250_handle_irq() locking and IIR handling
From: Andy Shevchenko @ 2026-01-27 13:48 UTC (permalink / raw)
To: Ilpo Järvinen
Cc: Greg Kroah-Hartman, Jiri Slaby, linux-serial, qianfan Zhao,
Adriana Nicolae, LKML, Bandal, Shankar, Murthy, Shanth
In-Reply-To: <2aa4aaa4-07b5-2003-eba7-6e1e6fa89611@linux.intel.com>
On Tue, Jan 27, 2026 at 02:48:30PM +0200, Ilpo Järvinen wrote:
> On Sat, 24 Jan 2026, Andy Shevchenko wrote:
> > On Fri, Jan 23, 2026 at 07:27:36PM +0200, Ilpo Järvinen wrote:
...
> > > dw8250_handle_irq() takes port's lock multiple times with no good
> > > reason to release it in between and calls serial8250_handle_irq()
> > > that also takes port's lock.
> > >
> > > As serial8250_handle_irq() takes port's lock itself, create
> > > serial8250_handle_irq_locked() that allows caller to hold port's lock
> > > across the call. Take port's lock only once in dw8250_handle_irq() and
> > > call serial8250_handle_irq_locked() directly.
> >
> > Sounds to me that the latter can be split to a prerequisite patch.
>
> It's not easy to split this DW-side IIR rework and locking changes. What I
> can do is to make 8250_port change separately. I guess I'll do just that
> and only the 8250_dw change in this patch.
Yes, that's what I had in mind.
...
> > > +++ b/drivers/tty/serial/8250/8250_port.c
> >
> > > #include <linux/ioport.h>
> > > #include <linux/init.h>
> > > #include <linux/irq.h>
> >
> > > +#include <linux/lockdep.h>
> >
> > I would still keep more order.
> >
> > > #include <linux/console.h>
> > > #include <linux/gpio/consumer.h>
> >
> > Giving the context we have, the better place for a new inclusion is somewhere
> > here.
>
> Feels to me something that is in the eye of the beholder, but whatever, I
> can move it from one's "correct" place to somebody elses "correct"
> place. :-)
The idea is to have the longest ordered chain even if it's broken by some
unordered pieces. In long-term it helps to cleanup without an additional
churn.
> > > #include <linux/sysrq.h>
> >
> > (Also perhaps sorting headers in a separate patch helps with finding better
> > places for the future inclusions?)
>
> Yes, later (not in this series).
Sure!
...
> > > +EXPORT_SYMBOL_GPL(serial8250_handle_irq_locked);
> >
> > Wondering if we can start exporting with a namespace...
>
> I'll do that. I picked "SERIAL_8250", is that fine or should I use e.g.
> "8250" instead?
Since it's a string now, I have no preferences, but SERIAL_8250 sounds like
slightly better choice as it has not only digits (its own namespace in the
naming) and less chances to collide in the future.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 6/6] serial: 8250_dw: Ensure BUSY is deasserted
From: Ilpo Järvinen @ 2026-01-27 13:35 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Greg Kroah-Hartman, Jiri Slaby, linux-serial, qianfan Zhao,
Adriana Nicolae, Markus Mayer, Tim Kryger, Matt Porter,
Heikki Krogerus, Jamie Iles, LKML, stable, Bandal, Shankar,
Murthy, Shanth
In-Reply-To: <aXP5YMNix8EfbJeF@smile.fi.intel.com>
[-- Attachment #1: Type: text/plain, Size: 6692 bytes --]
On Sat, 24 Jan 2026, Andy Shevchenko wrote:
> On Fri, Jan 23, 2026 at 07:27:39PM +0200, Ilpo Järvinen wrote:
> > DW UART cannot write to LCR, DLL, and DLH while BUSY is asserted.
> > Existance of BUSY depends on uart_16550_compatible, if UART HW is
> > configured with 16550 compatible those registers can always be written.
>
> with 16550 compatible --> with it
>
> > There currently is dw8250_force_idle() which attempts to archive
> > non-BUSY state by disabling FIFO, however, the solution is unreliable
> > when Rx keeps getting more and more characters.
> >
> > Create a sequence of operations to enforce that ensures UART cannot
> > keep BUSY asserted indefinitely. The new sequence relies on enabling
> > loopback mode temporarily to prevent incoming Rx characters keeping
> > UART BUSY.
>
> What if UART was already in a loopback mode? I assume that Tx pause
> described below should not affect the case.
>
> The real case scenario that I am thinking of is a stress test of UART
> using loopback mode.
If you're running a stress test that transfers characters while writing to
LCR, IMO you get to keep all the pieces yourself.
What will happen though is that LCR write would succeed still because of
the locking that will prevent Tx'ing more to loopback, but the stress test
might lose some pieces instead of getting to keep them. :-)
In general, I don't see sane reasons to mess with LCR while a real
transfer is going on. How is it sane to change line settings such as # of
bits while xferring something!?!
This is to fix scenarios where what's happening on the serial line is not
under our control (the other end keeps sending characters). There's
nothing we can do to stop that unlike running a loopback the stress test
while writing to LCR which is plain stupidity.
> > Ensure no Tx in ongoing while the UART is switches into the loopback
> > mode (requires exporting serial8250_fifo_wait_for_lsr_thre() and adding
> > DMA Tx pause/resume functions).
> >
> > According to tests performed by Adriana Nicolae <adriana@arista.com>,
> > simply disabling FIFO or clearing FIFOs only once does not always
> > ensure BUSY is deasserted but up to two tries may be needed. This could
> > be related to ongoing Rx of a character (a guess, not known for sure).
>
> Sounds like a plausible theory because UART has shift registers that are
> working independently on the current situation with FIFO. They are actual
> frontends for Tx and Rx data on the wire.
Yes. I just mentioned it's a guess as it's hard to verify, so if somebody
looks at this commit from the history, they know I've not been able to
confirm but just made an educated guess. And if they've been able to
acquire better information, they're more likely to rely on that info
instead of my guesswork.
> > Therefore, retry FIFO clearing a few times (retry limit 4 is arbitrary
> > number but using, e.g., p->fifosize seems overly large). Tests
> > performed by others did not exhibit similar challenge but it does not
> > seem harmful to leave the FIFO clearing loop in place for all DW UARTs
> > with BUSY functionality.
> >
> > Use the new dw8250_idle_enter/exit() to do divisor writes and LCR
> > writes. In case of plain LCR writes, opportunistically try to update
> > LCR first and only invoke dw8250_idle_enter() if the write did not
> > succeed (it has been observed that in practice most LCR writes do
> > succeed without complications).
> >
> > This issue was first reported by qianfan Zhao who put lots of debugging
> > effort into understanding the solution space.
>
> ...
>
> > + /* Prevent triggering interrupt from RBR filling */
> > + p->serial_out(p, UART_IER, 0);
>
> Do we specifically use callbacks directly and not wrappers all over the change?
I guess it's just a habit, I suppose you meant using serial_port_in/out
instead. I can try to change those.
> ...
>
> > + serial8250_fifo_wait_for_lsr_thre(up, p->fifosize);
> > + ndelay(p->frame_time);
>
> Wouldn't be a problem on lowest baud rates (exempli gratia 110)?
Perhaps, but until somebody comes with an issue report related to 110, I'm
wondering if this really is worth trying to address. Any suggestion how is
welcome as well?
> > + retries = 4; /* Arbitrary limit, 2 was always enough in tests */
> > + do {
> > + serial8250_clear_fifos(up);
> > + if (!(p->serial_in(p, usr_reg) & DW_UART_USR_BUSY))
> > + break;
> > + ndelay(p->frame_time);
> > + } while (--retries);
>
> read_poll_timeout_atomic() ? I assume it can't be used due to small frame time?
Frame time is in nanoseconds yes. I did consider
read_poll_timeout_atomic() but it would have required nsec -> usec
conversion so I left this as it is.
> > + if (d->in_idle) {
>
> > + /*
> > + * FIXME: this deadlocks if port->lock is already held
> > + * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
> > + */
>
> Hmm... That FIXME should gone since we have non-blocking consoles, no?
No, lockdep still gets angry if printing is used while holding port's
lock.
What would be possible though, is to mark the port's lock critical section
for print deferral (but it's outside the scope of this series). In case of
serial, it would be justified to use deferred printing (which is only
meant for special cases) because serial console and printing are related.
> > + return;
> > + }
>
> ...
>
> > + ret = dw8250_idle_enter(p);
> > + if (ret < 0) {
> > + /*
> > + * FIXME: this deadlocks if port->lock is already held
> > + * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
> > + */
> > + goto idle_failed;
> > }
> > - /*
> > - * FIXME: this deadlocks if port->lock is already held
> > - * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
> > - */
>
> Ditto.
>
> > }
>
> ...
>
> > p->dev = dev;
>
> Maybe put an added line here?
>
> > p->set_ldisc = dw8250_set_ldisc;
> > p->set_termios = dw8250_set_termios;
> > + p->set_divisor = dw8250_set_divisor;
>
> ...
>
> > +EXPORT_SYMBOL_GPL(serial8250_clear_fifos);
>
> Same Q, perhaps start exporting with a namespace?
Yes, I'll put this and the wait func into NS.
> > }
> > EXPORT_SYMBOL_GPL(serial8250_set_defaults);
>
> ...
>
> > +void serial8250_fifo_wait_for_lsr_thre(struct uart_8250_port *up, unsigned int count)
> > +{
> > + unsigned int i;
> > +
> > + for (i = 0; i < count; i++) {
>
> while (count--) ?
>
> Ah, it's existing code... OK then.
>
> > + if (wait_for_lsr(up, UART_LSR_THRE))
> > + return;
> > + }
> > +}
>
>
--
i.
^ permalink raw reply
* Re: [PATCH 4/6] serial: 8250_dw: Rework IIR_NO_INT handling to stop interrupt storm
From: Ilpo Järvinen @ 2026-01-27 13:01 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Greg Kroah-Hartman, Jiri Slaby, linux-serial, qianfan Zhao,
Adriana Nicolae, LKML, Bandal, Shankar, Murthy, Shanth
In-Reply-To: <aXPyiOMxClprdOQM@smile.fi.intel.com>
[-- Attachment #1: Type: text/plain, Size: 2319 bytes --]
On Sat, 24 Jan 2026, Andy Shevchenko wrote:
> On Fri, Jan 23, 2026 at 07:27:37PM +0200, Ilpo Järvinen wrote:
> > INTC10EE UART can end up into an interrupt storm where it reports
> > IIR_NO_INT (0x1). If the storm happens during active UART operation, it
> > is promptly stopped by IIR value change due to Rx or Tx events.
> > However, when there is no activity, either due to idle serial line or
> > due to specific circumstances such as during shutdown that writes
> > IER=0, there is nothing to stop the storm.
> >
> > During shutdown the storm is particularly problematic because
> > serial8250_do_shutdown() calls synchronize_irq() that will hang in
> > waiting for the storm to finish which never happens.
> >
> > This problem can also result in triggering a warning:
> >
> > irq 45: nobody cared (try booting with the "irqpoll" option)
> > [...snip...]
> > handlers:
> > serial8250_interrupt
> > Disabling IRQ #45
> >
> > Normal means to reset interrupt status by reading LSR, MSR, USR, or RX
> > register do not result in the UART deasserting the IRQ.
> >
> > Add a quirk to INTC10EE UARTs to enable Tx interrupts if UART's Tx is
> > currently empty and inactive. Rework IIR_NO_INT to keep track of the
> > number of consecutive IIR_NO_INT, and on third one perform the quirk.
> > Enabling Tx interrupts should change IIR value from IIR_NO_INT to
> > IIR_THRI which has been observed to stop the storm.
>
> ...
>
> > + u64 no_int_count;
>
> Why so big?
>
> ...
No particular reason, it's a leftover from debugging this issue.
> > + d->no_int_count++;
> > + if (d->no_int_count > 2 && quirks & DW_UART_QUIRK_IER_KICK)
> > + dw8250_quirk_ier_kick(p);
>
> Usual way is to use modulo. And perhaps use 4 for the sake of avoiding
> division:
>
> if (d->no_int_count == 3 && quirks & DW_UART_QUIRK_IER_KICK)
> dw8250_quirk_ier_kick(p);
>
> d->no_int_count = (d->no_int_count + 1) % 4;
This doesn't look equivalent code as it only fires on 4th NO_INT, but I
guess the difference doesn't matter that much so changing to your
suggestion so that the kick will only occurs on fourth NO_INT interrupt.
--
i.
> where 4 may be defined with meaningful name. With that u8 is more than enough.
>
> > return 0;
>
>
^ permalink raw reply
* Re: [PATCH v8] tty: tty_port: add workqueue to flip TTY buffer
From: Greg KH @ 2026-01-27 12:57 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Tommaso Merciai, Marek Szyprowski, Xin Zhao, jirislaby, tj, hch,
linux-kernel, linux-serial, Linux-Renesas
In-Reply-To: <CAMuHMdV2SLyrTs5MJKwAL2-jVLpd=TP+bMMnuEj-Ump0oyLjJA@mail.gmail.com>
On Tue, Jan 27, 2026 at 01:02:44PM +0100, Geert Uytterhoeven wrote:
> On Tue, 27 Jan 2026 at 12:10, Tommaso Merciai
> <tommaso.merciai.xr@bp.renesas.com> wrote:
> > On Tue, Jan 27, 2026 at 11:34:32AM +0100, Marek Szyprowski wrote:
> > > On 23.12.2025 04:48, Xin Zhao wrote:
> > > > On the embedded platform, certain critical data, such as IMU data, is
> > > > transmitted through UART. The tty_flip_buffer_push() interface in the TTY
> > > > layer uses system_dfl_wq to handle the flipping of the TTY buffer.
> > > > Although the unbound workqueue can create new threads on demand and wake
> > > > up the kworker thread on an idle CPU, it may be preempted by real-time
> > > > tasks or other high-prio tasks.
> > > >
> > > > flush_to_ldisc() needs to wake up the relevant data handle thread. When
> > > > executing __wake_up_common_lock(), it calls spin_lock_irqsave(), which
> > > > does not disable preemption but disables migration in RT-Linux. This
> > > > prevents the kworker thread from being migrated to other cores by CPU's
> > > > balancing logic, resulting in long delays. The call trace is as follows:
> > > > __wake_up_common_lock
> > > > __wake_up
> > > > ep_poll_callback
> > > > __wake_up_common
> > > > __wake_up_common_lock
> > > > __wake_up
> > > > n_tty_receive_buf_common
> > > > n_tty_receive_buf2
> > > > tty_ldisc_receive_buf
> > > > tty_port_default_receive_buf
> > > > flush_to_ldisc
> > > >
> > > > In our system, the processing interval for each frame of IMU data
> > > > transmitted via UART can experience significant jitter due to this issue.
> > > > Instead of the expected 10 to 15 ms frame processing interval, we see
> > > > spikes up to 30 to 35 ms. Moreover, in just one or two hours, there can
> > > > be 2 to 3 occurrences of such high jitter, which is quite frequent. This
> > > > jitter exceeds the software's tolerable limit of 20 ms.
> > > >
> > > > Introduce flip_wq in tty_port which can be set by tty_port_link_wq() or as
> > > > default linked to default workqueue allocated when tty_register_driver().
> > > > The default workqueue is allocated with flag WQ_SYSFS, so that cpumask and
> > > > nice can be set dynamically. The execution timing of tty_port_link_wq() is
> > > > not clearly restricted. The newly added function tty_port_link_driver_wq()
> > > > checks whether the flip_wq of the tty_port has already been assigned when
> > > > linking the default tty_driver's workqueue to the port. After the user has
> > > > set a custom workqueue for a certain tty_port using tty_port_link_wq(), the
> > > > system will only use this custom workqueue, even if tty_driver does not
> > > > have %TTY_DRIVER_CUSTOM_WORKQUEUE flag.
> > > >
> > > > Introduce %TTY_DRIVER_CUSTOM_WORKQUEUE flag meaning not to create the
> > > > default single tty_driver workqueue. Two reasons why need to introduce the
> > > > %TTY_DRIVER_CUSTOM_WORKQUEUE flag:
> > > > 1. If the WQ_SYSFS parameter is enabled, workqueue_sysfs_register() will
> > > > fail when trying to create a workqueue with the same name. The pty is an
> > > > example of this; if both CONFIG_LEGACY_PTYS and CONFIG_UNIX98_PTYS are
> > > > enabled, the call to tty_register_driver() in unix98_pty_init() will fail.
> > > > 2. Different tty ports may be used for different tasks, which may require
> > > > separate core binding control via workqueues. In this case, the workqueue
> > > > created by default in the tty driver is unnecessary. Enabling this flag
> > > > prevents the creation of this redundant workqueue.
> > > >
> > > > After applying this patch, we can set the related UART TTY flip buffer
> > > > workqueue by sysfs. We set the cpumask to CPU cores associated with the
> > > > IMU tasks, and set the nice to -20. Testing has shown significant
> > > > improvement in the previously described issue, with almost no stuttering
> > > > occurring anymore.
> > > >
> > > > Signed-off-by: Xin Zhao <jackzxcui1989@163.com>
> > >
> > > This patch landed in linux-next as commit d000422a46aa ("tty: tty_port:
> > > add workqueue to flip TTY buffer"). In my tests I found that it causes
> > > some regressions, see the comments in the code below.
> >
> > Same here, testing on RZ/G3E looks like s2idle is broken:
>
> > [ 185.237717] Call trace:
> > [ 185.240176] __queue_work+0x20/0x474 (P)
> > [ 185.244141] queue_work_on+0x8c/0xa8
> > [ 185.247753] tty_flip_buffer_push+0x2c/0x38
>
> Lucky you, there is a hint to tty in your trace ;-)
>
> I see a similar crash during boot on koelsch (R-Car M2-W), and a
> lock-up during boot on salvator-xs (R-Car H3 ES2.0), with either no
> output or an rcu stall:
>
> rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
> rcu: 1-...!: (0 ticks this GP) idle=1fe8/0/0x0 softirq=85/85
> fqs=1 (false positive?)
> rcu: 2-...!: (1 ticks this GP) idle=1c78/0/0x0 softirq=77/77
> fqs=1 (false positive?)
> rcu: 6-...!: (0 ticks this GP) idle=07b8/0/0x0 softirq=9/9
> fqs=1 (false positive?)
> rcu: (detected by 3, t=5260 jiffies, g=-1015, q=274 ncpus=8)
> Sending NMI from CPU 3 to CPUs 1:
> Sending NMI from CPU 3 to CPUs 2:
> Sending NMI from CPU 3 to CPUs 6:
> rcu: rcu_preempt kthread timer wakeup didn't happen for 12771
> jiffies! g-1015 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x200
> rcu: Possible timer handling issue on cpu=6 timer-softirq=1
> rcu: rcu_preempt kthread starved for 12780 jiffies! g-1015 f0x0
> RCU_GP_WAIT_FQS(5) ->state=0x200 ->cpu=6
> rcu: Unless rcu_preempt kthread gets sufficient CPU time, OOM
> is now expected behavior.
> rcu: RCU grace-period kthread stack dump:
> task:rcu_preempt state:R stack:0 pid:15 tgid:15
> ppid:2 task_flags:0x208040 flags:0x00000010
> Call trace:
> __switch_to+0xcc/0x100 (T)
> __schedule+0x368/0xc00
> schedule+0x30/0x100
> schedule_timeout+0x80/0xf8
> rcu_gp_fqs_loop+0xfc/0x418
> rcu_gp_kthread+0xe0/0xf4
> kthread+0x128/0x1e0
> ret_from_fork+0x10/0x20
>
> Reverting commit d000422a46aad322 ("tty: tty_port: add workqueue to
> flip TTY buffer") in tty-next fixes both.
Thanks all for the reports, I'll go revert this for now, sorry for the
problems!
greg k-h
^ permalink raw reply
* Re: [PATCH 3/6] serial: 8250_dw: Rework dw8250_handle_irq() locking and IIR handling
From: Ilpo Järvinen @ 2026-01-27 12:48 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Greg Kroah-Hartman, Jiri Slaby, linux-serial, qianfan Zhao,
Adriana Nicolae, LKML, Bandal, Shankar, Murthy, Shanth
In-Reply-To: <aXPwmfqPlUkI2zuw@smile.fi.intel.com>
[-- Attachment #1: Type: text/plain, Size: 2655 bytes --]
On Sat, 24 Jan 2026, Andy Shevchenko wrote:
> On Fri, Jan 23, 2026 at 07:27:36PM +0200, Ilpo Järvinen wrote:
> > dw8250_handle_irq() takes port's lock multiple times with no good
> > reason to release it in between and calls serial8250_handle_irq()
> > that also takes port's lock.
> >
> > As serial8250_handle_irq() takes port's lock itself, create
> > serial8250_handle_irq_locked() that allows caller to hold port's lock
> > across the call. Take port's lock only once in dw8250_handle_irq() and
> > call serial8250_handle_irq_locked() directly.
>
> Sounds to me that the latter can be split to a prerequisite patch.
It's not easy to split this DW-side IIR rework and locking changes. What I
can do is to make 8250_port change separately. I guess I'll do just that
and only the 8250_dw change in this patch.
> > As IIR_NO_INT check in serial8250_handle_irq() was outside of port's
> > lock, it has to be done already in dw8250_handle_irq().
> >
> > DW UART can, in addition to IIR_NO_INT, report BUSY_DETECT (0x7) which
> > collided with the IIR_NO_INT (0x1) check in serial8250_handle_irq()
> > (because & is used instead of ==) meaning that no other work is done by
> > serial8250_handle_irq() during an BUSY_DETECT interrupt.
> >
> > This allows reorganizing code in dw8250_handle_irq() to do both
> > IIR_NO_INT and BUSY_DETECT handling right at the start simplifying
> > the logic.
>
> ...
>
> > +#include <linux/bitfield.h>
> > +#include <linux/bits.h>
>
> + cleanup.h
>
> > #include <linux/clk.h>
> > #include <linux/delay.h>
> > #include <linux/device.h>
>
> ...
>
> > --- a/drivers/tty/serial/8250/8250_port.c
> > +++ b/drivers/tty/serial/8250/8250_port.c
>
> > #include <linux/ioport.h>
> > #include <linux/init.h>
> > #include <linux/irq.h>
>
> > +#include <linux/lockdep.h>
>
> I would still keep more order.
>
> > #include <linux/console.h>
> > #include <linux/gpio/consumer.h>
>
> Giving the context we have, the better place for a new inclusion is somewhere
> here.
Feels to me something that is in the eye of the beholder, but whatever, I
can move it from one's "correct" place to somebody elses "correct"
place. :-)
> > #include <linux/sysrq.h>
>
> (Also perhaps sorting headers in a separate patch helps with finding better
> places for the future inclusions?)
Yes, later (not in this series).
> ...
>
> > +EXPORT_SYMBOL_GPL(serial8250_handle_irq_locked);
>
> Wondering if we can start exporting with a namespace...
I'll do that. I picked "SERIAL_8250", is that fine or should I use e.g.
"8250" instead?
--
i.
^ permalink raw reply
* Re: [PATCH v8] tty: tty_port: add workqueue to flip TTY buffer
From: Geert Uytterhoeven @ 2026-01-27 12:02 UTC (permalink / raw)
To: Tommaso Merciai
Cc: Marek Szyprowski, Xin Zhao, gregkh, jirislaby, tj, hch,
linux-kernel, linux-serial, Linux-Renesas
In-Reply-To: <aXic3pyl0xfTSYB-@tom-desktop>
On Tue, 27 Jan 2026 at 12:10, Tommaso Merciai
<tommaso.merciai.xr@bp.renesas.com> wrote:
> On Tue, Jan 27, 2026 at 11:34:32AM +0100, Marek Szyprowski wrote:
> > On 23.12.2025 04:48, Xin Zhao wrote:
> > > On the embedded platform, certain critical data, such as IMU data, is
> > > transmitted through UART. The tty_flip_buffer_push() interface in the TTY
> > > layer uses system_dfl_wq to handle the flipping of the TTY buffer.
> > > Although the unbound workqueue can create new threads on demand and wake
> > > up the kworker thread on an idle CPU, it may be preempted by real-time
> > > tasks or other high-prio tasks.
> > >
> > > flush_to_ldisc() needs to wake up the relevant data handle thread. When
> > > executing __wake_up_common_lock(), it calls spin_lock_irqsave(), which
> > > does not disable preemption but disables migration in RT-Linux. This
> > > prevents the kworker thread from being migrated to other cores by CPU's
> > > balancing logic, resulting in long delays. The call trace is as follows:
> > > __wake_up_common_lock
> > > __wake_up
> > > ep_poll_callback
> > > __wake_up_common
> > > __wake_up_common_lock
> > > __wake_up
> > > n_tty_receive_buf_common
> > > n_tty_receive_buf2
> > > tty_ldisc_receive_buf
> > > tty_port_default_receive_buf
> > > flush_to_ldisc
> > >
> > > In our system, the processing interval for each frame of IMU data
> > > transmitted via UART can experience significant jitter due to this issue.
> > > Instead of the expected 10 to 15 ms frame processing interval, we see
> > > spikes up to 30 to 35 ms. Moreover, in just one or two hours, there can
> > > be 2 to 3 occurrences of such high jitter, which is quite frequent. This
> > > jitter exceeds the software's tolerable limit of 20 ms.
> > >
> > > Introduce flip_wq in tty_port which can be set by tty_port_link_wq() or as
> > > default linked to default workqueue allocated when tty_register_driver().
> > > The default workqueue is allocated with flag WQ_SYSFS, so that cpumask and
> > > nice can be set dynamically. The execution timing of tty_port_link_wq() is
> > > not clearly restricted. The newly added function tty_port_link_driver_wq()
> > > checks whether the flip_wq of the tty_port has already been assigned when
> > > linking the default tty_driver's workqueue to the port. After the user has
> > > set a custom workqueue for a certain tty_port using tty_port_link_wq(), the
> > > system will only use this custom workqueue, even if tty_driver does not
> > > have %TTY_DRIVER_CUSTOM_WORKQUEUE flag.
> > >
> > > Introduce %TTY_DRIVER_CUSTOM_WORKQUEUE flag meaning not to create the
> > > default single tty_driver workqueue. Two reasons why need to introduce the
> > > %TTY_DRIVER_CUSTOM_WORKQUEUE flag:
> > > 1. If the WQ_SYSFS parameter is enabled, workqueue_sysfs_register() will
> > > fail when trying to create a workqueue with the same name. The pty is an
> > > example of this; if both CONFIG_LEGACY_PTYS and CONFIG_UNIX98_PTYS are
> > > enabled, the call to tty_register_driver() in unix98_pty_init() will fail.
> > > 2. Different tty ports may be used for different tasks, which may require
> > > separate core binding control via workqueues. In this case, the workqueue
> > > created by default in the tty driver is unnecessary. Enabling this flag
> > > prevents the creation of this redundant workqueue.
> > >
> > > After applying this patch, we can set the related UART TTY flip buffer
> > > workqueue by sysfs. We set the cpumask to CPU cores associated with the
> > > IMU tasks, and set the nice to -20. Testing has shown significant
> > > improvement in the previously described issue, with almost no stuttering
> > > occurring anymore.
> > >
> > > Signed-off-by: Xin Zhao <jackzxcui1989@163.com>
> >
> > This patch landed in linux-next as commit d000422a46aa ("tty: tty_port:
> > add workqueue to flip TTY buffer"). In my tests I found that it causes
> > some regressions, see the comments in the code below.
>
> Same here, testing on RZ/G3E looks like s2idle is broken:
> [ 185.237717] Call trace:
> [ 185.240176] __queue_work+0x20/0x474 (P)
> [ 185.244141] queue_work_on+0x8c/0xa8
> [ 185.247753] tty_flip_buffer_push+0x2c/0x38
Lucky you, there is a hint to tty in your trace ;-)
I see a similar crash during boot on koelsch (R-Car M2-W), and a
lock-up during boot on salvator-xs (R-Car H3 ES2.0), with either no
output or an rcu stall:
rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
rcu: 1-...!: (0 ticks this GP) idle=1fe8/0/0x0 softirq=85/85
fqs=1 (false positive?)
rcu: 2-...!: (1 ticks this GP) idle=1c78/0/0x0 softirq=77/77
fqs=1 (false positive?)
rcu: 6-...!: (0 ticks this GP) idle=07b8/0/0x0 softirq=9/9
fqs=1 (false positive?)
rcu: (detected by 3, t=5260 jiffies, g=-1015, q=274 ncpus=8)
Sending NMI from CPU 3 to CPUs 1:
Sending NMI from CPU 3 to CPUs 2:
Sending NMI from CPU 3 to CPUs 6:
rcu: rcu_preempt kthread timer wakeup didn't happen for 12771
jiffies! g-1015 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x200
rcu: Possible timer handling issue on cpu=6 timer-softirq=1
rcu: rcu_preempt kthread starved for 12780 jiffies! g-1015 f0x0
RCU_GP_WAIT_FQS(5) ->state=0x200 ->cpu=6
rcu: Unless rcu_preempt kthread gets sufficient CPU time, OOM
is now expected behavior.
rcu: RCU grace-period kthread stack dump:
task:rcu_preempt state:R stack:0 pid:15 tgid:15
ppid:2 task_flags:0x208040 flags:0x00000010
Call trace:
__switch_to+0xcc/0x100 (T)
__schedule+0x368/0xc00
schedule+0x30/0x100
schedule_timeout+0x80/0xf8
rcu_gp_fqs_loop+0xfc/0x418
rcu_gp_kthread+0xe0/0xf4
kthread+0x128/0x1e0
ret_from_fork+0x10/0x20
Reverting commit d000422a46aad322 ("tty: tty_port: add workqueue to
flip TTY buffer") in tty-next fixes both.
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
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