Messages in this thread | | | Date | Fri, 21 Aug 2009 19:42:52 +0100 | From | Alan Cox <> | Subject | Re: 2.6.31-rc5 regression: Oops when USB Serial disconnected while in use |
| |
> Then surely serial_open() should call serial->type->open() _after_ > tty_port_block_til_ready(), not before.
It needs the hardware active and running to do the block_til_ready
> Now the second user tries to do stuff but the hardware isn't ready. > Instead this should go: > > serial_open() /* first user */ > tty_port_block_til_ready() /* returns immediately */ > serial->type->open() /* initializes the hardware */ > > serial_open() /* second user */ > tty_port_block_til_ready() /* blocks */
If the first user succeeded then second should open immediately as the use count is >= 1 already. It is re-opening the open device, unless the hangup occurs first.
> > serial_hangup() /* first connection drops */ > serial_do_down() > serial->type-close() /* resets the hardware */ > > ... tty_port_block_til_ready() returns > serial->type->open() /* not skipped */ > > Now the second user can proceed to use the hardware. Or have I > misunderstood how this is intended to work?
Usual paths
open block_til_ready open returns 0 do stuff close
open block_til_ready open returns 0 do stuff hangup (closes hw side) further stuff errors close (does nothing to the hw side tty_port_close knows about this)
open block_til_ready hangup open returns error close path called - knows about hangup in tty_close_port
Hence the reason it always calls the close path to cleanup hardware and other resources even if open returns an error
> > Alan Stern > > P.S.: Can you explain the reason why tty_port and tty_struct are two > separate structures? Isn't the same port always associated with the > same tty?
The tty structure is the virtual interface side, the tty_port is the hardware device. Historically the port side varied randomly by device preventing any commonality being extracted into helpers.
For most hardware the tty_port lifetime is the physical port lifetime, the tty lifetime is open->final close (or a final kref drop afterwards)
It also means eventually that we can have a tty_port and things hung off it for all hardware which means
- Most of the locking costs for receiving v hangup go away (as you queue to the tty_port not the tty - ie move the tty_buffer struct) - It becomes possible to have a proper generic console/debug console without hacks and fake tty devices.
Most drivers tend to look like
open test ASYNC_INITIALIZED init hardware [either in full or clean up partial] set ASYNC_INITIALIZED) any other alloc/counter magic tty->private_data = my stuff block_til_ready return ok/error
close if (hung_up) return if (tty->driver_data == NULL) return counts clean up resources if (last && test_clear INITIALIZED) deinit-hardware return ok/error
hangup if (initialized & test_clear INITIALIZED) { deinit hardware }
which is where I was trying to get the USB code.
| |