Date: Mon, 13 Dec 2004 15:44:59 +1100 (EST) From: Bruce Evans <bde@zeta.org.au> To: Julian Elischer <julian@elischer.org> Cc: freebsd-bugs@freebsd.org Subject: Re: kern/65769: Call to tcflush(x, TCIFLUSH) stops input on usb-serialforever Message-ID: <20041213131051.W2647@epsplex.bde.org> In-Reply-To: <41BBCC16.9040909@elischer.org> References: <41BBCC16.9040909@elischer.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, 11 Dec 2004, Julian Elischer wrote: > I there a patch that I can consider for commit for this? The PR mentions the wrong fix of breaking tty.c back to rev.1.15. This would be wrong because flushing of input must be requested of drivers to flush any downstream software or hardware buffers. t_stop() is overloaded to do this as follows: - t_stop() always flushes downstream i/o according to the setting of its FREAD/FWRITE flags - t_stop() stops downstream output iff the TS_TTSTOP flag is set. Most drivers don't need to anything in t_stop() for this, but sio converts TS_TTSTOP to a driver flag to simplify locking and improve efficiency. - t_stop() is not intended to stop input AFAIK. So pure stopping of downstream output involves setting TS_TTSTOP and calling t_stop() with flags 0, pure stopping of downstream input is not supported, and pure flushing of downstream i/o involves calling t_stop() with the relevant FREAD/FWRITE flags combination without changing TS_TTSTOP. We have the bug because our ucom.c is mostly maintained in NetBSD but out tty.c is mostly maintained in FreeBSD, and NetBSD still doesn't pass input-flushing requests down to drivers. It's interesting that the more common TCSETAF ioctl (== tcsetattr() with TCSAFLUSH) also stops/flushes input but apparently doesn't cause the problem. It apparently works because ucomparam() finishes up by calling ucomstart() which restarts things. Also, ucomparam() calls the the same function as ucomstop() to "stop" the devices, namely ucomstopread(), even in the !TCSAFLUSH case. This can only be right if (as I suspect) ucomstopread() is not overloaded to flush and ucomstop()'s input flushing is complete nonsense. It is reasonable to stop but not to flush input in ucomparam() -- stopping may be required for physical reasons to change the parameters, but flushing should not be done there since upper layers have already done it iff it has been requested (though there is a race here). OTOH, ucomstop() is apparently calling the stop function when only input flushing is requested. Possible fixes: 1. never stop input in ucomstop(), or 2. if ucomstopread() is needed in ucomstop() for a side effect of flushing input in ucomstop(), then call ucomstart() in ucomstop() to restart input, hopefully as in ucomparam(). Also, don't call it in ucomparam() if it flushes input. sio already has the corresponding call to comstart() from comstop() for unrelated reasons (to reduce duplication of code for stopping output). Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20041213131051.W2647>