diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/cyclades.c | 3 | ||||
-rw-r--r-- | drivers/char/epca.c | 4 | ||||
-rw-r--r-- | drivers/char/ip2/i2lib.c | 4 | ||||
-rw-r--r-- | drivers/char/ip2/ip2main.c | 7 | ||||
-rw-r--r-- | drivers/char/n_hdlc.c | 6 | ||||
-rw-r--r-- | drivers/char/n_r3964.c | 2 | ||||
-rw-r--r-- | drivers/char/n_tty.c | 2 | ||||
-rw-r--r-- | drivers/char/pcmcia/synclink_cs.c | 4 | ||||
-rw-r--r-- | drivers/char/pty.c | 10 | ||||
-rw-r--r-- | drivers/char/selection.c | 3 | ||||
-rw-r--r-- | drivers/char/synclink.c | 4 | ||||
-rw-r--r-- | drivers/char/synclink_gt.c | 4 | ||||
-rw-r--r-- | drivers/char/synclinkmp.c | 4 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 336 | ||||
-rw-r--r-- | drivers/char/tty_ioctl.c | 16 |
15 files changed, 251 insertions, 158 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 6bff9d87dc57..a957dbcc5a46 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -5246,7 +5246,8 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, | |||
5246 | HZ, info->idle_stats.recv_bytes, | 5246 | HZ, info->idle_stats.recv_bytes, |
5247 | (cur_jifs - info->idle_stats.recv_idle)/ | 5247 | (cur_jifs - info->idle_stats.recv_idle)/ |
5248 | HZ, info->idle_stats.overruns, | 5248 | HZ, info->idle_stats.overruns, |
5249 | (long)info->tty->ldisc.num); | 5249 | /* FIXME: double check locking */ |
5250 | (long)info->tty->ldisc.ops->num); | ||
5250 | else | 5251 | else |
5251 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu " | 5252 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu " |
5252 | "%10lu %8lu %9lu %6ld\n", | 5253 | "%10lu %8lu %9lu %6ld\n", |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 60a4df7dac12..aa8e19f44b45 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -2262,8 +2262,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, | |||
2262 | tty_wait_until_sent(tty, 0); | 2262 | tty_wait_until_sent(tty, 0); |
2263 | } else { | 2263 | } else { |
2264 | /* ldisc lock already held in ioctl */ | 2264 | /* ldisc lock already held in ioctl */ |
2265 | if (tty->ldisc.flush_buffer) | 2265 | if (tty->ldisc.ops->flush_buffer) |
2266 | tty->ldisc.flush_buffer(tty); | 2266 | tty->ldisc.ops->flush_buffer(tty); |
2267 | } | 2267 | } |
2268 | unlock_kernel(); | 2268 | unlock_kernel(); |
2269 | /* Fall Thru */ | 2269 | /* Fall Thru */ |
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c index 938879cc7bcc..0061e18aff60 100644 --- a/drivers/char/ip2/i2lib.c +++ b/drivers/char/ip2/i2lib.c | |||
@@ -868,11 +868,11 @@ i2Input(i2ChanStrPtr pCh) | |||
868 | amountToMove = count; | 868 | amountToMove = count; |
869 | } | 869 | } |
870 | // Move the first block | 870 | // Move the first block |
871 | pCh->pTTY->ldisc.receive_buf( pCh->pTTY, | 871 | pCh->pTTY->ldisc.ops->receive_buf( pCh->pTTY, |
872 | &(pCh->Ibuf[stripIndex]), NULL, amountToMove ); | 872 | &(pCh->Ibuf[stripIndex]), NULL, amountToMove ); |
873 | // If we needed to wrap, do the second data move | 873 | // If we needed to wrap, do the second data move |
874 | if (count > amountToMove) { | 874 | if (count > amountToMove) { |
875 | pCh->pTTY->ldisc.receive_buf( pCh->pTTY, | 875 | pCh->pTTY->ldisc.ops->receive_buf( pCh->pTTY, |
876 | pCh->Ibuf, NULL, count - amountToMove ); | 876 | pCh->Ibuf, NULL, count - amountToMove ); |
877 | } | 877 | } |
878 | // Bump and wrap the stripIndex all at once by the amount of data read. This | 878 | // Bump and wrap the stripIndex all at once by the amount of data read. This |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 9a2394cda943..5dc74404058f 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -1289,11 +1289,12 @@ static void do_input(struct work_struct *work) | |||
1289 | // code duplicated from n_tty (ldisc) | 1289 | // code duplicated from n_tty (ldisc) |
1290 | static inline void isig(int sig, struct tty_struct *tty, int flush) | 1290 | static inline void isig(int sig, struct tty_struct *tty, int flush) |
1291 | { | 1291 | { |
1292 | /* FIXME: This is completely bogus */ | ||
1292 | if (tty->pgrp) | 1293 | if (tty->pgrp) |
1293 | kill_pgrp(tty->pgrp, sig, 1); | 1294 | kill_pgrp(tty->pgrp, sig, 1); |
1294 | if (flush || !L_NOFLSH(tty)) { | 1295 | if (flush || !L_NOFLSH(tty)) { |
1295 | if ( tty->ldisc.flush_buffer ) | 1296 | if ( tty->ldisc.ops->flush_buffer ) |
1296 | tty->ldisc.flush_buffer(tty); | 1297 | tty->ldisc.ops->flush_buffer(tty); |
1297 | i2InputFlush( tty->driver_data ); | 1298 | i2InputFlush( tty->driver_data ); |
1298 | } | 1299 | } |
1299 | } | 1300 | } |
@@ -1342,7 +1343,7 @@ static void do_status(struct work_struct *work) | |||
1342 | } | 1343 | } |
1343 | tmp = pCh->pTTY->real_raw; | 1344 | tmp = pCh->pTTY->real_raw; |
1344 | pCh->pTTY->real_raw = 0; | 1345 | pCh->pTTY->real_raw = 0; |
1345 | pCh->pTTY->ldisc.receive_buf( pCh->pTTY, &brkc, &brkf, 1 ); | 1346 | pCh->pTTY->ldisc->ops.receive_buf( pCh->pTTY, &brkc, &brkf, 1 ); |
1346 | pCh->pTTY->real_raw = tmp; | 1347 | pCh->pTTY->real_raw = tmp; |
1347 | } | 1348 | } |
1348 | #endif /* NEVER_HAPPENS_AS_SETUP_XXX */ | 1349 | #endif /* NEVER_HAPPENS_AS_SETUP_XXX */ |
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index a35bfd7ee80e..ed4e03333ab4 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c | |||
@@ -199,7 +199,7 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty); | |||
199 | #define tty2n_hdlc(tty) ((struct n_hdlc *) ((tty)->disc_data)) | 199 | #define tty2n_hdlc(tty) ((struct n_hdlc *) ((tty)->disc_data)) |
200 | #define n_hdlc2tty(n_hdlc) ((n_hdlc)->tty) | 200 | #define n_hdlc2tty(n_hdlc) ((n_hdlc)->tty) |
201 | 201 | ||
202 | static struct tty_ldisc n_hdlc_ldisc = { | 202 | static struct tty_ldisc_ops n_hdlc_ldisc = { |
203 | .owner = THIS_MODULE, | 203 | .owner = THIS_MODULE, |
204 | .magic = TTY_LDISC_MAGIC, | 204 | .magic = TTY_LDISC_MAGIC, |
205 | .name = "hdlc", | 205 | .name = "hdlc", |
@@ -342,8 +342,8 @@ static int n_hdlc_tty_open (struct tty_struct *tty) | |||
342 | #endif | 342 | #endif |
343 | 343 | ||
344 | /* Flush any pending characters in the driver and discipline. */ | 344 | /* Flush any pending characters in the driver and discipline. */ |
345 | if (tty->ldisc.flush_buffer) | 345 | if (tty->ldisc.ops->flush_buffer) |
346 | tty->ldisc.flush_buffer(tty); | 346 | tty->ldisc.ops->flush_buffer(tty); |
347 | 347 | ||
348 | tty_driver_flush_buffer(tty); | 348 | tty_driver_flush_buffer(tty); |
349 | 349 | ||
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 902169062332..ae377aa473ba 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -143,7 +143,7 @@ static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, | |||
143 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, | 143 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, |
144 | char *fp, int count); | 144 | char *fp, int count); |
145 | 145 | ||
146 | static struct tty_ldisc tty_ldisc_N_R3964 = { | 146 | static struct tty_ldisc_ops tty_ldisc_N_R3964 = { |
147 | .owner = THIS_MODULE, | 147 | .owner = THIS_MODULE, |
148 | .magic = TTY_LDISC_MAGIC, | 148 | .magic = TTY_LDISC_MAGIC, |
149 | .name = "R3964", | 149 | .name = "R3964", |
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 8096389b0dc2..708c2b1dbe51 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -1573,7 +1573,7 @@ static unsigned int normal_poll(struct tty_struct *tty, struct file *file, | |||
1573 | return mask; | 1573 | return mask; |
1574 | } | 1574 | } |
1575 | 1575 | ||
1576 | struct tty_ldisc tty_ldisc_N_TTY = { | 1576 | struct tty_ldisc_ops tty_ldisc_N_TTY = { |
1577 | .magic = TTY_LDISC_MAGIC, | 1577 | .magic = TTY_LDISC_MAGIC, |
1578 | .name = "n_tty", | 1578 | .name = "n_tty", |
1579 | .open = n_tty_open, | 1579 | .open = n_tty_open, |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 1dd0e992c83d..95743e2682fe 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -514,8 +514,8 @@ static void ldisc_receive_buf(struct tty_struct *tty, | |||
514 | return; | 514 | return; |
515 | ld = tty_ldisc_ref(tty); | 515 | ld = tty_ldisc_ref(tty); |
516 | if (ld) { | 516 | if (ld) { |
517 | if (ld->receive_buf) | 517 | if (ld->ops->receive_buf) |
518 | ld->receive_buf(tty, data, flags, count); | 518 | ld->ops->receive_buf(tty, data, flags, count); |
519 | tty_ldisc_deref(ld); | 519 | tty_ldisc_deref(ld); |
520 | } | 520 | } |
521 | } | 521 | } |
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 0a05c038ae6f..76b27932d229 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -111,7 +111,7 @@ static int pty_write(struct tty_struct * tty, const unsigned char *buf, int coun | |||
111 | c = to->receive_room; | 111 | c = to->receive_room; |
112 | if (c > count) | 112 | if (c > count) |
113 | c = count; | 113 | c = count; |
114 | to->ldisc.receive_buf(to, buf, NULL, c); | 114 | to->ldisc.ops->receive_buf(to, buf, NULL, c); |
115 | 115 | ||
116 | return c; | 116 | return c; |
117 | } | 117 | } |
@@ -149,11 +149,11 @@ static int pty_chars_in_buffer(struct tty_struct *tty) | |||
149 | int count; | 149 | int count; |
150 | 150 | ||
151 | /* We should get the line discipline lock for "tty->link" */ | 151 | /* We should get the line discipline lock for "tty->link" */ |
152 | if (!to || !to->ldisc.chars_in_buffer) | 152 | if (!to || !to->ldisc.ops->chars_in_buffer) |
153 | return 0; | 153 | return 0; |
154 | 154 | ||
155 | /* The ldisc must report 0 if no characters available to be read */ | 155 | /* The ldisc must report 0 if no characters available to be read */ |
156 | count = to->ldisc.chars_in_buffer(to); | 156 | count = to->ldisc.ops->chars_in_buffer(to); |
157 | 157 | ||
158 | if (tty->driver->subtype == PTY_TYPE_SLAVE) return count; | 158 | if (tty->driver->subtype == PTY_TYPE_SLAVE) return count; |
159 | 159 | ||
@@ -186,8 +186,8 @@ static void pty_flush_buffer(struct tty_struct *tty) | |||
186 | if (!to) | 186 | if (!to) |
187 | return; | 187 | return; |
188 | 188 | ||
189 | if (to->ldisc.flush_buffer) | 189 | if (to->ldisc.ops->flush_buffer) |
190 | to->ldisc.flush_buffer(to); | 190 | to->ldisc.ops->flush_buffer(to); |
191 | 191 | ||
192 | if (to->packet) { | 192 | if (to->packet) { |
193 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 193 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
diff --git a/drivers/char/selection.c b/drivers/char/selection.c index d63f5ccc29e6..2978a49a172b 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c | |||
@@ -327,7 +327,8 @@ int paste_selection(struct tty_struct *tty) | |||
327 | } | 327 | } |
328 | count = sel_buffer_lth - pasted; | 328 | count = sel_buffer_lth - pasted; |
329 | count = min(count, tty->receive_room); | 329 | count = min(count, tty->receive_room); |
330 | tty->ldisc.receive_buf(tty, sel_buffer + pasted, NULL, count); | 330 | tty->ldisc.ops->receive_buf(tty, sel_buffer + pasted, |
331 | NULL, count); | ||
331 | pasted += count; | 332 | pasted += count; |
332 | } | 333 | } |
333 | remove_wait_queue(&vc->paste_wait, &wait); | 334 | remove_wait_queue(&vc->paste_wait, &wait); |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index ac5080df2565..5e4b2e638d0c 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -975,8 +975,8 @@ static void ldisc_receive_buf(struct tty_struct *tty, | |||
975 | return; | 975 | return; |
976 | ld = tty_ldisc_ref(tty); | 976 | ld = tty_ldisc_ref(tty); |
977 | if (ld) { | 977 | if (ld) { |
978 | if (ld->receive_buf) | 978 | if (ld->ops->receive_buf) |
979 | ld->receive_buf(tty, data, flags, count); | 979 | ld->ops->receive_buf(tty, data, flags, count); |
980 | tty_ldisc_deref(ld); | 980 | tty_ldisc_deref(ld); |
981 | } | 981 | } |
982 | } | 982 | } |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 55c1653be00c..e473778cd6fa 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -641,8 +641,8 @@ static void ldisc_receive_buf(struct tty_struct *tty, | |||
641 | return; | 641 | return; |
642 | ld = tty_ldisc_ref(tty); | 642 | ld = tty_ldisc_ref(tty); |
643 | if (ld) { | 643 | if (ld) { |
644 | if (ld->receive_buf) | 644 | if (ld->ops->receive_buf) |
645 | ld->receive_buf(tty, data, flags, count); | 645 | ld->ops->receive_buf(tty, data, flags, count); |
646 | tty_ldisc_deref(ld); | 646 | tty_ldisc_deref(ld); |
647 | } | 647 | } |
648 | } | 648 | } |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index bec54866e0bb..5341b5aaf8bc 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -712,8 +712,8 @@ static void ldisc_receive_buf(struct tty_struct *tty, | |||
712 | return; | 712 | return; |
713 | ld = tty_ldisc_ref(tty); | 713 | ld = tty_ldisc_ref(tty); |
714 | if (ld) { | 714 | if (ld) { |
715 | if (ld->receive_buf) | 715 | if (ld->ops->receive_buf) |
716 | ld->receive_buf(tty, data, flags, count); | 716 | ld->ops->receive_buf(tty, data, flags, count); |
717 | tty_ldisc_deref(ld); | 717 | tty_ldisc_deref(ld); |
718 | } | 718 | } |
719 | } | 719 | } |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 047a17339f83..54c4ada460ee 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -95,8 +95,9 @@ | |||
95 | #include <linux/wait.h> | 95 | #include <linux/wait.h> |
96 | #include <linux/bitops.h> | 96 | #include <linux/bitops.h> |
97 | #include <linux/delay.h> | 97 | #include <linux/delay.h> |
98 | #include <linux/seq_file.h> | ||
98 | 99 | ||
99 | #include <asm/uaccess.h> | 100 | #include <linux/uaccess.h> |
100 | #include <asm/system.h> | 101 | #include <asm/system.h> |
101 | 102 | ||
102 | #include <linux/kbd_kern.h> | 103 | #include <linux/kbd_kern.h> |
@@ -682,7 +683,7 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
682 | static DEFINE_SPINLOCK(tty_ldisc_lock); | 683 | static DEFINE_SPINLOCK(tty_ldisc_lock); |
683 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); | 684 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); |
684 | /* Line disc dispatch table */ | 685 | /* Line disc dispatch table */ |
685 | static struct tty_ldisc tty_ldiscs[NR_LDISCS]; | 686 | static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; |
686 | 687 | ||
687 | /** | 688 | /** |
688 | * tty_register_ldisc - install a line discipline | 689 | * tty_register_ldisc - install a line discipline |
@@ -697,7 +698,7 @@ static struct tty_ldisc tty_ldiscs[NR_LDISCS]; | |||
697 | * takes tty_ldisc_lock to guard against ldisc races | 698 | * takes tty_ldisc_lock to guard against ldisc races |
698 | */ | 699 | */ |
699 | 700 | ||
700 | int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) | 701 | int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) |
701 | { | 702 | { |
702 | unsigned long flags; | 703 | unsigned long flags; |
703 | int ret = 0; | 704 | int ret = 0; |
@@ -706,10 +707,9 @@ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) | |||
706 | return -EINVAL; | 707 | return -EINVAL; |
707 | 708 | ||
708 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 709 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
709 | tty_ldiscs[disc] = *new_ldisc; | 710 | tty_ldiscs[disc] = new_ldisc; |
710 | tty_ldiscs[disc].num = disc; | 711 | new_ldisc->num = disc; |
711 | tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED; | 712 | new_ldisc->refcount = 0; |
712 | tty_ldiscs[disc].refcount = 0; | ||
713 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 713 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
714 | 714 | ||
715 | return ret; | 715 | return ret; |
@@ -737,19 +737,56 @@ int tty_unregister_ldisc(int disc) | |||
737 | return -EINVAL; | 737 | return -EINVAL; |
738 | 738 | ||
739 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 739 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
740 | if (tty_ldiscs[disc].refcount) | 740 | if (tty_ldiscs[disc]->refcount) |
741 | ret = -EBUSY; | 741 | ret = -EBUSY; |
742 | else | 742 | else |
743 | tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED; | 743 | tty_ldiscs[disc] = NULL; |
744 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 744 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
745 | 745 | ||
746 | return ret; | 746 | return ret; |
747 | } | 747 | } |
748 | EXPORT_SYMBOL(tty_unregister_ldisc); | 748 | EXPORT_SYMBOL(tty_unregister_ldisc); |
749 | 749 | ||
750 | |||
751 | /** | ||
752 | * tty_ldisc_try_get - try and reference an ldisc | ||
753 | * @disc: ldisc number | ||
754 | * @ld: tty ldisc structure to complete | ||
755 | * | ||
756 | * Attempt to open and lock a line discipline into place. Return | ||
757 | * the line discipline refcounted and assigned in ld. On an error | ||
758 | * report the error code back | ||
759 | */ | ||
760 | |||
761 | static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) | ||
762 | { | ||
763 | unsigned long flags; | ||
764 | struct tty_ldisc_ops *ldops; | ||
765 | int err = -EINVAL; | ||
766 | |||
767 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
768 | ld->ops = NULL; | ||
769 | ldops = tty_ldiscs[disc]; | ||
770 | /* Check the entry is defined */ | ||
771 | if (ldops) { | ||
772 | /* If the module is being unloaded we can't use it */ | ||
773 | if (!try_module_get(ldops->owner)) | ||
774 | err = -EAGAIN; | ||
775 | else { | ||
776 | /* lock it */ | ||
777 | ldops->refcount++; | ||
778 | ld->ops = ldops; | ||
779 | err = 0; | ||
780 | } | ||
781 | } | ||
782 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
783 | return err; | ||
784 | } | ||
785 | |||
750 | /** | 786 | /** |
751 | * tty_ldisc_get - take a reference to an ldisc | 787 | * tty_ldisc_get - take a reference to an ldisc |
752 | * @disc: ldisc number | 788 | * @disc: ldisc number |
789 | * @ld: tty line discipline structure to use | ||
753 | * | 790 | * |
754 | * Takes a reference to a line discipline. Deals with refcounts and | 791 | * Takes a reference to a line discipline. Deals with refcounts and |
755 | * module locking counts. Returns NULL if the discipline is not available. | 792 | * module locking counts. Returns NULL if the discipline is not available. |
@@ -760,32 +797,20 @@ EXPORT_SYMBOL(tty_unregister_ldisc); | |||
760 | * takes tty_ldisc_lock to guard against ldisc races | 797 | * takes tty_ldisc_lock to guard against ldisc races |
761 | */ | 798 | */ |
762 | 799 | ||
763 | struct tty_ldisc *tty_ldisc_get(int disc) | 800 | static int tty_ldisc_get(int disc, struct tty_ldisc *ld) |
764 | { | 801 | { |
765 | unsigned long flags; | 802 | int err; |
766 | struct tty_ldisc *ld; | ||
767 | 803 | ||
768 | if (disc < N_TTY || disc >= NR_LDISCS) | 804 | if (disc < N_TTY || disc >= NR_LDISCS) |
769 | return NULL; | 805 | return -EINVAL; |
770 | 806 | err = tty_ldisc_try_get(disc, ld); | |
771 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 807 | if (err == -EAGAIN) { |
772 | 808 | request_module("tty-ldisc-%d", disc); | |
773 | ld = &tty_ldiscs[disc]; | 809 | err = tty_ldisc_try_get(disc, ld); |
774 | /* Check the entry is defined */ | 810 | } |
775 | if (ld->flags & LDISC_FLAG_DEFINED) { | 811 | return err; |
776 | /* If the module is being unloaded we can't use it */ | ||
777 | if (!try_module_get(ld->owner)) | ||
778 | ld = NULL; | ||
779 | else /* lock it */ | ||
780 | ld->refcount++; | ||
781 | } else | ||
782 | ld = NULL; | ||
783 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
784 | return ld; | ||
785 | } | 812 | } |
786 | 813 | ||
787 | EXPORT_SYMBOL_GPL(tty_ldisc_get); | ||
788 | |||
789 | /** | 814 | /** |
790 | * tty_ldisc_put - drop ldisc reference | 815 | * tty_ldisc_put - drop ldisc reference |
791 | * @disc: ldisc number | 816 | * @disc: ldisc number |
@@ -797,22 +822,67 @@ EXPORT_SYMBOL_GPL(tty_ldisc_get); | |||
797 | * takes tty_ldisc_lock to guard against ldisc races | 822 | * takes tty_ldisc_lock to guard against ldisc races |
798 | */ | 823 | */ |
799 | 824 | ||
800 | void tty_ldisc_put(int disc) | 825 | static void tty_ldisc_put(struct tty_ldisc_ops *ld) |
801 | { | 826 | { |
802 | struct tty_ldisc *ld; | ||
803 | unsigned long flags; | 827 | unsigned long flags; |
828 | int disc = ld->num; | ||
804 | 829 | ||
805 | BUG_ON(disc < N_TTY || disc >= NR_LDISCS); | 830 | BUG_ON(disc < N_TTY || disc >= NR_LDISCS); |
806 | 831 | ||
807 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 832 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
808 | ld = &tty_ldiscs[disc]; | 833 | ld = tty_ldiscs[disc]; |
809 | BUG_ON(ld->refcount == 0); | 834 | BUG_ON(ld->refcount == 0); |
810 | ld->refcount--; | 835 | ld->refcount--; |
811 | module_put(ld->owner); | 836 | module_put(ld->owner); |
812 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 837 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
813 | } | 838 | } |
814 | 839 | ||
815 | EXPORT_SYMBOL_GPL(tty_ldisc_put); | 840 | static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) |
841 | { | ||
842 | return (*pos < NR_LDISCS) ? pos : NULL; | ||
843 | } | ||
844 | |||
845 | static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos) | ||
846 | { | ||
847 | (*pos)++; | ||
848 | return (*pos < NR_LDISCS) ? pos : NULL; | ||
849 | } | ||
850 | |||
851 | static void tty_ldiscs_seq_stop(struct seq_file *m, void *v) | ||
852 | { | ||
853 | } | ||
854 | |||
855 | static int tty_ldiscs_seq_show(struct seq_file *m, void *v) | ||
856 | { | ||
857 | int i = *(loff_t *)v; | ||
858 | struct tty_ldisc ld; | ||
859 | |||
860 | if (tty_ldisc_get(i, &ld) < 0) | ||
861 | return 0; | ||
862 | seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i); | ||
863 | tty_ldisc_put(ld.ops); | ||
864 | return 0; | ||
865 | } | ||
866 | |||
867 | static const struct seq_operations tty_ldiscs_seq_ops = { | ||
868 | .start = tty_ldiscs_seq_start, | ||
869 | .next = tty_ldiscs_seq_next, | ||
870 | .stop = tty_ldiscs_seq_stop, | ||
871 | .show = tty_ldiscs_seq_show, | ||
872 | }; | ||
873 | |||
874 | static int proc_tty_ldiscs_open(struct inode *inode, struct file *file) | ||
875 | { | ||
876 | return seq_open(file, &tty_ldiscs_seq_ops); | ||
877 | } | ||
878 | |||
879 | const struct file_operations tty_ldiscs_proc_fops = { | ||
880 | .owner = THIS_MODULE, | ||
881 | .open = proc_tty_ldiscs_open, | ||
882 | .read = seq_read, | ||
883 | .llseek = seq_lseek, | ||
884 | .release = seq_release, | ||
885 | }; | ||
816 | 886 | ||
817 | /** | 887 | /** |
818 | * tty_ldisc_assign - set ldisc on a tty | 888 | * tty_ldisc_assign - set ldisc on a tty |
@@ -829,8 +899,8 @@ EXPORT_SYMBOL_GPL(tty_ldisc_put); | |||
829 | 899 | ||
830 | static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) | 900 | static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) |
831 | { | 901 | { |
902 | ld->refcount = 0; | ||
832 | tty->ldisc = *ld; | 903 | tty->ldisc = *ld; |
833 | tty->ldisc.refcount = 0; | ||
834 | } | 904 | } |
835 | 905 | ||
836 | /** | 906 | /** |
@@ -954,6 +1024,41 @@ static void tty_ldisc_enable(struct tty_struct *tty) | |||
954 | } | 1024 | } |
955 | 1025 | ||
956 | /** | 1026 | /** |
1027 | * tty_ldisc_restore - helper for tty ldisc change | ||
1028 | * @tty: tty to recover | ||
1029 | * @old: previous ldisc | ||
1030 | * | ||
1031 | * Restore the previous line discipline or N_TTY when a line discipline | ||
1032 | * change fails due to an open error | ||
1033 | */ | ||
1034 | |||
1035 | static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) | ||
1036 | { | ||
1037 | char buf[64]; | ||
1038 | struct tty_ldisc new_ldisc; | ||
1039 | |||
1040 | /* There is an outstanding reference here so this is safe */ | ||
1041 | tty_ldisc_get(old->ops->num, old); | ||
1042 | tty_ldisc_assign(tty, old); | ||
1043 | tty_set_termios_ldisc(tty, old->ops->num); | ||
1044 | if (old->ops->open && (old->ops->open(tty) < 0)) { | ||
1045 | tty_ldisc_put(old->ops); | ||
1046 | /* This driver is always present */ | ||
1047 | if (tty_ldisc_get(N_TTY, &new_ldisc) < 0) | ||
1048 | panic("n_tty: get"); | ||
1049 | tty_ldisc_assign(tty, &new_ldisc); | ||
1050 | tty_set_termios_ldisc(tty, N_TTY); | ||
1051 | if (new_ldisc.ops->open) { | ||
1052 | int r = new_ldisc.ops->open(tty); | ||
1053 | if (r < 0) | ||
1054 | panic("Couldn't open N_TTY ldisc for " | ||
1055 | "%s --- error %d.", | ||
1056 | tty_name(tty, buf), r); | ||
1057 | } | ||
1058 | } | ||
1059 | } | ||
1060 | |||
1061 | /** | ||
957 | * tty_set_ldisc - set line discipline | 1062 | * tty_set_ldisc - set line discipline |
958 | * @tty: the terminal to set | 1063 | * @tty: the terminal to set |
959 | * @ldisc: the line discipline | 1064 | * @ldisc: the line discipline |
@@ -967,28 +1072,18 @@ static void tty_ldisc_enable(struct tty_struct *tty) | |||
967 | 1072 | ||
968 | static int tty_set_ldisc(struct tty_struct *tty, int ldisc) | 1073 | static int tty_set_ldisc(struct tty_struct *tty, int ldisc) |
969 | { | 1074 | { |
970 | int retval = 0; | 1075 | int retval; |
971 | struct tty_ldisc o_ldisc; | 1076 | struct tty_ldisc o_ldisc, new_ldisc; |
972 | char buf[64]; | ||
973 | int work; | 1077 | int work; |
974 | unsigned long flags; | 1078 | unsigned long flags; |
975 | struct tty_ldisc *ld; | ||
976 | struct tty_struct *o_tty; | 1079 | struct tty_struct *o_tty; |
977 | 1080 | ||
978 | if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS)) | ||
979 | return -EINVAL; | ||
980 | |||
981 | restart: | 1081 | restart: |
982 | 1082 | /* This is a bit ugly for now but means we can break the 'ldisc | |
983 | ld = tty_ldisc_get(ldisc); | 1083 | is part of the tty struct' assumption later */ |
984 | /* Eduardo Blanco <ejbs@cs.cs.com.uy> */ | 1084 | retval = tty_ldisc_get(ldisc, &new_ldisc); |
985 | /* Cyrus Durgin <cider@speakeasy.org> */ | 1085 | if (retval) |
986 | if (ld == NULL) { | 1086 | return retval; |
987 | request_module("tty-ldisc-%d", ldisc); | ||
988 | ld = tty_ldisc_get(ldisc); | ||
989 | } | ||
990 | if (ld == NULL) | ||
991 | return -EINVAL; | ||
992 | 1087 | ||
993 | /* | 1088 | /* |
994 | * Problem: What do we do if this blocks ? | 1089 | * Problem: What do we do if this blocks ? |
@@ -996,8 +1091,8 @@ restart: | |||
996 | 1091 | ||
997 | tty_wait_until_sent(tty, 0); | 1092 | tty_wait_until_sent(tty, 0); |
998 | 1093 | ||
999 | if (tty->ldisc.num == ldisc) { | 1094 | if (tty->ldisc.ops->num == ldisc) { |
1000 | tty_ldisc_put(ldisc); | 1095 | tty_ldisc_put(new_ldisc.ops); |
1001 | return 0; | 1096 | return 0; |
1002 | } | 1097 | } |
1003 | 1098 | ||
@@ -1024,7 +1119,7 @@ restart: | |||
1024 | /* Free the new ldisc we grabbed. Must drop the lock | 1119 | /* Free the new ldisc we grabbed. Must drop the lock |
1025 | first. */ | 1120 | first. */ |
1026 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 1121 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
1027 | tty_ldisc_put(ldisc); | 1122 | tty_ldisc_put(o_ldisc.ops); |
1028 | /* | 1123 | /* |
1029 | * There are several reasons we may be busy, including | 1124 | * There are several reasons we may be busy, including |
1030 | * random momentary I/O traffic. We must therefore | 1125 | * random momentary I/O traffic. We must therefore |
@@ -1038,7 +1133,7 @@ restart: | |||
1038 | } | 1133 | } |
1039 | if (o_tty && o_tty->ldisc.refcount) { | 1134 | if (o_tty && o_tty->ldisc.refcount) { |
1040 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 1135 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
1041 | tty_ldisc_put(ldisc); | 1136 | tty_ldisc_put(o_tty->ldisc.ops); |
1042 | if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0) | 1137 | if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0) |
1043 | return -ERESTARTSYS; | 1138 | return -ERESTARTSYS; |
1044 | goto restart; | 1139 | goto restart; |
@@ -1049,8 +1144,9 @@ restart: | |||
1049 | * another ldisc change | 1144 | * another ldisc change |
1050 | */ | 1145 | */ |
1051 | if (!test_bit(TTY_LDISC, &tty->flags)) { | 1146 | if (!test_bit(TTY_LDISC, &tty->flags)) { |
1147 | struct tty_ldisc *ld; | ||
1052 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 1148 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
1053 | tty_ldisc_put(ldisc); | 1149 | tty_ldisc_put(new_ldisc.ops); |
1054 | ld = tty_ldisc_ref_wait(tty); | 1150 | ld = tty_ldisc_ref_wait(tty); |
1055 | tty_ldisc_deref(ld); | 1151 | tty_ldisc_deref(ld); |
1056 | goto restart; | 1152 | goto restart; |
@@ -1060,7 +1156,7 @@ restart: | |||
1060 | if (o_tty) | 1156 | if (o_tty) |
1061 | clear_bit(TTY_LDISC, &o_tty->flags); | 1157 | clear_bit(TTY_LDISC, &o_tty->flags); |
1062 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 1158 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
1063 | 1159 | ||
1064 | /* | 1160 | /* |
1065 | * From this point on we know nobody has an ldisc | 1161 | * From this point on we know nobody has an ldisc |
1066 | * usage reference, nor can they obtain one until | 1162 | * usage reference, nor can they obtain one until |
@@ -1070,45 +1166,30 @@ restart: | |||
1070 | work = cancel_delayed_work(&tty->buf.work); | 1166 | work = cancel_delayed_work(&tty->buf.work); |
1071 | /* | 1167 | /* |
1072 | * Wait for ->hangup_work and ->buf.work handlers to terminate | 1168 | * Wait for ->hangup_work and ->buf.work handlers to terminate |
1169 | * MUST NOT hold locks here. | ||
1073 | */ | 1170 | */ |
1074 | flush_scheduled_work(); | 1171 | flush_scheduled_work(); |
1075 | /* Shutdown the current discipline. */ | 1172 | /* Shutdown the current discipline. */ |
1076 | if (tty->ldisc.close) | 1173 | if (o_ldisc.ops->close) |
1077 | (tty->ldisc.close)(tty); | 1174 | (o_ldisc.ops->close)(tty); |
1078 | 1175 | ||
1079 | /* Now set up the new line discipline. */ | 1176 | /* Now set up the new line discipline. */ |
1080 | tty_ldisc_assign(tty, ld); | 1177 | tty_ldisc_assign(tty, &new_ldisc); |
1081 | tty_set_termios_ldisc(tty, ldisc); | 1178 | tty_set_termios_ldisc(tty, ldisc); |
1082 | if (tty->ldisc.open) | 1179 | if (new_ldisc.ops->open) |
1083 | retval = (tty->ldisc.open)(tty); | 1180 | retval = (new_ldisc.ops->open)(tty); |
1084 | if (retval < 0) { | 1181 | if (retval < 0) { |
1085 | tty_ldisc_put(ldisc); | 1182 | tty_ldisc_put(new_ldisc.ops); |
1086 | /* There is an outstanding reference here so this is safe */ | 1183 | tty_ldisc_restore(tty, &o_ldisc); |
1087 | tty_ldisc_assign(tty, tty_ldisc_get(o_ldisc.num)); | ||
1088 | tty_set_termios_ldisc(tty, tty->ldisc.num); | ||
1089 | if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) { | ||
1090 | tty_ldisc_put(o_ldisc.num); | ||
1091 | /* This driver is always present */ | ||
1092 | tty_ldisc_assign(tty, tty_ldisc_get(N_TTY)); | ||
1093 | tty_set_termios_ldisc(tty, N_TTY); | ||
1094 | if (tty->ldisc.open) { | ||
1095 | int r = tty->ldisc.open(tty); | ||
1096 | |||
1097 | if (r < 0) | ||
1098 | panic("Couldn't open N_TTY ldisc for " | ||
1099 | "%s --- error %d.", | ||
1100 | tty_name(tty, buf), r); | ||
1101 | } | ||
1102 | } | ||
1103 | } | 1184 | } |
1104 | /* At this point we hold a reference to the new ldisc and a | 1185 | /* At this point we hold a reference to the new ldisc and a |
1105 | a reference to the old ldisc. If we ended up flipping back | 1186 | a reference to the old ldisc. If we ended up flipping back |
1106 | to the existing ldisc we have two references to it */ | 1187 | to the existing ldisc we have two references to it */ |
1107 | 1188 | ||
1108 | if (tty->ldisc.num != o_ldisc.num && tty->ops->set_ldisc) | 1189 | if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc) |
1109 | tty->ops->set_ldisc(tty); | 1190 | tty->ops->set_ldisc(tty); |
1110 | 1191 | ||
1111 | tty_ldisc_put(o_ldisc.num); | 1192 | tty_ldisc_put(o_ldisc.ops); |
1112 | 1193 | ||
1113 | /* | 1194 | /* |
1114 | * Allow ldisc referencing to occur as soon as the driver | 1195 | * Allow ldisc referencing to occur as soon as the driver |
@@ -1335,8 +1416,8 @@ void tty_wakeup(struct tty_struct *tty) | |||
1335 | if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) { | 1416 | if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) { |
1336 | ld = tty_ldisc_ref(tty); | 1417 | ld = tty_ldisc_ref(tty); |
1337 | if (ld) { | 1418 | if (ld) { |
1338 | if (ld->write_wakeup) | 1419 | if (ld->ops->write_wakeup) |
1339 | ld->write_wakeup(tty); | 1420 | ld->ops->write_wakeup(tty); |
1340 | tty_ldisc_deref(ld); | 1421 | tty_ldisc_deref(ld); |
1341 | } | 1422 | } |
1342 | } | 1423 | } |
@@ -1357,8 +1438,8 @@ void tty_ldisc_flush(struct tty_struct *tty) | |||
1357 | { | 1438 | { |
1358 | struct tty_ldisc *ld = tty_ldisc_ref(tty); | 1439 | struct tty_ldisc *ld = tty_ldisc_ref(tty); |
1359 | if (ld) { | 1440 | if (ld) { |
1360 | if (ld->flush_buffer) | 1441 | if (ld->ops->flush_buffer) |
1361 | ld->flush_buffer(tty); | 1442 | ld->ops->flush_buffer(tty); |
1362 | tty_ldisc_deref(ld); | 1443 | tty_ldisc_deref(ld); |
1363 | } | 1444 | } |
1364 | tty_buffer_flush(tty); | 1445 | tty_buffer_flush(tty); |
@@ -1386,7 +1467,7 @@ static void tty_reset_termios(struct tty_struct *tty) | |||
1386 | * do_tty_hangup - actual handler for hangup events | 1467 | * do_tty_hangup - actual handler for hangup events |
1387 | * @work: tty device | 1468 | * @work: tty device |
1388 | * | 1469 | * |
1389 | * This can be called by the "eventd" kernel thread. That is process | 1470 | k * This can be called by the "eventd" kernel thread. That is process |
1390 | * synchronous but doesn't hold any locks, so we need to make sure we | 1471 | * synchronous but doesn't hold any locks, so we need to make sure we |
1391 | * have the appropriate locks for what we're doing. | 1472 | * have the appropriate locks for what we're doing. |
1392 | * | 1473 | * |
@@ -1449,14 +1530,14 @@ static void do_tty_hangup(struct work_struct *work) | |||
1449 | ld = tty_ldisc_ref(tty); | 1530 | ld = tty_ldisc_ref(tty); |
1450 | if (ld != NULL) { | 1531 | if (ld != NULL) { |
1451 | /* We may have no line discipline at this point */ | 1532 | /* We may have no line discipline at this point */ |
1452 | if (ld->flush_buffer) | 1533 | if (ld->ops->flush_buffer) |
1453 | ld->flush_buffer(tty); | 1534 | ld->ops->flush_buffer(tty); |
1454 | tty_driver_flush_buffer(tty); | 1535 | tty_driver_flush_buffer(tty); |
1455 | if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && | 1536 | if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && |
1456 | ld->write_wakeup) | 1537 | ld->ops->write_wakeup) |
1457 | ld->write_wakeup(tty); | 1538 | ld->ops->write_wakeup(tty); |
1458 | if (ld->hangup) | 1539 | if (ld->ops->hangup) |
1459 | ld->hangup(tty); | 1540 | ld->ops->hangup(tty); |
1460 | } | 1541 | } |
1461 | /* | 1542 | /* |
1462 | * FIXME: Once we trust the LDISC code better we can wait here for | 1543 | * FIXME: Once we trust the LDISC code better we can wait here for |
@@ -1825,8 +1906,8 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, | |||
1825 | /* We want to wait for the line discipline to sort out in this | 1906 | /* We want to wait for the line discipline to sort out in this |
1826 | situation */ | 1907 | situation */ |
1827 | ld = tty_ldisc_ref_wait(tty); | 1908 | ld = tty_ldisc_ref_wait(tty); |
1828 | if (ld->read) | 1909 | if (ld->ops->read) |
1829 | i = (ld->read)(tty, file, buf, count); | 1910 | i = (ld->ops->read)(tty, file, buf, count); |
1830 | else | 1911 | else |
1831 | i = -EIO; | 1912 | i = -EIO; |
1832 | tty_ldisc_deref(ld); | 1913 | tty_ldisc_deref(ld); |
@@ -1978,10 +2059,10 @@ static ssize_t tty_write(struct file *file, const char __user *buf, | |||
1978 | printk(KERN_ERR "tty driver %s lacks a write_room method.\n", | 2059 | printk(KERN_ERR "tty driver %s lacks a write_room method.\n", |
1979 | tty->driver->name); | 2060 | tty->driver->name); |
1980 | ld = tty_ldisc_ref_wait(tty); | 2061 | ld = tty_ldisc_ref_wait(tty); |
1981 | if (!ld->write) | 2062 | if (!ld->ops->write) |
1982 | ret = -EIO; | 2063 | ret = -EIO; |
1983 | else | 2064 | else |
1984 | ret = do_tty_write(ld->write, tty, file, buf, count); | 2065 | ret = do_tty_write(ld->ops->write, tty, file, buf, count); |
1985 | tty_ldisc_deref(ld); | 2066 | tty_ldisc_deref(ld); |
1986 | return ret; | 2067 | return ret; |
1987 | } | 2068 | } |
@@ -2076,6 +2157,7 @@ static int init_dev(struct tty_driver *driver, int idx, | |||
2076 | struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc; | 2157 | struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc; |
2077 | struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; | 2158 | struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; |
2078 | int retval = 0; | 2159 | int retval = 0; |
2160 | struct tty_ldisc *ld; | ||
2079 | 2161 | ||
2080 | /* check whether we're reopening an existing tty */ | 2162 | /* check whether we're reopening an existing tty */ |
2081 | if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { | 2163 | if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { |
@@ -2224,17 +2306,19 @@ static int init_dev(struct tty_driver *driver, int idx, | |||
2224 | * If we fail here just call release_tty to clean up. No need | 2306 | * If we fail here just call release_tty to clean up. No need |
2225 | * to decrement the use counts, as release_tty doesn't care. | 2307 | * to decrement the use counts, as release_tty doesn't care. |
2226 | */ | 2308 | */ |
2309 | |||
2310 | ld = &tty->ldisc; | ||
2227 | 2311 | ||
2228 | if (tty->ldisc.open) { | 2312 | if (ld->ops->open) { |
2229 | retval = (tty->ldisc.open)(tty); | 2313 | retval = (ld->ops->open)(tty); |
2230 | if (retval) | 2314 | if (retval) |
2231 | goto release_mem_out; | 2315 | goto release_mem_out; |
2232 | } | 2316 | } |
2233 | if (o_tty && o_tty->ldisc.open) { | 2317 | if (o_tty && o_tty->ldisc.ops->open) { |
2234 | retval = (o_tty->ldisc.open)(o_tty); | 2318 | retval = (o_tty->ldisc.ops->open)(o_tty); |
2235 | if (retval) { | 2319 | if (retval) { |
2236 | if (tty->ldisc.close) | 2320 | if (ld->ops->close) |
2237 | (tty->ldisc.close)(tty); | 2321 | (ld->ops->close)(tty); |
2238 | goto release_mem_out; | 2322 | goto release_mem_out; |
2239 | } | 2323 | } |
2240 | tty_ldisc_enable(o_tty); | 2324 | tty_ldisc_enable(o_tty); |
@@ -2378,6 +2462,7 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
2378 | static void release_dev(struct file *filp) | 2462 | static void release_dev(struct file *filp) |
2379 | { | 2463 | { |
2380 | struct tty_struct *tty, *o_tty; | 2464 | struct tty_struct *tty, *o_tty; |
2465 | struct tty_ldisc ld; | ||
2381 | int pty_master, tty_closing, o_tty_closing, do_sleep; | 2466 | int pty_master, tty_closing, o_tty_closing, do_sleep; |
2382 | int devpts; | 2467 | int devpts; |
2383 | int idx; | 2468 | int idx; |
@@ -2611,26 +2696,27 @@ static void release_dev(struct file *filp) | |||
2611 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 2696 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
2612 | /* | 2697 | /* |
2613 | * Shutdown the current line discipline, and reset it to N_TTY. | 2698 | * Shutdown the current line discipline, and reset it to N_TTY. |
2614 | * N.B. why reset ldisc when we're releasing the memory?? | ||
2615 | * | 2699 | * |
2616 | * FIXME: this MUST get fixed for the new reflocking | 2700 | * FIXME: this MUST get fixed for the new reflocking |
2617 | */ | 2701 | */ |
2618 | if (tty->ldisc.close) | 2702 | if (tty->ldisc.ops->close) |
2619 | (tty->ldisc.close)(tty); | 2703 | (tty->ldisc.ops->close)(tty); |
2620 | tty_ldisc_put(tty->ldisc.num); | 2704 | tty_ldisc_put(tty->ldisc.ops); |
2621 | 2705 | ||
2622 | /* | 2706 | /* |
2623 | * Switch the line discipline back | 2707 | * Switch the line discipline back |
2624 | */ | 2708 | */ |
2625 | tty_ldisc_assign(tty, tty_ldisc_get(N_TTY)); | 2709 | WARN_ON(tty_ldisc_get(N_TTY, &ld)); |
2710 | tty_ldisc_assign(tty, &ld); | ||
2626 | tty_set_termios_ldisc(tty, N_TTY); | 2711 | tty_set_termios_ldisc(tty, N_TTY); |
2627 | if (o_tty) { | 2712 | if (o_tty) { |
2628 | /* FIXME: could o_tty be in setldisc here ? */ | 2713 | /* FIXME: could o_tty be in setldisc here ? */ |
2629 | clear_bit(TTY_LDISC, &o_tty->flags); | 2714 | clear_bit(TTY_LDISC, &o_tty->flags); |
2630 | if (o_tty->ldisc.close) | 2715 | if (o_tty->ldisc.ops->close) |
2631 | (o_tty->ldisc.close)(o_tty); | 2716 | (o_tty->ldisc.ops->close)(o_tty); |
2632 | tty_ldisc_put(o_tty->ldisc.num); | 2717 | tty_ldisc_put(o_tty->ldisc.ops); |
2633 | tty_ldisc_assign(o_tty, tty_ldisc_get(N_TTY)); | 2718 | WARN_ON(tty_ldisc_get(N_TTY, &ld)); |
2719 | tty_ldisc_assign(o_tty, &ld); | ||
2634 | tty_set_termios_ldisc(o_tty, N_TTY); | 2720 | tty_set_termios_ldisc(o_tty, N_TTY); |
2635 | } | 2721 | } |
2636 | /* | 2722 | /* |
@@ -2899,8 +2985,8 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) | |||
2899 | return 0; | 2985 | return 0; |
2900 | 2986 | ||
2901 | ld = tty_ldisc_ref_wait(tty); | 2987 | ld = tty_ldisc_ref_wait(tty); |
2902 | if (ld->poll) | 2988 | if (ld->ops->poll) |
2903 | ret = (ld->poll)(tty, filp, wait); | 2989 | ret = (ld->ops->poll)(tty, filp, wait); |
2904 | tty_ldisc_deref(ld); | 2990 | tty_ldisc_deref(ld); |
2905 | return ret; | 2991 | return ret; |
2906 | } | 2992 | } |
@@ -2974,7 +3060,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p) | |||
2974 | if (get_user(ch, p)) | 3060 | if (get_user(ch, p)) |
2975 | return -EFAULT; | 3061 | return -EFAULT; |
2976 | ld = tty_ldisc_ref_wait(tty); | 3062 | ld = tty_ldisc_ref_wait(tty); |
2977 | ld->receive_buf(tty, &ch, &mbz, 1); | 3063 | ld->ops->receive_buf(tty, &ch, &mbz, 1); |
2978 | tty_ldisc_deref(ld); | 3064 | tty_ldisc_deref(ld); |
2979 | return 0; | 3065 | return 0; |
2980 | } | 3066 | } |
@@ -3528,7 +3614,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
3528 | case TIOCGSID: | 3614 | case TIOCGSID: |
3529 | return tiocgsid(tty, real_tty, p); | 3615 | return tiocgsid(tty, real_tty, p); |
3530 | case TIOCGETD: | 3616 | case TIOCGETD: |
3531 | return put_user(tty->ldisc.num, (int __user *)p); | 3617 | return put_user(tty->ldisc.ops->num, (int __user *)p); |
3532 | case TIOCSETD: | 3618 | case TIOCSETD: |
3533 | return tiocsetd(tty, p); | 3619 | return tiocsetd(tty, p); |
3534 | #ifdef CONFIG_VT | 3620 | #ifdef CONFIG_VT |
@@ -3581,8 +3667,8 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
3581 | } | 3667 | } |
3582 | ld = tty_ldisc_ref_wait(tty); | 3668 | ld = tty_ldisc_ref_wait(tty); |
3583 | retval = -EINVAL; | 3669 | retval = -EINVAL; |
3584 | if (ld->ioctl) { | 3670 | if (ld->ops->ioctl) { |
3585 | retval = ld->ioctl(tty, file, cmd, arg); | 3671 | retval = ld->ops->ioctl(tty, file, cmd, arg); |
3586 | if (retval == -ENOIOCTLCMD) | 3672 | if (retval == -ENOIOCTLCMD) |
3587 | retval = -EINVAL; | 3673 | retval = -EINVAL; |
3588 | } | 3674 | } |
@@ -3609,8 +3695,8 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, | |||
3609 | } | 3695 | } |
3610 | 3696 | ||
3611 | ld = tty_ldisc_ref_wait(tty); | 3697 | ld = tty_ldisc_ref_wait(tty); |
3612 | if (ld->compat_ioctl) | 3698 | if (ld->ops->compat_ioctl) |
3613 | retval = ld->compat_ioctl(tty, file, cmd, arg); | 3699 | retval = ld->ops->compat_ioctl(tty, file, cmd, arg); |
3614 | tty_ldisc_deref(ld); | 3700 | tty_ldisc_deref(ld); |
3615 | 3701 | ||
3616 | return retval; | 3702 | return retval; |
@@ -3782,7 +3868,8 @@ static void flush_to_ldisc(struct work_struct *work) | |||
3782 | flag_buf = head->flag_buf_ptr + head->read; | 3868 | flag_buf = head->flag_buf_ptr + head->read; |
3783 | head->read += count; | 3869 | head->read += count; |
3784 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 3870 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
3785 | disc->receive_buf(tty, char_buf, flag_buf, count); | 3871 | disc->ops->receive_buf(tty, char_buf, |
3872 | flag_buf, count); | ||
3786 | spin_lock_irqsave(&tty->buf.lock, flags); | 3873 | spin_lock_irqsave(&tty->buf.lock, flags); |
3787 | } | 3874 | } |
3788 | /* Restore the queue head */ | 3875 | /* Restore the queue head */ |
@@ -3843,9 +3930,12 @@ EXPORT_SYMBOL(tty_flip_buffer_push); | |||
3843 | 3930 | ||
3844 | static void initialize_tty_struct(struct tty_struct *tty) | 3931 | static void initialize_tty_struct(struct tty_struct *tty) |
3845 | { | 3932 | { |
3933 | struct tty_ldisc ld; | ||
3846 | memset(tty, 0, sizeof(struct tty_struct)); | 3934 | memset(tty, 0, sizeof(struct tty_struct)); |
3847 | tty->magic = TTY_MAGIC; | 3935 | tty->magic = TTY_MAGIC; |
3848 | tty_ldisc_assign(tty, tty_ldisc_get(N_TTY)); | 3936 | if (tty_ldisc_get(N_TTY, &ld) < 0) |
3937 | panic("n_tty: init_tty"); | ||
3938 | tty_ldisc_assign(tty, &ld); | ||
3849 | tty->session = NULL; | 3939 | tty->session = NULL; |
3850 | tty->pgrp = NULL; | 3940 | tty->pgrp = NULL; |
3851 | tty->overrun_time = jiffies; | 3941 | tty->overrun_time = jiffies; |
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 8f81139d6194..ea9fc5d03b99 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -491,8 +491,8 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) | |||
491 | 491 | ||
492 | ld = tty_ldisc_ref(tty); | 492 | ld = tty_ldisc_ref(tty); |
493 | if (ld != NULL) { | 493 | if (ld != NULL) { |
494 | if (ld->set_termios) | 494 | if (ld->ops->set_termios) |
495 | (ld->set_termios)(tty, &old_termios); | 495 | (ld->ops->set_termios)(tty, &old_termios); |
496 | tty_ldisc_deref(ld); | 496 | tty_ldisc_deref(ld); |
497 | } | 497 | } |
498 | mutex_unlock(&tty->termios_mutex); | 498 | mutex_unlock(&tty->termios_mutex); |
@@ -552,8 +552,8 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) | |||
552 | ld = tty_ldisc_ref(tty); | 552 | ld = tty_ldisc_ref(tty); |
553 | 553 | ||
554 | if (ld != NULL) { | 554 | if (ld != NULL) { |
555 | if ((opt & TERMIOS_FLUSH) && ld->flush_buffer) | 555 | if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer) |
556 | ld->flush_buffer(tty); | 556 | ld->ops->flush_buffer(tty); |
557 | tty_ldisc_deref(ld); | 557 | tty_ldisc_deref(ld); |
558 | } | 558 | } |
559 | 559 | ||
@@ -959,12 +959,12 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg) | |||
959 | ld = tty_ldisc_ref(tty); | 959 | ld = tty_ldisc_ref(tty); |
960 | switch (arg) { | 960 | switch (arg) { |
961 | case TCIFLUSH: | 961 | case TCIFLUSH: |
962 | if (ld && ld->flush_buffer) | 962 | if (ld && ld->ops->flush_buffer) |
963 | ld->flush_buffer(tty); | 963 | ld->ops->flush_buffer(tty); |
964 | break; | 964 | break; |
965 | case TCIOFLUSH: | 965 | case TCIOFLUSH: |
966 | if (ld && ld->flush_buffer) | 966 | if (ld && ld->ops->flush_buffer) |
967 | ld->flush_buffer(tty); | 967 | ld->ops->flush_buffer(tty); |
968 | /* fall through */ | 968 | /* fall through */ |
969 | case TCOFLUSH: | 969 | case TCOFLUSH: |
970 | tty_driver_flush_buffer(tty); | 970 | tty_driver_flush_buffer(tty); |