diff options
Diffstat (limited to 'drivers/char/tty_ioctl.c')
-rw-r--r-- | drivers/char/tty_ioctl.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 4d540619ac8..3b6fa7b0be8 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -423,24 +423,28 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars) | |||
423 | * | 423 | * |
424 | * Send a high priority character to the tty even if stopped | 424 | * Send a high priority character to the tty even if stopped |
425 | * | 425 | * |
426 | * Locking: none | 426 | * Locking: none for xchar method, write ordering for write method. |
427 | * | ||
428 | * FIXME: overlapping calls with start/stop tty lose state of tty | ||
429 | */ | 427 | */ |
430 | 428 | ||
431 | static void send_prio_char(struct tty_struct *tty, char ch) | 429 | static int send_prio_char(struct tty_struct *tty, char ch) |
432 | { | 430 | { |
433 | int was_stopped = tty->stopped; | 431 | int was_stopped = tty->stopped; |
434 | 432 | ||
435 | if (tty->driver->send_xchar) { | 433 | if (tty->driver->send_xchar) { |
436 | tty->driver->send_xchar(tty, ch); | 434 | tty->driver->send_xchar(tty, ch); |
437 | return; | 435 | return 0; |
438 | } | 436 | } |
437 | |||
438 | if (mutex_lock_interruptible(&tty->atomic_write_lock)) | ||
439 | return -ERESTARTSYS; | ||
440 | |||
439 | if (was_stopped) | 441 | if (was_stopped) |
440 | start_tty(tty); | 442 | start_tty(tty); |
441 | tty->driver->write(tty, &ch, 1); | 443 | tty->driver->write(tty, &ch, 1); |
442 | if (was_stopped) | 444 | if (was_stopped) |
443 | stop_tty(tty); | 445 | stop_tty(tty); |
446 | mutex_unlock(&tty->atomic_write_lock); | ||
447 | return 0; | ||
444 | } | 448 | } |
445 | 449 | ||
446 | int n_tty_ioctl(struct tty_struct * tty, struct file * file, | 450 | int n_tty_ioctl(struct tty_struct * tty, struct file * file, |
@@ -514,11 +518,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, | |||
514 | break; | 518 | break; |
515 | case TCIOFF: | 519 | case TCIOFF: |
516 | if (STOP_CHAR(tty) != __DISABLED_CHAR) | 520 | if (STOP_CHAR(tty) != __DISABLED_CHAR) |
517 | send_prio_char(tty, STOP_CHAR(tty)); | 521 | return send_prio_char(tty, STOP_CHAR(tty)); |
518 | break; | 522 | break; |
519 | case TCION: | 523 | case TCION: |
520 | if (START_CHAR(tty) != __DISABLED_CHAR) | 524 | if (START_CHAR(tty) != __DISABLED_CHAR) |
521 | send_prio_char(tty, START_CHAR(tty)); | 525 | return send_prio_char(tty, START_CHAR(tty)); |
522 | break; | 526 | break; |
523 | default: | 527 | default: |
524 | return -EINVAL; | 528 | return -EINVAL; |