diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2008-04-30 03:53:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 11:29:45 -0400 |
commit | 978e595f88a1fba5869aa42a4af4fba36f33ecac (patch) | |
tree | 60848f49949c5b7b518621ee36cdc6d500244539 /drivers/char/tty_ioctl.c | |
parent | ac0e4b7d319bf284bb64bc7e1c051417386b34a4 (diff) |
tty/serial: lay the foundations for the next set of reworks
- Stop drivers calling their own flush method indirectly, it obfuscates code
and it will change soon anyway
- A few more lock_kernel paths temporarily needed in some driver internal
waiting code
- Remove private put_char method that does a write call for one char - we
have that anyway
- Most but not yet all of the termios copy under lock fixing (some has other
dependencies to follow)
- Note a few locking bugs in drivers found in the process
- Kill remaining [ab]users of TIOCG/SSOFTCAR in the driver, these must go to
fix the termios locking
Signed-off-by: Alan Cox <alan@redhat.com>
Cc: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/tty_ioctl.c')
-rw-r--r-- | drivers/char/tty_ioctl.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index d769e43f73fb..8c4bf3e48d5b 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -396,7 +396,7 @@ EXPORT_SYMBOL(tty_termios_hw_change); | |||
396 | static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) | 396 | static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) |
397 | { | 397 | { |
398 | int canon_change; | 398 | int canon_change; |
399 | struct ktermios old_termios = *tty->termios; | 399 | struct ktermios old_termios; |
400 | struct tty_ldisc *ld; | 400 | struct tty_ldisc *ld; |
401 | unsigned long flags; | 401 | unsigned long flags; |
402 | 402 | ||
@@ -408,7 +408,7 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) | |||
408 | /* FIXME: we need to decide on some locking/ordering semantics | 408 | /* FIXME: we need to decide on some locking/ordering semantics |
409 | for the set_termios notification eventually */ | 409 | for the set_termios notification eventually */ |
410 | mutex_lock(&tty->termios_mutex); | 410 | mutex_lock(&tty->termios_mutex); |
411 | 411 | old_termios = *tty->termios; | |
412 | *tty->termios = *new_termios; | 412 | *tty->termios = *new_termios; |
413 | unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); | 413 | unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); |
414 | canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON; | 414 | canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON; |
@@ -480,7 +480,9 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) | |||
480 | if (retval) | 480 | if (retval) |
481 | return retval; | 481 | return retval; |
482 | 482 | ||
483 | mutex_lock(&tty->termios_mutex); | ||
483 | memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios)); | 484 | memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios)); |
485 | mutex_unlock(&tty->termios_mutex); | ||
484 | 486 | ||
485 | if (opt & TERMIOS_TERMIO) { | 487 | if (opt & TERMIOS_TERMIO) { |
486 | if (user_termio_to_kernel_termios(&tmp_termios, | 488 | if (user_termio_to_kernel_termios(&tmp_termios, |
@@ -666,12 +668,14 @@ static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars) | |||
666 | { | 668 | { |
667 | struct tchars tmp; | 669 | struct tchars tmp; |
668 | 670 | ||
671 | mutex_lock(&tty->termios_mutex); | ||
669 | tmp.t_intrc = tty->termios->c_cc[VINTR]; | 672 | tmp.t_intrc = tty->termios->c_cc[VINTR]; |
670 | tmp.t_quitc = tty->termios->c_cc[VQUIT]; | 673 | tmp.t_quitc = tty->termios->c_cc[VQUIT]; |
671 | tmp.t_startc = tty->termios->c_cc[VSTART]; | 674 | tmp.t_startc = tty->termios->c_cc[VSTART]; |
672 | tmp.t_stopc = tty->termios->c_cc[VSTOP]; | 675 | tmp.t_stopc = tty->termios->c_cc[VSTOP]; |
673 | tmp.t_eofc = tty->termios->c_cc[VEOF]; | 676 | tmp.t_eofc = tty->termios->c_cc[VEOF]; |
674 | tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */ | 677 | tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */ |
678 | mutex_unlock(&tty->termios_mutex); | ||
675 | return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; | 679 | return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; |
676 | } | 680 | } |
677 | 681 | ||
@@ -681,12 +685,14 @@ static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars) | |||
681 | 685 | ||
682 | if (copy_from_user(&tmp, tchars, sizeof(tmp))) | 686 | if (copy_from_user(&tmp, tchars, sizeof(tmp))) |
683 | return -EFAULT; | 687 | return -EFAULT; |
688 | mutex_lock(&tty->termios_mutex); | ||
684 | tty->termios->c_cc[VINTR] = tmp.t_intrc; | 689 | tty->termios->c_cc[VINTR] = tmp.t_intrc; |
685 | tty->termios->c_cc[VQUIT] = tmp.t_quitc; | 690 | tty->termios->c_cc[VQUIT] = tmp.t_quitc; |
686 | tty->termios->c_cc[VSTART] = tmp.t_startc; | 691 | tty->termios->c_cc[VSTART] = tmp.t_startc; |
687 | tty->termios->c_cc[VSTOP] = tmp.t_stopc; | 692 | tty->termios->c_cc[VSTOP] = tmp.t_stopc; |
688 | tty->termios->c_cc[VEOF] = tmp.t_eofc; | 693 | tty->termios->c_cc[VEOF] = tmp.t_eofc; |
689 | tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */ | 694 | tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */ |
695 | mutex_unlock(&tty->termios_mutex); | ||
690 | return 0; | 696 | return 0; |
691 | } | 697 | } |
692 | #endif | 698 | #endif |
@@ -696,6 +702,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) | |||
696 | { | 702 | { |
697 | struct ltchars tmp; | 703 | struct ltchars tmp; |
698 | 704 | ||
705 | mutex_lock(&tty->termios_mutex); | ||
699 | tmp.t_suspc = tty->termios->c_cc[VSUSP]; | 706 | tmp.t_suspc = tty->termios->c_cc[VSUSP]; |
700 | /* what is dsuspc anyway? */ | 707 | /* what is dsuspc anyway? */ |
701 | tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; | 708 | tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; |
@@ -704,6 +711,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) | |||
704 | tmp.t_flushc = tty->termios->c_cc[VEOL2]; | 711 | tmp.t_flushc = tty->termios->c_cc[VEOL2]; |
705 | tmp.t_werasc = tty->termios->c_cc[VWERASE]; | 712 | tmp.t_werasc = tty->termios->c_cc[VWERASE]; |
706 | tmp.t_lnextc = tty->termios->c_cc[VLNEXT]; | 713 | tmp.t_lnextc = tty->termios->c_cc[VLNEXT]; |
714 | mutex_unlock(&tty->termios_mutex); | ||
707 | return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; | 715 | return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; |
708 | } | 716 | } |
709 | 717 | ||
@@ -714,6 +722,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) | |||
714 | if (copy_from_user(&tmp, ltchars, sizeof(tmp))) | 722 | if (copy_from_user(&tmp, ltchars, sizeof(tmp))) |
715 | return -EFAULT; | 723 | return -EFAULT; |
716 | 724 | ||
725 | mutex_lock(&tty->termios_mutex); | ||
717 | tty->termios->c_cc[VSUSP] = tmp.t_suspc; | 726 | tty->termios->c_cc[VSUSP] = tmp.t_suspc; |
718 | /* what is dsuspc anyway? */ | 727 | /* what is dsuspc anyway? */ |
719 | tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; | 728 | tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; |
@@ -722,6 +731,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) | |||
722 | tty->termios->c_cc[VEOL2] = tmp.t_flushc; | 731 | tty->termios->c_cc[VEOL2] = tmp.t_flushc; |
723 | tty->termios->c_cc[VWERASE] = tmp.t_werasc; | 732 | tty->termios->c_cc[VWERASE] = tmp.t_werasc; |
724 | tty->termios->c_cc[VLNEXT] = tmp.t_lnextc; | 733 | tty->termios->c_cc[VLNEXT] = tmp.t_lnextc; |
734 | mutex_unlock(&tty->termios_mutex); | ||
725 | return 0; | 735 | return 0; |
726 | } | 736 | } |
727 | #endif | 737 | #endif |