2007-05-07 21:06:59

by Paul Fulghum

[permalink] [raw]
Subject: [PATCH] tty flush flip buffer on ldisc input queue flush

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);




2008-01-03 22:25:43

by Matthias Goebl

[permalink] [raw]
Subject: [PATCH] isdn/i4l: 'NO CARRIER' message lost after ldisc flush

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)))) {

2008-01-03 22:32:38

by Alan

[permalink] [raw]
Subject: Re: [PATCH] isdn/i4l: 'NO CARRIER' message lost after ldisc flush

> 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

2008-01-04 10:19:55

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] isdn/i4l: 'NO CARRIER' message lost after ldisc flush

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.