Linux Serial subsystem development
 help / color / mirror / Atom feed
* 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

* 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: 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 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 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 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 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 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] 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: 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 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: 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] 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 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

* [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

* [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

* [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 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

* 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

* [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

* [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

* [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 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 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 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


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