arc_uart: serial output truncated
Hi,
I'm seeing truncated serial console output, with 3.8 based arc_uart driver (drivers/tty/serial/arc_uart.c)
It would seem funny that I'm the driver author and still bringing this up - because this seems like an interplay of tty-core/serial-core with a slow serial device, rather than a driver specific issue, which is causing this.
The basic call flow is a write(2) to STDERR which lands in the tty layer. The routine n_tty_write() successfully copies the complete msg from tty layer's buffer to driver's tx buffer (tty->driver_state->xmit->buf). There are 3 arc-uart driver output calls in that codepath and with 1 deep Tx FIFO only 3 characters are output
- as follows:
n_tty_write
process_output_block
tty->ops->write --> full user buffer
uart_write
copy tty buffer into driver buffer
uart_start
port->ops->start_tx
arc_serial_tx_chars ==> 1st char
process_output
tty->ops->write --> "\r\n"
uart_start
port->ops->start_tx
arc_serial_tx_chars ==> 2nd char
tty_flush_chars
uart_start
port->ops->start_tx
arc_serial_tx_chars ==> 3rd charOnce interrupts are re-enabled (spin_unlock_irqrestore) a few more chars are output via the driver ISR path.
However user app then immediately calls exit().
do_exit
tty_release
uart_close
tty_port_close_start --> returns 0 - because port->count == 4
...
disassociate_ctty
tty_ldisk_hangup
tty_driver_flush_buffer
tty->ops->flush_buffer
uart_flush_buffer
uart_circ_clear --> zeros the driver tx buffer head/tailtty_port_close_start() has logic for port->drain_delay but in my case the port->count is 4 (3 due to init task, 1 from this specific app) so that logic is not hit.
Eventually, uart_flush_buffer is called, with unwritten data still present, but the head/tail pointers are reset, causing that driver data to be effectively lost.
So maybe this is how it works (for a 1 deep FIFO uart) but I wanted to confirm with the serial gurus. Is there any serial setting I can apply here to enable the last remaining chars to be dumped out of uart tx buffer.
Thx,
-Vineet
Quoted 4 lines · Vineet Gupta
Hi,
I'm seeing truncated serial console output, with 3.8 based
arc_uartdriver (drivers/tty/serial/arc_uart.c)
<...snip...>
Quoted 19 lines
However user app then immediately calls
exit().
do_exit
tty_releaseuart_close tty_port_close_start --> returns 0 - because port->count == 4 ... disassociate_ctty tty_ldisk_hangup tty_driver_flush_buffer tty->ops->flush_buffer uart_flush_buffer uart_circ_clear --> zeros the driver tx buffer head/tail
tty_port_close_start()has logic forport->drain_delaybut in my case theport->countis 4 (3 due to init task, 1 from this specific app) so that logic is not hit.
Quoted 6 lines
Eventually,
uart_flush_bufferis called, with unwritten data still present, but the head/tail pointers are reset, causing that driver data to be effectively lost.So maybe this is how it works (for a 1 deep FIFO uart) but I wanted to confirm with the serial gurus. Is there any serial setting I can apply here to enable the last remaining chars to be dumped out of uart tx buffer.
Hi Vineet,
You're correct in that this is not driver related, and that it's a problem in the tty core, specifically in __tty_hangup().
The problem is actually worse with a really high speed tty (like over Firewire) and on the receive end can amount to 60+K of dropped data.
The problem stems from the semantics of 'hangup': for one usage, it means 'this end is done transmitting' and in the other usage, it means 'don't send me anymore data'. So for first meaning, receiving all the data is important. In the second meaning, the receiver doesn't want data anymore.
Unfortunately, there is almost no distinction in the tty core; it implements the second meaning while providing interface for the first meaning.
I'm meaning to address this eventually (because I'm working around this now in TTY-over-Firewire -- its on the receive end so wouldn't be any help in your situation), but don't have a plan on how to best fix this yet.
Regards,
Peter Hurley