aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_ldisc.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/tty/tty_ldisc.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/tty/tty_ldisc.c')
-rw-r--r--drivers/tty/tty_ldisc.c161
1 files changed, 83 insertions, 78 deletions
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index c5782294e53..a76c808afad 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -1,11 +1,19 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include <linux/major.h>
2#include <linux/errno.h> 3#include <linux/errno.h>
3#include <linux/kmod.h> 4#include <linux/signal.h>
5#include <linux/fcntl.h>
4#include <linux/sched.h> 6#include <linux/sched.h>
5#include <linux/interrupt.h> 7#include <linux/interrupt.h>
6#include <linux/tty.h> 8#include <linux/tty.h>
7#include <linux/tty_driver.h> 9#include <linux/tty_driver.h>
10#include <linux/tty_flip.h>
11#include <linux/devpts_fs.h>
8#include <linux/file.h> 12#include <linux/file.h>
13#include <linux/console.h>
14#include <linux/timer.h>
15#include <linux/ctype.h>
16#include <linux/kd.h>
9#include <linux/mm.h> 17#include <linux/mm.h>
10#include <linux/string.h> 18#include <linux/string.h>
11#include <linux/slab.h> 19#include <linux/slab.h>
@@ -16,8 +24,18 @@
16#include <linux/device.h> 24#include <linux/device.h>
17#include <linux/wait.h> 25#include <linux/wait.h>
18#include <linux/bitops.h> 26#include <linux/bitops.h>
27#include <linux/delay.h>
19#include <linux/seq_file.h> 28#include <linux/seq_file.h>
29
20#include <linux/uaccess.h> 30#include <linux/uaccess.h>
31#include <asm/system.h>
32
33#include <linux/kbd_kern.h>
34#include <linux/vt_kern.h>
35#include <linux/selection.h>
36
37#include <linux/kmod.h>
38#include <linux/nsproxy.h>
21#include <linux/ratelimit.h> 39#include <linux/ratelimit.h>
22 40
23/* 41/*
@@ -26,8 +44,9 @@
26 * callers who will do ldisc lookups and cannot sleep. 44 * callers who will do ldisc lookups and cannot sleep.
27 */ 45 */
28 46
29static DEFINE_RAW_SPINLOCK(tty_ldisc_lock); 47static DEFINE_SPINLOCK(tty_ldisc_lock);
30static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); 48static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
49static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_idle);
31/* Line disc dispatch table */ 50/* Line disc dispatch table */
32static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; 51static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
33 52
@@ -49,22 +68,22 @@ static void put_ldisc(struct tty_ldisc *ld)
49 * If this is the last user, free the ldisc, and 68 * If this is the last user, free the ldisc, and
50 * release the ldisc ops. 69 * release the ldisc ops.
51 * 70 *
52 * We really want an "atomic_dec_and_raw_lock_irqsave()", 71 * We really want an "atomic_dec_and_lock_irqsave()",
53 * but we don't have it, so this does it by hand. 72 * but we don't have it, so this does it by hand.
54 */ 73 */
55 raw_spin_lock_irqsave(&tty_ldisc_lock, flags); 74 local_irq_save(flags);
56 if (atomic_dec_and_test(&ld->users)) { 75 if (atomic_dec_and_lock(&ld->users, &tty_ldisc_lock)) {
57 struct tty_ldisc_ops *ldo = ld->ops; 76 struct tty_ldisc_ops *ldo = ld->ops;
58 77
59 ldo->refcount--; 78 ldo->refcount--;
60 module_put(ldo->owner); 79 module_put(ldo->owner);
61 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); 80 spin_unlock_irqrestore(&tty_ldisc_lock, flags);
62 81
63 kfree(ld); 82 kfree(ld);
64 return; 83 return;
65 } 84 }
66 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); 85 local_irq_restore(flags);
67 wake_up(&ld->wq_idle); 86 wake_up(&tty_ldisc_idle);
68} 87}
69 88
70/** 89/**
@@ -88,11 +107,11 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
88 if (disc < N_TTY || disc >= NR_LDISCS) 107 if (disc < N_TTY || disc >= NR_LDISCS)
89 return -EINVAL; 108 return -EINVAL;
90 109
91 raw_spin_lock_irqsave(&tty_ldisc_lock, flags); 110 spin_lock_irqsave(&tty_ldisc_lock, flags);
92 tty_ldiscs[disc] = new_ldisc; 111 tty_ldiscs[disc] = new_ldisc;
93 new_ldisc->num = disc; 112 new_ldisc->num = disc;
94 new_ldisc->refcount = 0; 113 new_ldisc->refcount = 0;
95 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); 114 spin_unlock_irqrestore(&tty_ldisc_lock, flags);
96 115
97 return ret; 116 return ret;
98} 117}
@@ -118,12 +137,12 @@ int tty_unregister_ldisc(int disc)
118 if (disc < N_TTY || disc >= NR_LDISCS) 137 if (disc < N_TTY || disc >= NR_LDISCS)
119 return -EINVAL; 138 return -EINVAL;
120 139
121 raw_spin_lock_irqsave(&tty_ldisc_lock, flags); 140 spin_lock_irqsave(&tty_ldisc_lock, flags);
122 if (tty_ldiscs[disc]->refcount) 141 if (tty_ldiscs[disc]->refcount)
123 ret = -EBUSY; 142 ret = -EBUSY;
124 else 143 else
125 tty_ldiscs[disc] = NULL; 144 tty_ldiscs[disc] = NULL;
126 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); 145 spin_unlock_irqrestore(&tty_ldisc_lock, flags);
127 146
128 return ret; 147 return ret;
129} 148}
@@ -134,7 +153,7 @@ static struct tty_ldisc_ops *get_ldops(int disc)
134 unsigned long flags; 153 unsigned long flags;
135 struct tty_ldisc_ops *ldops, *ret; 154 struct tty_ldisc_ops *ldops, *ret;
136 155
137 raw_spin_lock_irqsave(&tty_ldisc_lock, flags); 156 spin_lock_irqsave(&tty_ldisc_lock, flags);
138 ret = ERR_PTR(-EINVAL); 157 ret = ERR_PTR(-EINVAL);
139 ldops = tty_ldiscs[disc]; 158 ldops = tty_ldiscs[disc];
140 if (ldops) { 159 if (ldops) {
@@ -144,7 +163,7 @@ static struct tty_ldisc_ops *get_ldops(int disc)
144 ret = ldops; 163 ret = ldops;
145 } 164 }
146 } 165 }
147 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); 166 spin_unlock_irqrestore(&tty_ldisc_lock, flags);
148 return ret; 167 return ret;
149} 168}
150 169
@@ -152,10 +171,10 @@ static void put_ldops(struct tty_ldisc_ops *ldops)
152{ 171{
153 unsigned long flags; 172 unsigned long flags;
154 173
155 raw_spin_lock_irqsave(&tty_ldisc_lock, flags); 174 spin_lock_irqsave(&tty_ldisc_lock, flags);
156 ldops->refcount--; 175 ldops->refcount--;
157 module_put(ldops->owner); 176 module_put(ldops->owner);
158 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); 177 spin_unlock_irqrestore(&tty_ldisc_lock, flags);
159} 178}
160 179
161/** 180/**
@@ -199,8 +218,6 @@ static struct tty_ldisc *tty_ldisc_get(int disc)
199 218
200 ld->ops = ldops; 219 ld->ops = ldops;
201 atomic_set(&ld->users, 1); 220 atomic_set(&ld->users, 1);
202 init_waitqueue_head(&ld->wq_idle);
203
204 return ld; 221 return ld;
205} 222}
206 223
@@ -287,11 +304,11 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
287 unsigned long flags; 304 unsigned long flags;
288 struct tty_ldisc *ld; 305 struct tty_ldisc *ld;
289 306
290 raw_spin_lock_irqsave(&tty_ldisc_lock, flags); 307 spin_lock_irqsave(&tty_ldisc_lock, flags);
291 ld = NULL; 308 ld = NULL;
292 if (test_bit(TTY_LDISC, &tty->flags)) 309 if (test_bit(TTY_LDISC, &tty->flags))
293 ld = get_ldisc(tty->ldisc); 310 ld = get_ldisc(tty->ldisc);
294 raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); 311 spin_unlock_irqrestore(&tty_ldisc_lock, flags);
295 return ld; 312 return ld;
296} 313}
297 314
@@ -413,7 +430,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
413static void tty_set_termios_ldisc(struct tty_struct *tty, int num) 430static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
414{ 431{
415 mutex_lock(&tty->termios_mutex); 432 mutex_lock(&tty->termios_mutex);
416 tty->termios.c_line = num; 433 tty->termios->c_line = num;
417 mutex_unlock(&tty->termios_mutex); 434 mutex_unlock(&tty->termios_mutex);
418} 435}
419 436
@@ -434,6 +451,7 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
434 if (ld->ops->open) { 451 if (ld->ops->open) {
435 int ret; 452 int ret;
436 /* BTM here locks versus a hangup event */ 453 /* BTM here locks versus a hangup event */
454 WARN_ON(!tty_locked());
437 ret = ld->ops->open(tty); 455 ret = ld->ops->open(tty);
438 if (ret) 456 if (ret)
439 clear_bit(TTY_LDISC_OPEN, &tty->flags); 457 clear_bit(TTY_LDISC_OPEN, &tty->flags);
@@ -512,7 +530,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
512static int tty_ldisc_halt(struct tty_struct *tty) 530static int tty_ldisc_halt(struct tty_struct *tty)
513{ 531{
514 clear_bit(TTY_LDISC, &tty->flags); 532 clear_bit(TTY_LDISC, &tty->flags);
515 return cancel_work_sync(&tty->port->buf.work); 533 return cancel_work_sync(&tty->buf.work);
516} 534}
517 535
518/** 536/**
@@ -523,9 +541,9 @@ static int tty_ldisc_halt(struct tty_struct *tty)
523 */ 541 */
524static void tty_ldisc_flush_works(struct tty_struct *tty) 542static void tty_ldisc_flush_works(struct tty_struct *tty)
525{ 543{
526 flush_work(&tty->hangup_work); 544 flush_work_sync(&tty->hangup_work);
527 flush_work(&tty->SAK_work); 545 flush_work_sync(&tty->SAK_work);
528 flush_work(&tty->port->buf.work); 546 flush_work_sync(&tty->buf.work);
529} 547}
530 548
531/** 549/**
@@ -539,8 +557,10 @@ static void tty_ldisc_flush_works(struct tty_struct *tty)
539static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) 557static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
540{ 558{
541 long ret; 559 long ret;
542 ret = wait_event_timeout(tty->ldisc->wq_idle, 560 ret = wait_event_timeout(tty_ldisc_idle,
543 atomic_read(&tty->ldisc->users) == 1, timeout); 561 atomic_read(&tty->ldisc->users) == 1, timeout);
562 if (ret < 0)
563 return ret;
544 return ret > 0 ? 0 : -EBUSY; 564 return ret > 0 ? 0 : -EBUSY;
545} 565}
546 566
@@ -568,7 +588,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
568 if (IS_ERR(new_ldisc)) 588 if (IS_ERR(new_ldisc))
569 return PTR_ERR(new_ldisc); 589 return PTR_ERR(new_ldisc);
570 590
571 tty_lock(tty); 591 tty_lock();
572 /* 592 /*
573 * We need to look at the tty locking here for pty/tty pairs 593 * We need to look at the tty locking here for pty/tty pairs
574 * when both sides try to change in parallel. 594 * when both sides try to change in parallel.
@@ -582,12 +602,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
582 */ 602 */
583 603
584 if (tty->ldisc->ops->num == ldisc) { 604 if (tty->ldisc->ops->num == ldisc) {
585 tty_unlock(tty); 605 tty_unlock();
586 tty_ldisc_put(new_ldisc); 606 tty_ldisc_put(new_ldisc);
587 return 0; 607 return 0;
588 } 608 }
589 609
590 tty_unlock(tty); 610 tty_unlock();
591 /* 611 /*
592 * Problem: What do we do if this blocks ? 612 * Problem: What do we do if this blocks ?
593 * We could deadlock here 613 * We could deadlock here
@@ -595,7 +615,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
595 615
596 tty_wait_until_sent(tty, 0); 616 tty_wait_until_sent(tty, 0);
597 617
598 tty_lock(tty); 618 tty_lock();
599 mutex_lock(&tty->ldisc_mutex); 619 mutex_lock(&tty->ldisc_mutex);
600 620
601 /* 621 /*
@@ -605,10 +625,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
605 625
606 while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { 626 while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
607 mutex_unlock(&tty->ldisc_mutex); 627 mutex_unlock(&tty->ldisc_mutex);
608 tty_unlock(tty); 628 tty_unlock();
609 wait_event(tty_ldisc_wait, 629 wait_event(tty_ldisc_wait,
610 test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); 630 test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
611 tty_lock(tty); 631 tty_lock();
612 mutex_lock(&tty->ldisc_mutex); 632 mutex_lock(&tty->ldisc_mutex);
613 } 633 }
614 634
@@ -623,7 +643,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
623 643
624 o_ldisc = tty->ldisc; 644 o_ldisc = tty->ldisc;
625 645
626 tty_unlock(tty); 646 tty_unlock();
627 /* 647 /*
628 * Make sure we don't change while someone holds a 648 * Make sure we don't change while someone holds a
629 * reference to the line discipline. The TTY_LDISC bit 649 * reference to the line discipline. The TTY_LDISC bit
@@ -650,7 +670,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
650 670
651 retval = tty_ldisc_wait_idle(tty, 5 * HZ); 671 retval = tty_ldisc_wait_idle(tty, 5 * HZ);
652 672
653 tty_lock(tty); 673 tty_lock();
654 mutex_lock(&tty->ldisc_mutex); 674 mutex_lock(&tty->ldisc_mutex);
655 675
656 /* handle wait idle failure locked */ 676 /* handle wait idle failure locked */
@@ -659,13 +679,13 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
659 goto enable; 679 goto enable;
660 } 680 }
661 681
662 if (test_bit(TTY_HUPPING, &tty->flags)) { 682 if (test_bit(TTY_HUPPED, &tty->flags)) {
663 /* We were raced by the hangup method. It will have stomped 683 /* We were raced by the hangup method. It will have stomped
664 the ldisc data and closed the ldisc down */ 684 the ldisc data and closed the ldisc down */
665 clear_bit(TTY_LDISC_CHANGING, &tty->flags); 685 clear_bit(TTY_LDISC_CHANGING, &tty->flags);
666 mutex_unlock(&tty->ldisc_mutex); 686 mutex_unlock(&tty->ldisc_mutex);
667 tty_ldisc_put(new_ldisc); 687 tty_ldisc_put(new_ldisc);
668 tty_unlock(tty); 688 tty_unlock();
669 return -EIO; 689 return -EIO;
670 } 690 }
671 691
@@ -704,11 +724,11 @@ enable:
704 /* Restart the work queue in case no characters kick it off. Safe if 724 /* Restart the work queue in case no characters kick it off. Safe if
705 already running */ 725 already running */
706 if (work) 726 if (work)
707 schedule_work(&tty->port->buf.work); 727 schedule_work(&tty->buf.work);
708 if (o_work) 728 if (o_work)
709 schedule_work(&o_tty->port->buf.work); 729 schedule_work(&o_tty->buf.work);
710 mutex_unlock(&tty->ldisc_mutex); 730 mutex_unlock(&tty->ldisc_mutex);
711 tty_unlock(tty); 731 tty_unlock();
712 return retval; 732 return retval;
713} 733}
714 734
@@ -722,9 +742,9 @@ enable:
722static void tty_reset_termios(struct tty_struct *tty) 742static void tty_reset_termios(struct tty_struct *tty)
723{ 743{
724 mutex_lock(&tty->termios_mutex); 744 mutex_lock(&tty->termios_mutex);
725 tty->termios = tty->driver->init_termios; 745 *tty->termios = tty->driver->init_termios;
726 tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios); 746 tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
727 tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios); 747 tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
728 mutex_unlock(&tty->termios_mutex); 748 mutex_unlock(&tty->termios_mutex);
729} 749}
730 750
@@ -816,11 +836,11 @@ void tty_ldisc_hangup(struct tty_struct *tty)
816 * need to wait for another function taking the BTM 836 * need to wait for another function taking the BTM
817 */ 837 */
818 clear_bit(TTY_LDISC, &tty->flags); 838 clear_bit(TTY_LDISC, &tty->flags);
819 tty_unlock(tty); 839 tty_unlock();
820 cancel_work_sync(&tty->port->buf.work); 840 cancel_work_sync(&tty->buf.work);
821 mutex_unlock(&tty->ldisc_mutex); 841 mutex_unlock(&tty->ldisc_mutex);
822retry: 842retry:
823 tty_lock(tty); 843 tty_lock();
824 mutex_lock(&tty->ldisc_mutex); 844 mutex_lock(&tty->ldisc_mutex);
825 845
826 /* At this point we have a closed ldisc and we want to 846 /* At this point we have a closed ldisc and we want to
@@ -831,7 +851,7 @@ retry:
831 if (atomic_read(&tty->ldisc->users) != 1) { 851 if (atomic_read(&tty->ldisc->users) != 1) {
832 char cur_n[TASK_COMM_LEN], tty_n[64]; 852 char cur_n[TASK_COMM_LEN], tty_n[64];
833 long timeout = 3 * HZ; 853 long timeout = 3 * HZ;
834 tty_unlock(tty); 854 tty_unlock();
835 855
836 while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { 856 while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
837 timeout = MAX_SCHEDULE_TIMEOUT; 857 timeout = MAX_SCHEDULE_TIMEOUT;
@@ -846,7 +866,7 @@ retry:
846 866
847 if (reset == 0) { 867 if (reset == 0) {
848 868
849 if (!tty_ldisc_reinit(tty, tty->termios.c_line)) 869 if (!tty_ldisc_reinit(tty, tty->termios->c_line))
850 err = tty_ldisc_open(tty, tty->ldisc); 870 err = tty_ldisc_open(tty, tty->ldisc);
851 else 871 else
852 err = 1; 872 err = 1;
@@ -894,28 +914,6 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
894 tty_ldisc_enable(tty); 914 tty_ldisc_enable(tty);
895 return 0; 915 return 0;
896} 916}
897
898static void tty_ldisc_kill(struct tty_struct *tty)
899{
900 /* There cannot be users from userspace now. But there still might be
901 * drivers holding a reference via tty_ldisc_ref. Do not steal them the
902 * ldisc until they are done. */
903 tty_ldisc_wait_idle(tty, MAX_SCHEDULE_TIMEOUT);
904
905 mutex_lock(&tty->ldisc_mutex);
906 /*
907 * Now kill off the ldisc
908 */
909 tty_ldisc_close(tty, tty->ldisc);
910 tty_ldisc_put(tty->ldisc);
911 /* Force an oops if we mess this up */
912 tty->ldisc = NULL;
913
914 /* Ensure the next open requests the N_TTY ldisc */
915 tty_set_termios_ldisc(tty, N_TTY);
916 mutex_unlock(&tty->ldisc_mutex);
917}
918
919/** 917/**
920 * tty_ldisc_release - release line discipline 918 * tty_ldisc_release - release line discipline
921 * @tty: tty being shut down 919 * @tty: tty being shut down
@@ -934,21 +932,28 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
934 * race with the set_ldisc code path. 932 * race with the set_ldisc code path.
935 */ 933 */
936 934
937 tty_lock_pair(tty, o_tty); 935 tty_unlock();
938 tty_ldisc_halt(tty); 936 tty_ldisc_halt(tty);
939 tty_ldisc_flush_works(tty); 937 tty_ldisc_flush_works(tty);
940 if (o_tty) { 938 tty_lock();
941 tty_ldisc_halt(o_tty);
942 tty_ldisc_flush_works(o_tty);
943 }
944 939
945 /* This will need doing differently if we need to lock */ 940 mutex_lock(&tty->ldisc_mutex);
946 tty_ldisc_kill(tty); 941 /*
942 * Now kill off the ldisc
943 */
944 tty_ldisc_close(tty, tty->ldisc);
945 tty_ldisc_put(tty->ldisc);
946 /* Force an oops if we mess this up */
947 tty->ldisc = NULL;
947 948
949 /* Ensure the next open requests the N_TTY ldisc */
950 tty_set_termios_ldisc(tty, N_TTY);
951 mutex_unlock(&tty->ldisc_mutex);
952
953 /* This will need doing differently if we need to lock */
948 if (o_tty) 954 if (o_tty)
949 tty_ldisc_kill(o_tty); 955 tty_ldisc_release(o_tty, NULL);
950 956
951 tty_unlock_pair(tty, o_tty);
952 /* And the memory resources remaining (buffers, termios) will be 957 /* And the memory resources remaining (buffers, termios) will be
953 disposed of when the kref hits zero */ 958 disposed of when the kref hits zero */
954} 959}