On Wednesday 19 February 2003 18:26, Ian Abbott wrote:
> On Wednesday 19 February 2003 15:52, Mathias Fengler wrote:
> > I'm using a plain vanilla 2.4.20 kernel with the 1.3.0 beta
> > drivers. I have a 245 based device that is constantly sending 'X'
> > characters. Connecting to /dev/ttyUSB0 with minicom causes an
> > immediate OOPS. I've attached some debug output and the OOPS
> > message (caught using a serial conole). The 1.2.1 drivers included
> > in the 2.4.20 kernel are producing a similar oops.
>
> It looks like the driver has managed to fill up a buffer with
> incoming data and pass it to the tty layer before the tty layer even
> knows whether opening the serial port was successful or not!
> (ftdi_open hasn't returned yet.)  This probably wouldn't happen with
> other drivers under normal circumstances.  I wonder if the tty layer
> can deal with this race condition?

Here is a slightly more complete description of what's happening:

1. tty_open <tty_io.c> indirectly (via tty->driver.open) calls 
serial_open <usbserial.c>;

2. serial_open <usbserial.c> downs the port semaphore;

3. serial_open indirectly (via serial->type->open) calls ftdi_open 
<ftdi_sio.c>;

4. ftdi_open <ftdi_sio.c> does some initialisation, including setting 
the tty's low_latency flag;

5. ftdi_open sets up an urb for bulk reading and submits it;

a. asynchronously, an interrupt occurs as bulk data is available to be 
read, resulting in an indirect call to ftdi_read_bulk_callback 
<ftdi_sio.c>;

b. ftdi_read_bulk_callback <ftdi_sio.c> repeatly calls 
tty_insert_flip_char <tty_flip.h> until TTY_FLIPBUF_SIZE is reached and 
then calls tty_flip_buffer_push <tty_io.c>;

c. as the low_latency flag is set, tty_flip_buffer_push <tty_io.c> calls 
flush_to_ldisc <tty_io.c>;

d. flush_to_ldisc <tty_io.c> finds that the TTY_DONT_FLIP flag is not 
set, so it flips the buffer and indirectly calls (via 
tty->ldisc.receive_buf) n_tty_receive_buf <n_tty.c>;

e. n_tty_receive_buf <n_tty.c> finds that the raw discipline is not in 
use and calls n_tty_receive_char <n_tty.c> for the first character in 
the buffer;

f. n_tty_receive_char <n_tty.c> decides that the character should be 
echoed and calls echo_char <n_tty.c>;

g. echo_char <n_tty.c> decides not to treat the character specially and 
calls opost <n_tty.c>;

h. opost <n_tty.c> doesn't take any special action and indirectly calls 
(via tty->driver.put_char) tty_default_put_char <tty_io.c>;

i. tty_default_put_char <tty_io.c> indirectly calls (via 
tty->driver.write) serial_write <usbserial.c>;

j. serial_write <usbserial.c> attempts to down the port semaphore again, 
but it's still downed from step 2, resulting in the Oops and kernel 
panic.

Possible solutions include (but I haven't worked out the implications):

1. releasing the port semaphore in serial_open <usbserial.c> around the 
lower level open calls;

2. setting the TTY_DONT_FLIP flag at some point during the opening 
process.

I'm CCing this to Greg and the linux-usb-devel list, as it sounds like 
it's up their street.

Mathius, I _would_ suggest setting the raw discipline, but you have to 
open the port in the first place to do that, so it won't help.

-- 
-=( Ian Abbott @ MEV Ltd.    E-mail: <[EMAIL PROTECTED]>        )=-
-=( Tel: +44 (0)161 477 1898   FAX: +44 (0)161 718 3587         )=-



-------------------------------------------------------
This SF.net email is sponsored by: SlickEdit Inc. Develop an edge.
The most comprehensive and flexible code editor you can use.
Code faster. C/C++, C#, Java, HTML, XML, many more. FREE 30-Day Trial.
www.slickedit.com/sourceforge
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to