Skip site navigation (1)Skip section navigation (2)
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>