kern/124777: USB cua dvices don't revert to tty devices when they are closed

Bruce Evans brde at optusnet.com.au
Fri Jun 20 13:57:13 UTC 2008


On Fri, 20 Jun 2008, Arthur Hartwig wrote:

>> Description:
> Once a USB serial device is opened as a cua device it continues to behave as a cua device even after being closed. cua devices allow only one open, tty devices allow multiple concurrent opens. Thus if a USB serial adapter is opened as /dev/cuaU0 (for example to set some modem parameters) closed and then opened as /dev/ttyU0 to allow login through the USB serial port adapter, then after login the 'more' command specifying a large enough file (more than a screen full) stalls when the controlling terminal is opened because the kernel thinks the controlling terminal is still a cua device and it has already been opened.

Where is the bug that keeps generating long lines like the above in PRs?

>> Fix:
> For now I have added the two lines:
>
>    tp->t_actout = FALSE;
>    wakeup(&tp->t_actout);
>
> to ucomclose() in sys/dev/usb/ucom.c to mimic what is done with other serial port hardware but I think the better solution is to add these two lines to tty_close() in sys/kern/tty.c and remove them from close functions in the serial port drivers.

Yes, handling of the callin and callout devices should have been completely
moved to generic code.

But beware of bugs doing this.  Code cannot simply be moved, since it
might need to run in a particular order.  At least the sio and cy were
broken by changing the order of the siosettimeout() call.  This results
in (at least) the timeout not being set up on the first call and never
being torn down after the second call.  After 2 calls, the timeout is
always active and always gives panics on module unload.

The working non-generic open code was essentially:

 	MI_stuff_part_1();
 	MD_stuff_part_1();
 	MI_stuff_part_2();
 	MD_stuff_part_2();
 	...
 	MI_stuff_part_5();	/* perhaps up to 10 sections */
 	MD_stuff_part_5();

and not all of the reorderings to reduce this to a single MD call are valid.

The above t_actout code is just before the broken siosettimout() call in
sio, but moving it seems to be OK.  The working code was:

% 	s = spltty();
% 	ttyld_close(tp, flag);
% 	com->hotchar = ttyldoptim(tp);
% 	comhardclose(com);
% 	ttyclose(tp);
% 	siosettimeout();
% 	splx(s);

The t_actout code was in comhardclose() and has only been renamed.  It was
at the end together with a TSA_CARR_ON() wakeup which should also be moved
(to the MI code just before the ttyclose() call).  The siosettimeout() call
was also moved into comhardclose(), but that completely broke it.  It must
be after the ttyclose() call.

Other bugs in this area include almost null documentation  of the callin
and callout devices in ucom(4).

Bruce


More information about the freebsd-bugs mailing list