On Tue, Apr 05, 2022 at 01:24:37PM +0300, Ilpo Järvinen wrote:
When tty is not read from, XON/XOFF may get stuck into an
intermediate buffer. As those characters are there to do software
flow-control, it is not very useful. In the case where neither end
reads from ttys, the receiving ends might not be able receive the
XOFF characters and just keep sending more data to the opposite
direction. This problem is almost guaranteed to occur with DMA
which sends data in large chunks.
If TTY is slow to process characters, that is, eats less than given
amount in receive_buf, invoke lookahead for the rest of the chars
to process potential XON/XOFF characters.
The guards necessary for ensuring the XON/XOFF character are
processed only once were added by the previous patch. All this patch
needs to do on that front is to pass the lookahead count (that can
now be non-zero) into port->client_ops->receive_buf().
...
+static bool __n_tty_receive_char_special(struct tty_struct *tty, unsigned char c,
+ bool lookahead_done)
+{
+ if (!I_IXON(tty))
+ return false;
+
+ if (c == START_CHAR(tty)) {
+ if (!lookahead_done) {
+ start_tty(tty);
+ process_echoes(tty);
+ }
+ return true;
+ }
+ if (c == STOP_CHAR(tty)) {
+ if (!lookahead_done)
+ stop_tty(tty);
+ return true;
+ }
+ return false;
+}
Looking into this I would first make a preparatory patch that splits out
current code into something like
static bool __n_tty_receive_char_special_no_lookahead(struct tty_struct *tty, unsigned char c)
{
...current code...
}
Then in the patch 1 you add
static bool __n_tty_receive_char_special_lookahead(struct tty_struct *tty, unsigned char c)
{
...
}
static bool __n_tty_receive_char_special(struct tty_struct *tty, unsigned char c,
bool lookahead_done)
{
if (!I_IXON(tty))
return false;
if (lookahead_done)
return _lookahead();
return _no_lookahead();
}