serial driver / tty issues

Benjamin Herrenschmidt
2004-03-05T09:19:52Z

Hi Russell !

So, I was tracking down some problems with that pmac_zilog() driver
of mine, some were my fault, but some others are still quite
interesting as they seem to affect other drivers as well.

The basic issue was an interesting HW situation that resulted in the
SCC flooding me with 0 chars + framing errors like mad (faster than
the serial port speed, more like a stuck irq actually) when the port
is connected to an unplug keyspan adapter (so the input line is
probably getting noise or whatever crap).

That triggered extreme situation both in the driver and the tty layer
due to the fast flood of incoming shit.

- most/all serial drivers, when the flip buffer is full, will
call tty->flip.work.func() directly with the spinlock held. This is
asking for trouble. I have reproduceable cases where that cause the
tty layer to try to echo, thus calling back the serial_core
uart_put_char() which will try to ... take the spinlock. Dead.

- what about the call to tty_flip_buffer_push() done by all
drivers with the lock held too ? It's fine as long as we don't
have this low_latency thing set. I suppose nothing but the driver
itself will set it but I got a bit lost in the serial_core, can
you just confirm that is ok ?

- I had a couple of times a crash in n_tty_receive_buf() called
from keventd (from ldisc flip workqueue), apparently racing with
a close of the port. The scenario is that the close happens, i
get out of my driver back to serial core which goes back to
tty_release afaik. At that point (I'm not sure exactly when, maybe
in the flush of the pending work queues that is done there, maybe
just on the other CPU), the pending work queue is triggered since
our input buffer is still full of crap.
It reliably oopses trying to derefence 0 (writing a byte, it's not
a memcpy, without a spinlocked region, I haven't spotted exactly
where in n_tty_receive_buf(), this function is shit to disassemble
as it seems to get a ton of things inlined).

Ben.