Serial driver broken since 2.2.x?

Petr Novak (Petr.Novak@i.cz)
Thu, 24 Jun 1999 16:20:26 +0200


Hello,

I was trying to upgrade a machine running xntpd with DCF-77 receiver
from 2.0.x kernel to 2.2.x kernel (and other stuff, of course). One of
the problems seems to be that the non-canonical mode of "dumb" serial
ports (ttyS0 and ttyS1) is broken since 2.2.x kernels.

The RAWDCF code in xntpd handles the port as raw (non-canonical mode)
device, with 50 baud speed. The DCF-77 data format produces 1 pulse
(long or short) every second, which read at the serial port nominally as
'\0' or '\340' (the actual char may vary with the precise width of the
pulse, but typically it is one of these chars).

The acutal code uses a select system call with NULL in the timeout
argument, the port is set up with VMIN=1 and VTIME=0. Once the select
returns, the character is read into a buffer, and another select is
issued. (actually, there is also a periodic timer firing every second,
but we can ingore that for now).

Now, with 2.0.x kernels, the code works fine, the select returns with 1
and the fd of the serial line, the read is immediately satisfied and
reads exactly the 1 character, some background work is done and
eventually another select is issued, which again returns with 1 fd, 1
char is read etc.

With 2.2.x kernels the select is dead for about 10 seconds and then is
satisfied and when a read is issued, that reads (typically) 10 chars of
information.

I was trying to look into the kernel code myself (I had some experience
with kernel-level code, but not character devices), but I was not able
to find the reason of the incorrect behaviour myself (ie. wheather it is
in the select/poll processing, n_tty line discipline, tty_io.c or
serial.c). I am aware of the fact that the problem may be with different
programming of the hardware (the FIFO in 16550A and later UARTs),
although it seems that with speeds <= 2400 baud the UART is told to
interrupt on every characters.

For anyone willing to look into the problem I attach the strace output
with 2.0.x and 2.2.x kernels (only small parts, obviously).

As I do not subscribe to this list, please CC me also to <P.Novak@i.cz>
if replying to this message.

Thanks in advance to anyone able to help,

--
Petr Novak <Petr.Novak@i.cz>
ICZ a.s.   www.i.cz
Zirovnicka 6
CZ-106 00 Praha 10
Ph:  +420 2 7276 0337   **changed 1999-03**
Fax: +420 2 7276 0322	**changed 1999-03**

------- cut here ----------- kernel 2.0.35 516 23:38:11.766345 select(8, [4 5 7], NULL, NULL, NULL) = 1 (in [7]) 516 23:38:11.894564 gettimeofday({930173891, 894703}, NULL) = 0 516 23:38:11.895015 select(8, [4 5 7], NULL, NULL, {0, 0}) = 1 (in [7], left {0, 0}) 516 23:38:11.896271 read(7, "\340", 500) = 1 516 23:38:11.896751 select(8, [4 5 7], NULL, NULL, {0, 0}) = 0 (Timeout) 516 23:38:11.897654 select(8, [4 5 7], NULL, NULL, NULL) = ? ERESTARTNOHAND (To be restarted) 516 23:38:12.764089 --- SIGALRM (Alarm clock) --- 516 23:38:12.764731 sigreturn() = ? (mask now []) 516 23:38:12.765451 adjtimex({modes=32769, offset=0, freq=0, maxerror=16384000, esterror=16384000, status=64, constant=2, precision=1, tolerance=13107200, time={930173892, 765593}}) = 5 516 23:38:12.766287 select(8, [4 5 7], NULL, NULL, NULL) = 1 (in [7]) 516 23:38:12.894568 gettimeofday({930173892, 894708}, NULL) = 0 516 23:38:12.895021 select(8, [4 5 7], NULL, NULL, {0, 0}) = 1 (in [7], left {0, 0}) 516 23:38:12.896281 read(7, "\0", 500) = 1 516 23:38:12.896759 select(8, [4 5 7], NULL, NULL, {0, 0}) = 0 (Timeout) 516 23:38:12.897629 select(8, [4 5 7], NULL, NULL, NULL) = ? ERESTARTNOHAND (To be restarted) 516 23:38:13.764089 --- SIGALRM (Alarm clock) --- 516 23:38:13.764725 sigreturn() = ? (mask now []) 516 23:38:13.765437 adjtimex({modes=32769, offset=0, freq=0, maxerror=16384000, esterror=16384000, status=64, constant=2, precision=1, tolerance=13107200, time={930173893, 765579}}) = 5 516 23:38:13.766493 select(8, [4 5 7], NULL, NULL, NULL) = 1 (in [7]) ------- cut here ---------------

