aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tty_ioctl.c
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2006-09-29 05:01:40 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-29 12:18:24 -0400
commit5f412b24240d92212e50ebbaff2dff20c9e6f3d0 (patch)
tree4929d68d6949c887fbd3fb0594b0c1ec5a7e765d /drivers/char/tty_ioctl.c
parent67cc0161ecc9ebee6eba4af6cbfdba028090b1b9 (diff)
[PATCH] Fix locking for tty drivers when doing urgent characters
If you send a priority character (as is done for flow control) then the tty driver can either have its own method for "jumping the queue" or the characrer can be queued normally. In the latter case we call the write method but without the atomic_write_lock taken elsewhere. Make this consistent. Note that the send_xchar method if implemented remains outside of the lock as it can jump ahead of a current write so must not be locked out by it. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
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 4d540619ac84..3b6fa7b0be8b 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;