aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tty_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/tty_ioctl.c')
-rw-r--r--drivers/char/tty_ioctl.c18
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
431static void send_prio_char(struct tty_struct *tty, char ch) 429static 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
446int n_tty_ioctl(struct tty_struct * tty, struct file * file, 450int 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;