------- cut here --------------- kernel 2.2.10 476 23:47:27.419604 select(8, [4 5 7], NULL, NULL, NULL) = ? ERESTARTNOHAND (To be restarted) 476 23:47:28.418603 --- SIGALRM (Alarm clock) --- 476 23:47:28.419067 sigreturn() = ? (mask now []) 476 23:47:28.419421 adjtimex({modes=32769, offset=0, freq=0, maxerror=16384000, esterror=16384000, status=64, constant=2, precision=1, tolerance=33554432, time={930174448, 419504}}) = 5 476 23:47:28.419740 select(8, [4 5 7], NULL, NULL, NULL) = ? ERESTARTNOHAND (To be restarted) 476 23:47:29.418530 --- SIGALRM (Alarm clock) --- 476 23:47:29.418968 sigreturn() = ? (mask now []) 476 23:47:29.419284 adjtimex({modes=32769, offset=0, freq=0, maxerror=16384000, esterror=16384000, status=64, constant=2, precision=1, tolerance=33554432, time={930174449, 419365}}) = 5 476 23:47:29.419599 select(8, [4 5 7], NULL, NULL, NULL) = ? ERESTARTNOHAND (To be restarted) 476 23:47:30.418527 --- SIGALRM (Alarm clock) --- 476 23:47:30.418956 sigreturn() = ? (mask now []) 476 23:47:30.419272 adjtimex({modes=32769, offset=0, freq=0, maxerror=16384000, esterror=16384000, status=64, constant=2, precision=1, tolerance=33554432, time={930174450, 419353}}) = 5 476 23:47:30.419623 select(8, [4 5 7], NULL, NULL, NULL) = ? ERESTARTNOHAND (To be restarted) 476 23:47:31.418531 --- SIGALRM (Alarm clock) --- 476 23:47:31.418964 sigreturn() = ? (mask now []) 476 23:47:31.419279 adjtimex({modes=32769, offset=0, freq=0, maxerror=16384000, esterror=16384000, status=64, constant=2, precision=1, tolerance=33554432, time={930174451, 419360}}) = 5 476 23:47:31.419595 select(8, [4 5 7], NULL, NULL, NULL) = ? ERESTARTNOHAND (To be restarted) 476 23:47:32.418528 --- SIGALRM (Alarm clock) --- 476 23:47:32.418959 sigreturn() = ? (mask now []) 476 23:47:32.419275 adjtimex({modes=32769, offset=0, freq=0, maxerror=16384000, esterror=16384000, status=64, constant=2, precision=1, tolerance=33554432, time={930174452, 419357}}) = 5 476 23:47:32.419592 select(8, [4 5 7], NULL, NULL, NULL) = ? ERESTARTNOHAND (To be restarted) 476 23:47:33.418595 --- SIGALRM (Alarm clock) --- 476 23:47:33.419064 sigreturn() = ? (mask now []) 476 23:47:33.419383 adjtimex({modes=32769, offset=0, freq=0, maxerror=16384000, esterror=16384000, status=64, constant=2, precision=1, tolerance=33554432, time={930174453, 419497}}) = 5 476 23:47:33.419734 select(8, [4 5 7], NULL, NULL, NULL) = 1 (in [7]) 476 23:47:33.578644 gettimeofday({930174453, 578724}, NULL) = 0 476 23:47:33.578870 select(8, [4 5 7], NULL, NULL, {0, 0}) = 1 (in [7], left {0, 0}) 476 23:47:33.579282 read(7, "\0\0\0\340\340\340\0\0\0\0", 500) = 10 476 23:47:33.579595 select(8, [4 5 7], NULL, NULL, {0, 0}) = 0 (Timeout) 476 23:47:33.580050 time([930174453]) = 930174453 ----- cut here ---------------------

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/