|
@@ -369,25 +369,54 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * tty_buffer_flush - flush full tty buffers
|
|
|
+ * __tty_buffer_flush - flush full tty buffers
|
|
|
* @tty: tty to flush
|
|
|
*
|
|
|
- * flush all the buffers containing receive data
|
|
|
+ * flush all the buffers containing receive data. Caller must
|
|
|
+ * hold the buffer lock and must have ensured no parallel flush to
|
|
|
+ * ldisc is running.
|
|
|
*
|
|
|
- * Locking: none
|
|
|
+ * Locking: Caller must hold tty->buf.lock
|
|
|
*/
|
|
|
|
|
|
-static void tty_buffer_flush(struct tty_struct *tty)
|
|
|
+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;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * tty_buffer_flush - flush full tty buffers
|
|
|
+ * @tty: tty to flush
|
|
|
+ *
|
|
|
+ * flush all the buffers containing receive data. If the buffer is
|
|
|
+ * being processed by flush_to_ldisc then we defer the processing
|
|
|
+ * to that function
|
|
|
+ *
|
|
|
+ * Locking: none
|
|
|
+ */
|
|
|
+
|
|
|
+static void tty_buffer_flush(struct tty_struct *tty)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+ spin_lock_irqsave(&tty->buf.lock, flags);
|
|
|
+
|
|
|
+ /* If the data is being pushed to the tty layer then we can't
|
|
|
+ process it here. Instead set a flag and the flush_to_ldisc
|
|
|
+ path will process the flush request before it exits */
|
|
|
+ if (test_bit(TTY_FLUSHING, &tty->flags)) {
|
|
|
+ set_bit(TTY_FLUSHPENDING, &tty->flags);
|
|
|
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
|
|
|
+ wait_event(tty->read_wait,
|
|
|
+ test_bit(TTY_FLUSHPENDING, &tty->flags) == 0);
|
|
|
+ return;
|
|
|
+ } else
|
|
|
+ __tty_buffer_flush(tty);
|
|
|
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
|
|
}
|
|
|
|
|
@@ -3594,6 +3623,7 @@ static void flush_to_ldisc(struct work_struct *work)
|
|
|
return;
|
|
|
|
|
|
spin_lock_irqsave(&tty->buf.lock, flags);
|
|
|
+ set_bit(TTY_FLUSHING, &tty->flags); /* So we know a flush is running */
|
|
|
head = tty->buf.head;
|
|
|
if (head != NULL) {
|
|
|
tty->buf.head = NULL;
|
|
@@ -3607,6 +3637,11 @@ static void flush_to_ldisc(struct work_struct *work)
|
|
|
tty_buffer_free(tty, tbuf);
|
|
|
continue;
|
|
|
}
|
|
|
+ /* Ldisc or user is trying to flush the buffers
|
|
|
+ we are feeding to the ldisc, stop feeding the
|
|
|
+ line discipline as we want to empty the queue */
|
|
|
+ if (test_bit(TTY_FLUSHPENDING, &tty->flags))
|
|
|
+ break;
|
|
|
if (!tty->receive_room) {
|
|
|
schedule_delayed_work(&tty->buf.work, 1);
|
|
|
break;
|
|
@@ -3620,8 +3655,17 @@ static void flush_to_ldisc(struct work_struct *work)
|
|
|
disc->receive_buf(tty, char_buf, flag_buf, count);
|
|
|
spin_lock_irqsave(&tty->buf.lock, flags);
|
|
|
}
|
|
|
+ /* Restore the queue head */
|
|
|
tty->buf.head = head;
|
|
|
}
|
|
|
+ /* We may have a deferred request to flush the input buffer,
|
|
|
+ if so pull the chain under the lock and empty the queue */
|
|
|
+ if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
|
|
|
+ __tty_buffer_flush(tty);
|
|
|
+ clear_bit(TTY_FLUSHPENDING, &tty->flags);
|
|
|
+ wake_up(&tty->read_wait);
|
|
|
+ }
|
|
|
+ clear_bit(TTY_FLUSHING, &tty->flags);
|
|
|
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
|
|
|
|
|
tty_ldisc_deref(disc);
|