This isn't actually an issue with the serial port driver, it's the printk code that is failing to schedule while printing out all the msgs. During printk(), if the console lock is held, the msgs are queued up, and inside console_unlock() any queued msgs are sent to the console before unlocking:
void console_unlock(void)
{
...
bool do_cond_resched, retry;
...
/*
* Console drivers are called under logbuf_lock, so
* @console_may_schedule should be cleared before; however, we may
* end up dumping a lot of lines, for example, if called from
* console registration path, and should invoke cond_resched()
* between lines if allowable. Not doing so can cause a very long
* scheduling stall on a slow console leading to RCU stall and
* softlockup warnings which exacerbate the issue with more
* messages practically incapacitating the system.
*/ do_cond_resched = console_may_schedule; console_may_schedule = 0;
...
for (;;) {
... call_console_drivers(level, text, len);
...
if (do_cond_resched) cond_resched();
}
so what happens here is, console_may_schedule is 0 and therefore cond_resched() isn't called between printk msgs sent to the serial port driver; and the serial port takes so long to actually send the msgs, eventually rcu thinks the cpu has soft-locked up.
This isn't actually an issue with the serial port driver, it's the printk code that is failing to schedule while printing out all the msgs. During printk(), if the console lock is held, the msgs are queued up, and inside console_unlock() any queued msgs are sent to the console before unlocking:
void console_ unlock( void) may_schedule should be cleared before; however, we may
do_cond_ resched = console_ may_schedule;
console_ may_schedule = 0;
call_ console_ drivers( level, text, len);
cond_ resched( );
{
...
bool do_cond_resched, retry;
...
/*
* Console drivers are called under logbuf_lock, so
* @console_
* end up dumping a lot of lines, for example, if called from
* console registration path, and should invoke cond_resched()
* between lines if allowable. Not doing so can cause a very long
* scheduling stall on a slow console leading to RCU stall and
* softlockup warnings which exacerbate the issue with more
* messages practically incapacitating the system.
*/
...
for (;;) {
...
...
if (do_cond_resched)
}
so what happens here is, console_ may_schedule is 0 and therefore cond_resched() isn't called between printk msgs sent to the serial port driver; and the serial port takes so long to actually send the msgs, eventually rcu thinks the cpu has soft-locked up.