Messages in this thread Patch in this message | | | Date | Sat, 2 Jan 1999 01:35:03 -0500 | From | "Theodore Y. Ts'o" <> | Subject | Re: setserial hangs during 2.2.0-pre2 boot |
| |
Date: Fri, 1 Jan 1999 19:44:50 +0000 From: Nick Holloway <alfie@alfie.demon.co.uk>
Fairly often, but not always, the setserial commands run by the Debian 2.0 boot scripts hang when booting 2.2.0-pre2. This means the whole boot hangs, leading to a reset, and the associated fsck on the next boot :-(
It is caused by "setserial -b /dev/ttyS1 autoconfig", and when the device is closed. What is happening is that rs_wait_until_close is being called with a maximum timeout (MAX_SCHEDULE) by tty_wait_until_sent. The loop in rs_wait_until_sent never thinks that the UART has finished sending, and so repeatedly re-schedules.
This appears to be a UART bug. The TEMT bit is supposed to be set whenever the transmitter shift register is empty. Apparently, it's not doing it for your UART after it leaves the automatic loopback state (which is used by the UART configuration code). I can't duplicate it on my system, but your debugging traces clearly point to that as the problem.
I've enclosed a patch below which should fix the problem. Could you please test it and let me know how it works for you? Thanks!!
- Ted
Patch generated: on Sat Jan 2 01:34:46 EST 1999 by tytso@rsts-11.mit.edu against Linux version 2.2.0 =================================================================== RCS file: drivers/char/RCS/serial.c,v retrieving revision 1.1 diff -u -r1.1 drivers/char/serial.c --- drivers/char/serial.c 1999/01/02 06:14:35 1.1 +++ drivers/char/serial.c 1999/01/02 06:34:42 @@ -2356,6 +2356,17 @@ char_time = 1; if (timeout) char_time = MIN(char_time, timeout); + /* + * If the transmitter hasn't cleared in twice the approximate + * amount of time to send the entire FIFO, it probably won't + * ever clear. This assumes the UART isn't doing flow + * control, which is currently the case. Hence, if it ever + * takes longer than info->timeout, this is probably due to a + * UART bug of some kind. So, we clamp the timeout parameter at + * 2*info->timeout. + */ + if (!timeout || timeout > 2*info->timeout) + timeout = 2*info->timeout; #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time); printk("jiff=%lu...", jiffies); - 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/
| |