| .. | .. |
|---|
| 21 | 21 | #include <linux/bitops.h> |
|---|
| 22 | 22 | #include <linux/mutex.h> |
|---|
| 23 | 23 | #include <linux/compat.h> |
|---|
| 24 | +#include "tty.h" |
|---|
| 24 | 25 | |
|---|
| 25 | 26 | #include <asm/io.h> |
|---|
| 26 | 27 | #include <linux/uaccess.h> |
|---|
| .. | .. |
|---|
| 397 | 398 | tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios); |
|---|
| 398 | 399 | tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios); |
|---|
| 399 | 400 | |
|---|
| 400 | | - ld = tty_ldisc_ref(tty); |
|---|
| 401 | + if (opt & (TERMIOS_FLUSH|TERMIOS_WAIT)) { |
|---|
| 402 | +retry_write_wait: |
|---|
| 403 | + retval = wait_event_interruptible(tty->write_wait, !tty_chars_in_buffer(tty)); |
|---|
| 404 | + if (retval < 0) |
|---|
| 405 | + return retval; |
|---|
| 401 | 406 | |
|---|
| 402 | | - if (ld != NULL) { |
|---|
| 403 | | - if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer) |
|---|
| 404 | | - ld->ops->flush_buffer(tty); |
|---|
| 405 | | - tty_ldisc_deref(ld); |
|---|
| 407 | + if (tty_write_lock(tty, 0) < 0) |
|---|
| 408 | + goto retry_write_wait; |
|---|
| 409 | + |
|---|
| 410 | + /* Racing writer? */ |
|---|
| 411 | + if (tty_chars_in_buffer(tty)) { |
|---|
| 412 | + tty_write_unlock(tty); |
|---|
| 413 | + goto retry_write_wait; |
|---|
| 414 | + } |
|---|
| 415 | + |
|---|
| 416 | + ld = tty_ldisc_ref(tty); |
|---|
| 417 | + if (ld != NULL) { |
|---|
| 418 | + if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer) |
|---|
| 419 | + ld->ops->flush_buffer(tty); |
|---|
| 420 | + tty_ldisc_deref(ld); |
|---|
| 421 | + } |
|---|
| 422 | + |
|---|
| 423 | + if ((opt & TERMIOS_WAIT) && tty->ops->wait_until_sent) { |
|---|
| 424 | + tty->ops->wait_until_sent(tty, 0); |
|---|
| 425 | + if (signal_pending(current)) { |
|---|
| 426 | + tty_write_unlock(tty); |
|---|
| 427 | + return -ERESTARTSYS; |
|---|
| 428 | + } |
|---|
| 429 | + } |
|---|
| 430 | + |
|---|
| 431 | + tty_set_termios(tty, &tmp_termios); |
|---|
| 432 | + |
|---|
| 433 | + tty_write_unlock(tty); |
|---|
| 434 | + } else { |
|---|
| 435 | + tty_set_termios(tty, &tmp_termios); |
|---|
| 406 | 436 | } |
|---|
| 407 | | - |
|---|
| 408 | | - if (opt & TERMIOS_WAIT) { |
|---|
| 409 | | - tty_wait_until_sent(tty, 0); |
|---|
| 410 | | - if (signal_pending(current)) |
|---|
| 411 | | - return -ERESTARTSYS; |
|---|
| 412 | | - } |
|---|
| 413 | | - |
|---|
| 414 | | - tty_set_termios(tty, &tmp_termios); |
|---|
| 415 | 437 | |
|---|
| 416 | 438 | /* FIXME: Arguably if tmp_termios == tty->termios AND the |
|---|
| 417 | 439 | actual requested termios was not tmp_termios then we may |
|---|