aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2008-07-16 16:53:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-20 20:12:34 -0400
commita352def21a642133758b868c71bee12ab34ad5c5 (patch)
tree95d0f7229f9e4afccdc6fbbf11f7f5c6dd83b0fd
parente1e5770bb63fb9d71619a68f52cb0ba4b2ae58a6 (diff)
tty: Ldisc revamp
Move the line disciplines towards a conventional ->ops arrangement. For the moment the actual 'tty_ldisc' struct in the tty is kept as part of the tty struct but this can then be changed if it turns out that when it all settles down we want to refcount ldiscs separately to the tty. Pull the ldisc code out of /proc and put it with our ldisc code. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/bluetooth/hci_ldisc.c6
-rw-r--r--drivers/char/cyclades.c3
-rw-r--r--drivers/char/epca.c4
-rw-r--r--drivers/char/ip2/i2lib.c4
-rw-r--r--drivers/char/ip2/ip2main.c7
-rw-r--r--drivers/char/n_hdlc.c6
-rw-r--r--drivers/char/n_r3964.c2
-rw-r--r--drivers/char/n_tty.c2
-rw-r--r--drivers/char/pcmcia/synclink_cs.c4
-rw-r--r--drivers/char/pty.c10
-rw-r--r--drivers/char/selection.c3
-rw-r--r--drivers/char/synclink.c4
-rw-r--r--drivers/char/synclink_gt.c4
-rw-r--r--drivers/char/synclinkmp.c4
-rw-r--r--drivers/char/tty_io.c336
-rw-r--r--drivers/char/tty_ioctl.c16
-rw-r--r--drivers/input/serio/serport.c2
-rw-r--r--drivers/isdn/capi/capi.c4
-rw-r--r--drivers/isdn/gigaset/ser-gigaset.c2
-rw-r--r--drivers/net/hamradio/6pack.c2
-rw-r--r--drivers/net/hamradio/mkiss.c2
-rw-r--r--drivers/net/irda/irtty-sir.c2
-rw-r--r--drivers/net/ppp_async.c2
-rw-r--r--drivers/net/ppp_synctty.c2
-rw-r--r--drivers/net/slip.c2
-rw-r--r--drivers/net/wan/pc300_tty.c4
-rw-r--r--drivers/net/wan/x25_asy.c2
-rw-r--r--fs/proc/proc_tty.c48
-rw-r--r--include/linux/tty.h9
-rw-r--r--include/linux/tty_ldisc.h7
-rw-r--r--net/bluetooth/rfcomm/tty.c13
-rw-r--r--net/irda/ircomm/ircomm_tty.c14
32 files changed, 286 insertions, 246 deletions
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index e5cd856a2fea..69df187d74ce 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -282,8 +282,8 @@ static int hci_uart_tty_open(struct tty_struct *tty)
282 /* FIXME: why is this needed. Note don't use ldisc_ref here as the 282 /* FIXME: why is this needed. Note don't use ldisc_ref here as the
283 open path is before the ldisc is referencable */ 283 open path is before the ldisc is referencable */
284 284
285 if (tty->ldisc.flush_buffer) 285 if (tty->ldisc.ops->flush_buffer)
286 tty->ldisc.flush_buffer(tty); 286 tty->ldisc.ops->flush_buffer(tty);
287 tty_driver_flush_buffer(tty); 287 tty_driver_flush_buffer(tty);
288 288
289 return 0; 289 return 0;
@@ -514,7 +514,7 @@ static unsigned int hci_uart_tty_poll(struct tty_struct *tty,
514 514
515static int __init hci_uart_init(void) 515static int __init hci_uart_init(void)
516{ 516{
517 static struct tty_ldisc hci_uart_ldisc; 517 static struct tty_ldisc_ops hci_uart_ldisc;
518 int err; 518 int err;
519 519
520 BT_INFO("HCI UART driver ver %s", VERSION); 520 BT_INFO("HCI UART driver ver %s", VERSION);
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)
1290static inline void isig(int sig, struct tty_struct *tty, int flush) 1290static 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
202static struct tty_ldisc n_hdlc_ldisc = { 202static 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,
143static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, 143static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
144 char *fp, int count); 144 char *fp, int count);
145 145
146static struct tty_ldisc tty_ldisc_N_R3964 = { 146static 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
1576struct tty_ldisc tty_ldisc_N_TTY = { 1576struct 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)
682static DEFINE_SPINLOCK(tty_ldisc_lock); 683static DEFINE_SPINLOCK(tty_ldisc_lock);
683static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); 684static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
684/* Line disc dispatch table */ 685/* Line disc dispatch table */
685static struct tty_ldisc tty_ldiscs[NR_LDISCS]; 686static 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
700int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) 701int 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}
748EXPORT_SYMBOL(tty_unregister_ldisc); 748EXPORT_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
761static 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
763struct tty_ldisc *tty_ldisc_get(int disc) 800static 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
787EXPORT_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
800void tty_ldisc_put(int disc) 825static 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
815EXPORT_SYMBOL_GPL(tty_ldisc_put); 840static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
841{
842 return (*pos < NR_LDISCS) ? pos : NULL;
843}
844
845static 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
851static void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
852{
853}
854
855static 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
867static 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
874static int proc_tty_ldiscs_open(struct inode *inode, struct file *file)
875{
876 return seq_open(file, &tty_ldiscs_seq_ops);
877}
878
879const 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
830static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) 900static 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
1035static 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
968static int tty_set_ldisc(struct tty_struct *tty, int ldisc) 1073static 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
981restart: 1081restart:
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 1470k * 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)
2378static void release_dev(struct file *filp) 2462static 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
3844static void initialize_tty_struct(struct tty_struct *tty) 3931static 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);
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 7ff71ba7b7c9..b9694b6445d0 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -216,7 +216,7 @@ static void serport_ldisc_write_wakeup(struct tty_struct * tty)
216 * The line discipline structure. 216 * The line discipline structure.
217 */ 217 */
218 218
219static struct tty_ldisc serport_ldisc = { 219static struct tty_ldisc_ops serport_ldisc = {
220 .owner = THIS_MODULE, 220 .owner = THIS_MODULE,
221 .name = "input", 221 .name = "input",
222 .open = serport_ldisc_open, 222 .open = serport_ldisc_open,
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 2095153582f1..8a35029caca0 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -466,7 +466,7 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
466 ld = tty_ldisc_ref(mp->tty); 466 ld = tty_ldisc_ref(mp->tty);
467 if (ld == NULL) 467 if (ld == NULL)
468 return -1; 468 return -1;
469 if (ld->receive_buf == NULL) { 469 if (ld->ops->receive_buf == NULL) {
470#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) 470#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
471 printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n"); 471 printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n");
472#endif 472#endif
@@ -501,7 +501,7 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
501 printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", 501 printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n",
502 datahandle, skb->len); 502 datahandle, skb->len);
503#endif 503#endif
504 ld->receive_buf(mp->tty, skb->data, NULL, skb->len); 504 ld->ops->receive_buf(mp->tty, skb->data, NULL, skb->len);
505 kfree_skb(skb); 505 kfree_skb(skb);
506 tty_ldisc_deref(ld); 506 tty_ldisc_deref(ld);
507 return 0; 507 return 0;
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index 45d1ee93cd39..5e89fa177816 100644
--- a/drivers/isdn/gigaset/ser-gigaset.c
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -766,7 +766,7 @@ gigaset_tty_wakeup(struct tty_struct *tty)
766 cs_put(cs); 766 cs_put(cs);
767} 767}
768 768
769static struct tty_ldisc gigaset_ldisc = { 769static struct tty_ldisc_ops gigaset_ldisc = {
770 .owner = THIS_MODULE, 770 .owner = THIS_MODULE,
771 .magic = TTY_LDISC_MAGIC, 771 .magic = TTY_LDISC_MAGIC,
772 .name = "ser_gigaset", 772 .name = "ser_gigaset",
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 9d5721287d6f..19dd0a61749c 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -783,7 +783,7 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
783 return err; 783 return err;
784} 784}
785 785
786static struct tty_ldisc sp_ldisc = { 786static struct tty_ldisc_ops sp_ldisc = {
787 .owner = THIS_MODULE, 787 .owner = THIS_MODULE,
788 .magic = TTY_LDISC_MAGIC, 788 .magic = TTY_LDISC_MAGIC,
789 .name = "6pack", 789 .name = "6pack",
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 65166035aca0..c6ca47599fd4 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -969,7 +969,7 @@ out:
969 mkiss_put(ax); 969 mkiss_put(ax);
970} 970}
971 971
972static struct tty_ldisc ax_ldisc = { 972static struct tty_ldisc_ops ax_ldisc = {
973 .owner = THIS_MODULE, 973 .owner = THIS_MODULE,
974 .magic = TTY_LDISC_MAGIC, 974 .magic = TTY_LDISC_MAGIC,
975 .name = "mkiss", 975 .name = "mkiss",
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index e6f40b7f9041..9e33196f9459 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -533,7 +533,7 @@ static void irtty_close(struct tty_struct *tty)
533 533
534/* ------------------------------------------------------- */ 534/* ------------------------------------------------------- */
535 535
536static struct tty_ldisc irda_ldisc = { 536static struct tty_ldisc_ops irda_ldisc = {
537 .magic = TTY_LDISC_MAGIC, 537 .magic = TTY_LDISC_MAGIC,
538 .name = "irda", 538 .name = "irda",
539 .flags = 0, 539 .flags = 0,
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index f1a52def1241..451bdb57d6fc 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -378,7 +378,7 @@ ppp_asynctty_wakeup(struct tty_struct *tty)
378} 378}
379 379
380 380
381static struct tty_ldisc ppp_ldisc = { 381static struct tty_ldisc_ops ppp_ldisc = {
382 .owner = THIS_MODULE, 382 .owner = THIS_MODULE,
383 .magic = TTY_LDISC_MAGIC, 383 .magic = TTY_LDISC_MAGIC,
384 .name = "ppp", 384 .name = "ppp",
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index b8f0369a71e7..801d8f99d471 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -418,7 +418,7 @@ ppp_sync_wakeup(struct tty_struct *tty)
418} 418}
419 419
420 420
421static struct tty_ldisc ppp_sync_ldisc = { 421static struct tty_ldisc_ops ppp_sync_ldisc = {
422 .owner = THIS_MODULE, 422 .owner = THIS_MODULE,
423 .magic = TTY_LDISC_MAGIC, 423 .magic = TTY_LDISC_MAGIC,
424 .name = "pppsync", 424 .name = "pppsync",
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 84af68fdb6c2..1d58991d395b 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -1301,7 +1301,7 @@ static int sl_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1301#endif 1301#endif
1302/* VSV changes end */ 1302/* VSV changes end */
1303 1303
1304static struct tty_ldisc sl_ldisc = { 1304static struct tty_ldisc_ops sl_ldisc = {
1305 .owner = THIS_MODULE, 1305 .owner = THIS_MODULE,
1306 .magic = TTY_LDISC_MAGIC, 1306 .magic = TTY_LDISC_MAGIC,
1307 .name = "slip", 1307 .name = "slip",
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index e03eef2f2282..c2c10c632260 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -688,9 +688,9 @@ static void cpc_tty_rx_work(struct work_struct *work)
688 if (cpc_tty->tty) { 688 if (cpc_tty->tty) {
689 ld = tty_ldisc_ref(cpc_tty->tty); 689 ld = tty_ldisc_ref(cpc_tty->tty);
690 if (ld) { 690 if (ld) {
691 if (ld->receive_buf) { 691 if (ld->ops->receive_buf) {
692 CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name); 692 CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name);
693 ld->receive_buf(cpc_tty->tty, (char *)(buf->data), &flags, buf->size); 693 ld->ops->receive_buf(cpc_tty->tty, (char *)(buf->data), &flags, buf->size);
694 } 694 }
695 tty_ldisc_deref(ld); 695 tty_ldisc_deref(ld);
696 } 696 }
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 069f8bb0a99f..2a6c7a60756f 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -754,7 +754,7 @@ static void x25_asy_setup(struct net_device *dev)
754 dev->flags = IFF_NOARP; 754 dev->flags = IFF_NOARP;
755} 755}
756 756
757static struct tty_ldisc x25_ldisc = { 757static struct tty_ldisc_ops x25_ldisc = {
758 .owner = THIS_MODULE, 758 .owner = THIS_MODULE,
759 .magic = TTY_LDISC_MAGIC, 759 .magic = TTY_LDISC_MAGIC,
760 .name = "X.25", 760 .name = "X.25",
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index 21f490f5d65c..d153946d6d15 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -136,54 +136,6 @@ static const struct file_operations proc_tty_drivers_operations = {
136 .release = seq_release, 136 .release = seq_release,
137}; 137};
138 138
139static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
140{
141 return (*pos < NR_LDISCS) ? pos : NULL;
142}
143
144static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
145{
146 (*pos)++;
147 return (*pos < NR_LDISCS) ? pos : NULL;
148}
149
150static void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
151{
152}
153
154static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
155{
156 int i = *(loff_t *)v;
157 struct tty_ldisc *ld;
158
159 ld = tty_ldisc_get(i);
160 if (ld == NULL)
161 return 0;
162 seq_printf(m, "%-10s %2d\n", ld->name ? ld->name : "???", i);
163 tty_ldisc_put(i);
164 return 0;
165}
166
167static const struct seq_operations tty_ldiscs_seq_ops = {
168 .start = tty_ldiscs_seq_start,
169 .next = tty_ldiscs_seq_next,
170 .stop = tty_ldiscs_seq_stop,
171 .show = tty_ldiscs_seq_show,
172};
173
174static int proc_tty_ldiscs_open(struct inode *inode, struct file *file)
175{
176 return seq_open(file, &tty_ldiscs_seq_ops);
177}
178
179static const struct file_operations tty_ldiscs_proc_fops = {
180 .owner = THIS_MODULE,
181 .open = proc_tty_ldiscs_open,
182 .read = seq_read,
183 .llseek = seq_lseek,
184 .release = seq_release,
185};
186
187/* 139/*
188 * This function is called by tty_register_driver() to handle 140 * This function is called by tty_register_driver() to handle
189 * registering the driver's /proc handler into /proc/tty/driver/<foo> 141 * registering the driver's /proc handler into /proc/tty/driver/<foo>
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 324a3b231d40..013711ea7385 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -185,6 +185,7 @@ struct tty_struct {
185 struct tty_driver *driver; 185 struct tty_driver *driver;
186 const struct tty_operations *ops; 186 const struct tty_operations *ops;
187 int index; 187 int index;
188 /* The ldisc objects are protected by tty_ldisc_lock at the moment */
188 struct tty_ldisc ldisc; 189 struct tty_ldisc ldisc;
189 struct mutex termios_mutex; 190 struct mutex termios_mutex;
190 spinlock_t ctrl_lock; 191 spinlock_t ctrl_lock;
@@ -289,7 +290,7 @@ extern void tty_wait_until_sent(struct tty_struct * tty, long timeout);
289extern int tty_check_change(struct tty_struct * tty); 290extern int tty_check_change(struct tty_struct * tty);
290extern void stop_tty(struct tty_struct * tty); 291extern void stop_tty(struct tty_struct * tty);
291extern void start_tty(struct tty_struct * tty); 292extern void start_tty(struct tty_struct * tty);
292extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc); 293extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
293extern int tty_unregister_ldisc(int disc); 294extern int tty_unregister_ldisc(int disc);
294extern int tty_register_driver(struct tty_driver *driver); 295extern int tty_register_driver(struct tty_driver *driver);
295extern int tty_unregister_driver(struct tty_driver *driver); 296extern int tty_unregister_driver(struct tty_driver *driver);
@@ -330,9 +331,7 @@ extern int tty_termios_hw_change(struct ktermios *a, struct ktermios *b);
330extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *); 331extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
331extern void tty_ldisc_deref(struct tty_ldisc *); 332extern void tty_ldisc_deref(struct tty_ldisc *);
332extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *); 333extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
333 334extern const struct file_operations tty_ldiscs_proc_fops;
334extern struct tty_ldisc *tty_ldisc_get(int);
335extern void tty_ldisc_put(int);
336 335
337extern void tty_wakeup(struct tty_struct *tty); 336extern void tty_wakeup(struct tty_struct *tty);
338extern void tty_ldisc_flush(struct tty_struct *tty); 337extern void tty_ldisc_flush(struct tty_struct *tty);
@@ -354,7 +353,7 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay);
354 353
355 354
356/* n_tty.c */ 355/* n_tty.c */
357extern struct tty_ldisc tty_ldisc_N_TTY; 356extern struct tty_ldisc_ops tty_ldisc_N_TTY;
358 357
359/* tty_audit.c */ 358/* tty_audit.c */
360#ifdef CONFIG_AUDIT 359#ifdef CONFIG_AUDIT
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index 6226504d9108..40f38d896777 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -104,7 +104,7 @@
104#include <linux/fs.h> 104#include <linux/fs.h>
105#include <linux/wait.h> 105#include <linux/wait.h>
106 106
107struct tty_ldisc { 107struct tty_ldisc_ops {
108 int magic; 108 int magic;
109 char *name; 109 char *name;
110 int num; 110 int num;
@@ -142,6 +142,11 @@ struct tty_ldisc {
142 int refcount; 142 int refcount;
143}; 143};
144 144
145struct tty_ldisc {
146 struct tty_ldisc_ops *ops;
147 int refcount;
148};
149
145#define TTY_LDISC_MAGIC 0x5403 150#define TTY_LDISC_MAGIC 0x5403
146 151
147#define LDISC_FLAG_DEFINED 0x00000001 152#define LDISC_FLAG_DEFINED 0x00000001
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index c9191871c1e0..0a387f2eb7a9 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -617,14 +617,7 @@ static void rfcomm_tty_wakeup(unsigned long arg)
617 return; 617 return;
618 618
619 BT_DBG("dev %p tty %p", dev, tty); 619 BT_DBG("dev %p tty %p", dev, tty);
620 620 tty_wakeup(tty);
621 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && tty->ldisc.write_wakeup)
622 (tty->ldisc.write_wakeup)(tty);
623
624 wake_up_interruptible(&tty->write_wait);
625#ifdef SERIAL_HAVE_POLL_WAIT
626 wake_up_interruptible(&tty->poll_wait);
627#endif
628} 621}
629 622
630static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) 623static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
@@ -1005,9 +998,7 @@ static void rfcomm_tty_flush_buffer(struct tty_struct *tty)
1005 return; 998 return;
1006 999
1007 skb_queue_purge(&dev->dlc->tx_queue); 1000 skb_queue_purge(&dev->dlc->tx_queue);
1008 1001 tty_wakeup(tty);
1009 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && tty->ldisc.write_wakeup)
1010 tty->ldisc.write_wakeup(tty);
1011} 1002}
1012 1003
1013static void rfcomm_tty_send_xchar(struct tty_struct *tty, char ch) 1004static void rfcomm_tty_send_xchar(struct tty_struct *tty, char ch)
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 76c3057d0179..e4e2caeb9d82 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -650,12 +650,7 @@ static void ircomm_tty_do_softint(struct work_struct *work)
650 } 650 }
651 651
652 /* Check if user (still) wants to be waken up */ 652 /* Check if user (still) wants to be waken up */
653 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && 653 tty_wakeup(tty);
654 tty->ldisc.write_wakeup)
655 {
656 (tty->ldisc.write_wakeup)(tty);
657 }
658 wake_up_interruptible(&tty->write_wait);
659} 654}
660 655
661/* 656/*
@@ -1141,6 +1136,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
1141 struct sk_buff *skb) 1136 struct sk_buff *skb)
1142{ 1137{
1143 struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; 1138 struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
1139 struct tty_ldisc *ld;
1144 1140
1145 IRDA_DEBUG(2, "%s()\n", __func__ ); 1141 IRDA_DEBUG(2, "%s()\n", __func__ );
1146 1142
@@ -1173,7 +1169,11 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
1173 * involve the flip buffers, since we are not running in an interrupt 1169 * involve the flip buffers, since we are not running in an interrupt
1174 * handler 1170 * handler
1175 */ 1171 */
1176 self->tty->ldisc.receive_buf(self->tty, skb->data, NULL, skb->len); 1172
1173 ld = tty_ldisc_ref(self->tty);
1174 if (ld)
1175 ld->ops->receive_buf(self->tty, skb->data, NULL, skb->len);
1176 tty_ldisc_deref(ld);
1177 1177
1178 /* No need to kfree_skb - see ircomm_ttp_data_indication() */ 1178 /* No need to kfree_skb - see ircomm_ttp_data_indication() */
1179 1179