diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 143deb62467d57a1f1216d3f418c2bfccb72201c..3605103fc1ac6d891f255fea127f6fbd8b6ad96b 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -202,14 +202,16 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) /** * tty_buffer_flush - flush full tty buffers * @tty: tty to flush + * @ld: optional ldisc ptr (must be referenced) * - * flush all the buffers containing receive data. + * flush all the buffers containing receive data. If ld != NULL, + * flush the ldisc input buffer. * * Locking: takes buffer lock to ensure single-threaded flip buffer * 'consumer' */ -void tty_buffer_flush(struct tty_struct *tty) +void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld) { struct tty_port *port = tty->port; struct tty_bufhead *buf = &port->buf; @@ -223,6 +225,10 @@ void tty_buffer_flush(struct tty_struct *tty) buf->head = next; } buf->head->read = buf->head->commit; + + if (ld && ld->ops->flush_buffer) + ld->ops->flush_buffer(tty); + atomic_dec(&buf->priority); mutex_unlock(&buf->lock); } diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 4ecee2856eceb6a24ca1f4c6afeaaa6f6b14db76..aa83cd1bf07161c95dd1ea9f46cce878129f3589 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2890,7 +2890,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case TCIFLUSH: case TCIOFLUSH: /* flush tty buffer and allow ldisc to process ioctl */ - tty_buffer_flush(tty); + tty_buffer_flush(tty, NULL); break; } break; diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 6368dd95e13740ffd52f4a54e65ed11179ca41b0..b66a81d0549e3171420ae948ec3a24ef74987836 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -397,19 +397,17 @@ static void __lockfunc tty_ldisc_unlock_pair(struct tty_struct *tty, * tty_ldisc_flush - flush line discipline queue * @tty: tty * - * Flush the line discipline queue (if any) for this tty. If there - * is no line discipline active this is a no-op. + * Flush the line discipline queue (if any) and the tty flip buffers + * for this tty. */ void tty_ldisc_flush(struct tty_struct *tty) { struct tty_ldisc *ld = tty_ldisc_ref(tty); - if (ld) { - if (ld->ops->flush_buffer) - ld->ops->flush_buffer(tty); + + tty_buffer_flush(tty, ld); + if (ld) tty_ldisc_deref(ld); - } - tty_buffer_flush(tty); } EXPORT_SYMBOL_GPL(tty_ldisc_flush); diff --git a/include/linux/tty.h b/include/linux/tty.h index e33ea1a0c2d0e2403f4d5390696e6152519cc21f..f6835ea1079a2a4e1cd54d1058803438d6f33c7e 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -441,7 +441,7 @@ extern void __do_SAK(struct tty_struct *tty); extern void no_tty(void); extern void tty_flush_to_ldisc(struct tty_struct *tty); extern void tty_buffer_free_all(struct tty_port *port); -extern void tty_buffer_flush(struct tty_struct *tty); +extern void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld); extern void tty_buffer_init(struct tty_port *port); extern speed_t tty_termios_baud_rate(struct ktermios *termios); extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);