Flush the tty flip buffer when the line discipline
input queue is flushed, including the user call
tcflush(TCIFLUSH/TCIOFLUSH). This prevents unexpected
stale data after a user application calls tcflush().
Cc: Alan Cox <[email protected]>
Cc: Antonino Ingargiola <[email protected]>
Signed-off-by: Paul Fulghum <[email protected]>
--- a/drivers/char/tty_io.c 2007-05-04 05:46:55.000000000 -0500
+++ b/drivers/char/tty_io.c 2007-05-05 03:23:46.000000000 -0500
@@ -365,6 +365,29 @@ static void tty_buffer_free(struct tty_s
}
/**
+ * tty_buffer_flush - flush full tty buffers
+ * @tty: tty to flush
+ *
+ * flush all the buffers containing receive data
+ *
+ * Locking: none
+ */
+
+static void tty_buffer_flush(struct tty_struct *tty)
+{
+ struct tty_buffer *thead;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ while((thead = tty->buf.head) != NULL) {
+ tty->buf.head = thead->next;
+ tty_buffer_free(tty, thead);
+ }
+ tty->buf.tail = NULL;
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+}
+
+/**
* tty_buffer_find - find a free tty buffer
* @tty: tty owning the buffer
* @size: characters wanted
@@ -1240,6 +1263,7 @@ void tty_ldisc_flush(struct tty_struct *
ld->flush_buffer(tty);
tty_ldisc_deref(ld);
}
+ tty_buffer_flush(tty);
}
EXPORT_SYMBOL_GPL(tty_ldisc_flush);
@@ -3336,6 +3360,15 @@ int tty_ioctl(struct inode * inode, stru
case TIOCMBIC:
case TIOCMBIS:
return tty_tiocmset(tty, file, cmd, p);
+ case TCFLSH:
+ switch (arg) {
+ case TCIFLUSH:
+ case TCIOFLUSH:
+ /* flush tty buffer and allow ldisc to process ioctl */
+ tty_buffer_flush(tty);
+ break;
+ }
+ break;
}
if (tty->driver->ioctl) {
retval = (tty->driver->ioctl)(tty, file, cmd, arg);
The ISDN tty layer doesn't produce a 'NO CARRIER' message after hangup.
I suppose it broke when tty_buffer_flush() has been added to
tty_ldisc_flush() in the commit below.
For isdn_tty_modem_result(RESULT_NO_CARRIER..) the
message inserted via isdn_tty_at_cout() -> tty_insert_flip_char()
is flushed immediately by tty_ldisc_flush() -> tty_buffer_flush().
More annoyingly, the audio abort sequence DLE-ETX is also lost.
This patch fixes only active audio connections, because I assume that nobody
changes the line discipline for audio.
For non-audio connections the problem remains.
Maybe we can remove the tty_ldisc_flush() in isdn_tty_modem_result()
at all because it's done at tty_close?
On Mon, May 07, 2007 at 04:05:57PM -0500, Paul Fulghum wrote:
> Flush the tty flip buffer when the line discipline
> input queue is flushed, including the user call
> tcflush(TCIFLUSH/TCIOFLUSH). This prevents unexpected
> stale data after a user application calls tcflush().
>
> Cc: Alan Cox <[email protected]>
> Cc: Antonino Ingargiola <[email protected]>
> Signed-off-by: Paul Fulghum <[email protected]>
>
> --- a/drivers/char/tty_io.c 2007-05-04 05:46:55.000000000 -0500
> +++ b/drivers/char/tty_io.c 2007-05-05 03:23:46.000000000 -0500
> @@ -1240,6 +1263,7 @@ void tty_ldisc_flush(struct tty_struct *
> ld->flush_buffer(tty);
> tty_ldisc_deref(ld);
> }
> + tty_buffer_flush(tty);
[..]
Signed-off-by: Matthias Goebl <[email protected]>
--- linux-2.6.23.12.orig/drivers/isdn/i4l/isdn_tty.c
+++ linux-2.6.23.12/drivers/isdn/i4l/isdn_tty.c
@@ -2645,7 +2649,12 @@
if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
return;
}
+#ifdef CONFIG_ISDN_AUDIO
+ if ( !info->vonline )
+ tty_ldisc_flush(info->tty);
+#else
tty_ldisc_flush(info->tty);
+#endif
if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
(!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
(info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
> For non-audio connections the problem remains.
> Maybe we can remove the tty_ldisc_flush() in isdn_tty_modem_result()
> at all because it's done at tty_close?
I'm not sure I understand why the tty_ldisc_flush is being done in the
ISDN layer at this point but this change looks fine to me.
Alan
From: Alan Cox <[email protected]>
Date: Thu, 3 Jan 2008 22:30:54 +0000
> > For non-audio connections the problem remains.
> > Maybe we can remove the tty_ldisc_flush() in isdn_tty_modem_result()
> > at all because it's done at tty_close?
>
> I'm not sure I understand why the tty_ldisc_flush is being done in the
> ISDN layer at this point but this change looks fine to me.
I'll apply this fix to net-2.6 and push to Linus.
Thanks.