diff options
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r-- | drivers/tty/tty_io.c | 96 |
1 files changed, 60 insertions, 36 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 8fbad3410c75..2f6f9b5e4891 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -908,8 +908,7 @@ void no_tty(void) | |||
908 | * stop_tty - propagate flow control | 908 | * stop_tty - propagate flow control |
909 | * @tty: tty to stop | 909 | * @tty: tty to stop |
910 | * | 910 | * |
911 | * Perform flow control to the driver. For PTY/TTY pairs we | 911 | * Perform flow control to the driver. May be called |
912 | * must also propagate the TIOCKPKT status. May be called | ||
913 | * on an already stopped device and will not re-call the driver | 912 | * on an already stopped device and will not re-call the driver |
914 | * method. | 913 | * method. |
915 | * | 914 | * |
@@ -919,64 +918,58 @@ void no_tty(void) | |||
919 | * but not always. | 918 | * but not always. |
920 | * | 919 | * |
921 | * Locking: | 920 | * Locking: |
922 | * Uses the tty control lock internally | 921 | * flow_lock |
923 | */ | 922 | */ |
924 | 923 | ||
925 | void stop_tty(struct tty_struct *tty) | 924 | void __stop_tty(struct tty_struct *tty) |
926 | { | 925 | { |
927 | unsigned long flags; | 926 | if (tty->stopped) |
928 | spin_lock_irqsave(&tty->ctrl_lock, flags); | ||
929 | if (tty->stopped) { | ||
930 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | ||
931 | return; | 927 | return; |
932 | } | ||
933 | tty->stopped = 1; | 928 | tty->stopped = 1; |
934 | if (tty->link && tty->link->packet) { | ||
935 | tty->ctrl_status &= ~TIOCPKT_START; | ||
936 | tty->ctrl_status |= TIOCPKT_STOP; | ||
937 | wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); | ||
938 | } | ||
939 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | ||
940 | if (tty->ops->stop) | 929 | if (tty->ops->stop) |
941 | (tty->ops->stop)(tty); | 930 | (tty->ops->stop)(tty); |
942 | } | 931 | } |
943 | 932 | ||
933 | void stop_tty(struct tty_struct *tty) | ||
934 | { | ||
935 | unsigned long flags; | ||
936 | |||
937 | spin_lock_irqsave(&tty->flow_lock, flags); | ||
938 | __stop_tty(tty); | ||
939 | spin_unlock_irqrestore(&tty->flow_lock, flags); | ||
940 | } | ||
944 | EXPORT_SYMBOL(stop_tty); | 941 | EXPORT_SYMBOL(stop_tty); |
945 | 942 | ||
946 | /** | 943 | /** |
947 | * start_tty - propagate flow control | 944 | * start_tty - propagate flow control |
948 | * @tty: tty to start | 945 | * @tty: tty to start |
949 | * | 946 | * |
950 | * Start a tty that has been stopped if at all possible. Perform | 947 | * Start a tty that has been stopped if at all possible. If this |
951 | * any necessary wakeups and propagate the TIOCPKT status. If this | 948 | * tty was previous stopped and is now being started, the driver |
952 | * is the tty was previous stopped and is being started then the | 949 | * start method is invoked and the line discipline woken. |
953 | * driver start method is invoked and the line discipline woken. | ||
954 | * | 950 | * |
955 | * Locking: | 951 | * Locking: |
956 | * ctrl_lock | 952 | * flow_lock |
957 | */ | 953 | */ |
958 | 954 | ||
959 | void start_tty(struct tty_struct *tty) | 955 | void __start_tty(struct tty_struct *tty) |
960 | { | 956 | { |
961 | unsigned long flags; | 957 | if (!tty->stopped || tty->flow_stopped) |
962 | spin_lock_irqsave(&tty->ctrl_lock, flags); | ||
963 | if (!tty->stopped || tty->flow_stopped) { | ||
964 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | ||
965 | return; | 958 | return; |
966 | } | ||
967 | tty->stopped = 0; | 959 | tty->stopped = 0; |
968 | if (tty->link && tty->link->packet) { | ||
969 | tty->ctrl_status &= ~TIOCPKT_STOP; | ||
970 | tty->ctrl_status |= TIOCPKT_START; | ||
971 | wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); | ||
972 | } | ||
973 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | ||
974 | if (tty->ops->start) | 960 | if (tty->ops->start) |
975 | (tty->ops->start)(tty); | 961 | (tty->ops->start)(tty); |
976 | /* If we have a running line discipline it may need kicking */ | ||
977 | tty_wakeup(tty); | 962 | tty_wakeup(tty); |
978 | } | 963 | } |
979 | 964 | ||
965 | void start_tty(struct tty_struct *tty) | ||
966 | { | ||
967 | unsigned long flags; | ||
968 | |||
969 | spin_lock_irqsave(&tty->flow_lock, flags); | ||
970 | __start_tty(tty); | ||
971 | spin_unlock_irqrestore(&tty->flow_lock, flags); | ||
972 | } | ||
980 | EXPORT_SYMBOL(start_tty); | 973 | EXPORT_SYMBOL(start_tty); |
981 | 974 | ||
982 | /* We limit tty time update visibility to every 8 seconds or so. */ | 975 | /* We limit tty time update visibility to every 8 seconds or so. */ |
@@ -1030,14 +1023,14 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, | |||
1030 | return i; | 1023 | return i; |
1031 | } | 1024 | } |
1032 | 1025 | ||
1033 | void tty_write_unlock(struct tty_struct *tty) | 1026 | static void tty_write_unlock(struct tty_struct *tty) |
1034 | __releases(&tty->atomic_write_lock) | 1027 | __releases(&tty->atomic_write_lock) |
1035 | { | 1028 | { |
1036 | mutex_unlock(&tty->atomic_write_lock); | 1029 | mutex_unlock(&tty->atomic_write_lock); |
1037 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); | 1030 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); |
1038 | } | 1031 | } |
1039 | 1032 | ||
1040 | int tty_write_lock(struct tty_struct *tty, int ndelay) | 1033 | static int tty_write_lock(struct tty_struct *tty, int ndelay) |
1041 | __acquires(&tty->atomic_write_lock) | 1034 | __acquires(&tty->atomic_write_lock) |
1042 | { | 1035 | { |
1043 | if (!mutex_trylock(&tty->atomic_write_lock)) { | 1036 | if (!mutex_trylock(&tty->atomic_write_lock)) { |
@@ -1224,6 +1217,35 @@ ssize_t redirected_tty_write(struct file *file, const char __user *buf, | |||
1224 | return tty_write(file, buf, count, ppos); | 1217 | return tty_write(file, buf, count, ppos); |
1225 | } | 1218 | } |
1226 | 1219 | ||
1220 | /** | ||
1221 | * tty_send_xchar - send priority character | ||
1222 | * | ||
1223 | * Send a high priority character to the tty even if stopped | ||
1224 | * | ||
1225 | * Locking: none for xchar method, write ordering for write method. | ||
1226 | */ | ||
1227 | |||
1228 | int tty_send_xchar(struct tty_struct *tty, char ch) | ||
1229 | { | ||
1230 | int was_stopped = tty->stopped; | ||
1231 | |||
1232 | if (tty->ops->send_xchar) { | ||
1233 | tty->ops->send_xchar(tty, ch); | ||
1234 | return 0; | ||
1235 | } | ||
1236 | |||
1237 | if (tty_write_lock(tty, 0) < 0) | ||
1238 | return -ERESTARTSYS; | ||
1239 | |||
1240 | if (was_stopped) | ||
1241 | start_tty(tty); | ||
1242 | tty->ops->write(tty, &ch, 1); | ||
1243 | if (was_stopped) | ||
1244 | stop_tty(tty); | ||
1245 | tty_write_unlock(tty); | ||
1246 | return 0; | ||
1247 | } | ||
1248 | |||
1227 | static char ptychar[] = "pqrstuvwxyzabcde"; | 1249 | static char ptychar[] = "pqrstuvwxyzabcde"; |
1228 | 1250 | ||
1229 | /** | 1251 | /** |
@@ -1544,13 +1566,14 @@ static void release_one_tty(struct work_struct *work) | |||
1544 | struct tty_struct *tty = | 1566 | struct tty_struct *tty = |
1545 | container_of(work, struct tty_struct, hangup_work); | 1567 | container_of(work, struct tty_struct, hangup_work); |
1546 | struct tty_driver *driver = tty->driver; | 1568 | struct tty_driver *driver = tty->driver; |
1569 | struct module *owner = driver->owner; | ||
1547 | 1570 | ||
1548 | if (tty->ops->cleanup) | 1571 | if (tty->ops->cleanup) |
1549 | tty->ops->cleanup(tty); | 1572 | tty->ops->cleanup(tty); |
1550 | 1573 | ||
1551 | tty->magic = 0; | 1574 | tty->magic = 0; |
1552 | tty_driver_kref_put(driver); | 1575 | tty_driver_kref_put(driver); |
1553 | module_put(driver->owner); | 1576 | module_put(owner); |
1554 | 1577 | ||
1555 | spin_lock(&tty_files_lock); | 1578 | spin_lock(&tty_files_lock); |
1556 | list_del_init(&tty->tty_files); | 1579 | list_del_init(&tty->tty_files); |
@@ -3018,6 +3041,7 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) | |||
3018 | INIT_WORK(&tty->hangup_work, do_tty_hangup); | 3041 | INIT_WORK(&tty->hangup_work, do_tty_hangup); |
3019 | mutex_init(&tty->atomic_write_lock); | 3042 | mutex_init(&tty->atomic_write_lock); |
3020 | spin_lock_init(&tty->ctrl_lock); | 3043 | spin_lock_init(&tty->ctrl_lock); |
3044 | spin_lock_init(&tty->flow_lock); | ||
3021 | INIT_LIST_HEAD(&tty->tty_files); | 3045 | INIT_LIST_HEAD(&tty->tty_files); |
3022 | INIT_WORK(&tty->SAK_work, do_SAK_work); | 3046 | INIT_WORK(&tty->SAK_work, do_SAK_work); |
3023 | 3047 | ||