diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2008-04-30 03:54:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 11:29:47 -0400 |
commit | f34d7a5b7010b82fe97da95496b9971435530062 (patch) | |
tree | 87e2abec1e33ed4fe5e63ee2fd000bc2ad745e57 /drivers/char/tty_ioctl.c | |
parent | 251b8dd7eee30fda089a1dc088abf4fc9a0dee9c (diff) |
tty: The big operations rework
- Operations are now a shared const function block as with most other Linux
objects
- Introduce wrappers for some optional functions to get consistent behaviour
- Wrap put_char which used to be patched by the tty layer
- Document which functions are needed/optional
- Make put_char report success/fail
- Cache the driver->ops pointer in the tty as tty->ops
- Remove various surplus lock calls we no longer need
- Remove proc_write method as noted by Alexey Dobriyan
- Introduce some missing sanity checks where certain driver/ldisc
combinations would oops as they didn't check needed methods were present
[akpm@linux-foundation.org: fix fs/compat_ioctl.c build]
[akpm@linux-foundation.org: fix isicom]
[akpm@linux-foundation.org: fix arch/ia64/hp/sim/simserial.c build]
[akpm@linux-foundation.org: fix kgdb]
Signed-off-by: Alan Cox <alan@redhat.com>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Jason Wessel <jason.wessel@windriver.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 | 62 |
1 files changed, 42 insertions, 20 deletions
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 8c4bf3e48d5b..c10d40c4c5ca 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -40,6 +40,34 @@ | |||
40 | #define TERMIOS_OLD 8 | 40 | #define TERMIOS_OLD 8 |
41 | 41 | ||
42 | 42 | ||
43 | int tty_chars_in_buffer(struct tty_struct *tty) | ||
44 | { | ||
45 | if (tty->ops->chars_in_buffer) | ||
46 | return tty->ops->chars_in_buffer(tty); | ||
47 | else | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | EXPORT_SYMBOL(tty_chars_in_buffer); | ||
52 | |||
53 | int tty_write_room(struct tty_struct *tty) | ||
54 | { | ||
55 | if (tty->ops->write_room) | ||
56 | return tty->ops->write_room(tty); | ||
57 | return 2048; | ||
58 | } | ||
59 | |||
60 | EXPORT_SYMBOL(tty_write_room); | ||
61 | |||
62 | void tty_driver_flush_buffer(struct tty_struct *tty) | ||
63 | { | ||
64 | if (tty->ops->flush_buffer) | ||
65 | tty->ops->flush_buffer(tty); | ||
66 | } | ||
67 | |||
68 | EXPORT_SYMBOL(tty_driver_flush_buffer); | ||
69 | |||
70 | |||
43 | /** | 71 | /** |
44 | * tty_wait_until_sent - wait for I/O to finish | 72 | * tty_wait_until_sent - wait for I/O to finish |
45 | * @tty: tty we are waiting for | 73 | * @tty: tty we are waiting for |
@@ -58,17 +86,13 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout) | |||
58 | 86 | ||
59 | printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf)); | 87 | printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf)); |
60 | #endif | 88 | #endif |
61 | if (!tty->driver->chars_in_buffer) | ||
62 | return; | ||
63 | if (!timeout) | 89 | if (!timeout) |
64 | timeout = MAX_SCHEDULE_TIMEOUT; | 90 | timeout = MAX_SCHEDULE_TIMEOUT; |
65 | lock_kernel(); | ||
66 | if (wait_event_interruptible_timeout(tty->write_wait, | 91 | if (wait_event_interruptible_timeout(tty->write_wait, |
67 | !tty->driver->chars_in_buffer(tty), timeout) >= 0) { | 92 | !tty_chars_in_buffer(tty), timeout) >= 0) { |
68 | if (tty->driver->wait_until_sent) | 93 | if (tty->ops->wait_until_sent) |
69 | tty->driver->wait_until_sent(tty, timeout); | 94 | tty->ops->wait_until_sent(tty, timeout); |
70 | } | 95 | } |
71 | unlock_kernel(); | ||
72 | } | 96 | } |
73 | EXPORT_SYMBOL(tty_wait_until_sent); | 97 | EXPORT_SYMBOL(tty_wait_until_sent); |
74 | 98 | ||
@@ -444,8 +468,8 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) | |||
444 | } | 468 | } |
445 | } | 469 | } |
446 | 470 | ||
447 | if (tty->driver->set_termios) | 471 | if (tty->ops->set_termios) |
448 | (*tty->driver->set_termios)(tty, &old_termios); | 472 | (*tty->ops->set_termios)(tty, &old_termios); |
449 | else | 473 | else |
450 | tty_termios_copy_hw(tty->termios, &old_termios); | 474 | tty_termios_copy_hw(tty->termios, &old_termios); |
451 | 475 | ||
@@ -748,8 +772,8 @@ static int send_prio_char(struct tty_struct *tty, char ch) | |||
748 | { | 772 | { |
749 | int was_stopped = tty->stopped; | 773 | int was_stopped = tty->stopped; |
750 | 774 | ||
751 | if (tty->driver->send_xchar) { | 775 | if (tty->ops->send_xchar) { |
752 | tty->driver->send_xchar(tty, ch); | 776 | tty->ops->send_xchar(tty, ch); |
753 | return 0; | 777 | return 0; |
754 | } | 778 | } |
755 | 779 | ||
@@ -758,7 +782,7 @@ static int send_prio_char(struct tty_struct *tty, char ch) | |||
758 | 782 | ||
759 | if (was_stopped) | 783 | if (was_stopped) |
760 | start_tty(tty); | 784 | start_tty(tty); |
761 | tty->driver->write(tty, &ch, 1); | 785 | tty->ops->write(tty, &ch, 1); |
762 | if (was_stopped) | 786 | if (was_stopped) |
763 | stop_tty(tty); | 787 | stop_tty(tty); |
764 | tty_write_unlock(tty); | 788 | tty_write_unlock(tty); |
@@ -778,13 +802,14 @@ static int tty_change_softcar(struct tty_struct *tty, int arg) | |||
778 | { | 802 | { |
779 | int ret = 0; | 803 | int ret = 0; |
780 | int bit = arg ? CLOCAL : 0; | 804 | int bit = arg ? CLOCAL : 0; |
781 | struct ktermios old = *tty->termios; | 805 | struct ktermios old; |
782 | 806 | ||
783 | mutex_lock(&tty->termios_mutex); | 807 | mutex_lock(&tty->termios_mutex); |
808 | old = *tty->termios; | ||
784 | tty->termios->c_cflag &= ~CLOCAL; | 809 | tty->termios->c_cflag &= ~CLOCAL; |
785 | tty->termios->c_cflag |= bit; | 810 | tty->termios->c_cflag |= bit; |
786 | if (tty->driver->set_termios) | 811 | if (tty->ops->set_termios) |
787 | tty->driver->set_termios(tty, &old); | 812 | tty->ops->set_termios(tty, &old); |
788 | if ((tty->termios->c_cflag & CLOCAL) != bit) | 813 | if ((tty->termios->c_cflag & CLOCAL) != bit) |
789 | ret = -EINVAL; | 814 | ret = -EINVAL; |
790 | mutex_unlock(&tty->termios_mutex); | 815 | mutex_unlock(&tty->termios_mutex); |
@@ -926,8 +951,7 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg) | |||
926 | ld->flush_buffer(tty); | 951 | ld->flush_buffer(tty); |
927 | /* fall through */ | 952 | /* fall through */ |
928 | case TCOFLUSH: | 953 | case TCOFLUSH: |
929 | if (tty->driver->flush_buffer) | 954 | tty_driver_flush_buffer(tty); |
930 | tty->driver->flush_buffer(tty); | ||
931 | break; | 955 | break; |
932 | default: | 956 | default: |
933 | tty_ldisc_deref(ld); | 957 | tty_ldisc_deref(ld); |
@@ -984,9 +1008,7 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file, | |||
984 | case TCFLSH: | 1008 | case TCFLSH: |
985 | return tty_perform_flush(tty, arg); | 1009 | return tty_perform_flush(tty, arg); |
986 | case TIOCOUTQ: | 1010 | case TIOCOUTQ: |
987 | return put_user(tty->driver->chars_in_buffer ? | 1011 | return put_user(tty_chars_in_buffer(tty), (int __user *) arg); |
988 | tty->driver->chars_in_buffer(tty) : 0, | ||
989 | (int __user *) arg); | ||
990 | case TIOCINQ: | 1012 | case TIOCINQ: |
991 | retval = tty->read_cnt; | 1013 | retval = tty->read_cnt; |
992 | if (L_ICANON(tty)) | 1014 | if (L_ICANON(tty)) |