]> git.pld-linux.org Git - packages/kernel.git/blob - patch-2.2.27-pre2-CAN-2004-0814.patch
- obsolete
[packages/kernel.git] / patch-2.2.27-pre2-CAN-2004-0814.patch
1 diff -urN linux-2.2.26.orig/drivers/char/cyclades.c linux-2.2.26/drivers/char/cyclades.c
2 --- linux-2.2.26.orig/drivers/char/cyclades.c   2001-11-02 17:39:06.000000000 +0100
3 +++ linux-2.2.26/drivers/char/cyclades.c        2004-10-25 00:41:47.000000000 +0200
4 @@ -1019,10 +1019,7 @@
5         wake_up_interruptible(&info->delta_msr_wait);
6      }
7      if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
8 -        if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP))
9 -        && tty->ldisc.write_wakeup){
10 -            (tty->ldisc.write_wakeup)(tty);
11 -        }
12 +       tty_wakeup(tty);
13          wake_up_interruptible(&tty->write_wait);
14         wake_up_interruptible(&tty->poll_wait);
15      }
16 @@ -2821,6 +2818,7 @@
17  cy_close(struct tty_struct *tty, struct file *filp)
18  {
19    struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
20 +  struct tty_ldisc *ld;
21    unsigned long flags;
22  
23  #ifdef CY_DEBUG_OTHER
24 @@ -2938,8 +2936,12 @@
25      shutdown(info);
26      if (tty->driver.flush_buffer)
27          tty->driver.flush_buffer(tty);
28 -    if (tty->ldisc.flush_buffer)
29 -        tty->ldisc.flush_buffer(tty);
30 +    ld = tty_ldisc_ref(tty);
31 +    if (ld) {
32 +           if (ld->flush_buffer)
33 +           ld->flush_buffer(tty);
34 +           tty_ldisc_deref(ld);
35 +    }
36      CY_LOCK(info, flags);
37  
38      tty->closing = 0;
39 @@ -4701,11 +4703,9 @@
40         }
41         CY_UNLOCK(info, flags);
42      }
43 +    tty_wakeup(tty);
44      wake_up_interruptible(&tty->write_wait);
45      wake_up_interruptible(&tty->poll_wait);
46 -    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
47 -       && tty->ldisc.write_wakeup)
48 -           (tty->ldisc.write_wakeup)(tty);
49  } /* cy_flush_buffer */
50  
51  
52 diff -urN linux-2.2.26.orig/drivers/char/dz.c linux-2.2.26/drivers/char/dz.c
53 --- linux-2.2.26.orig/drivers/char/dz.c 2001-03-25 18:31:27.000000000 +0200
54 +++ linux-2.2.26/drivers/char/dz.c      2004-10-31 09:32:57.000000000 +0100
55 @@ -1084,10 +1084,10 @@
56    info->event = 0;
57    info->tty = 0;
58  
59 -  if (tty->ldisc.num != ldiscs[N_TTY].num) {
60 +  if (tty->ldisc.num != N_TTY) {
61      if (tty->ldisc.close)
62        (tty->ldisc.close)(tty);
63 -    tty->ldisc = ldiscs[N_TTY];
64 +    tty->ldisc = *(tty_ldisc_get(N_TTY));
65      tty->termios->c_line = N_TTY;
66      if (tty->ldisc.open)
67        (tty->ldisc.open)(tty);
68 diff -urN linux-2.2.26.orig/drivers/char/epca.c linux-2.2.26/drivers/char/epca.c
69 --- linux-2.2.26.orig/drivers/char/epca.c       2001-11-02 17:39:06.000000000 +0100
70 +++ linux-2.2.26/drivers/char/epca.c    2004-10-25 00:50:02.000000000 +0200
71 @@ -572,7 +572,8 @@
72  
73         if ((ch = verifyChannel(tty)) != NULL) 
74         { /* Begin if ch != NULL */
75 -
76 +               struct tty_ldisc *ld;   
77 +       
78                 save_flags(flags);
79                 cli();
80  
81 @@ -633,8 +634,12 @@
82                 if (tty->driver.flush_buffer)
83                         tty->driver.flush_buffer(tty);
84  
85 -               if (tty->ldisc.flush_buffer)
86 -                       tty->ldisc.flush_buffer(tty);
87 +               ld = tty_ldisc_ref(tty);
88 +                       if (ld != NULL) {
89 +                               if(ld->flush_buffer)
90 +                                   ld->flush_buffer(tty);
91 +                       tty_ldisc_deref(ld);
92 +                       }
93  
94                 shutdown(ch);
95                 tty->closing = 0;
96 @@ -737,12 +742,20 @@
97         { /* Begin if ch != NULL */
98  
99                 unsigned long flags;
100 -
101 +               struct tty_ldisc *ld;
102 +               
103                 save_flags(flags);
104                 cli();
105                 if (tty->driver.flush_buffer)
106                         tty->driver.flush_buffer(tty);
107  
108 +               ld = tty_ldisc_ref(tty);
109 +               if (ld != NULL) {
110 +                       if (ld->flush_buffer)
111 +                               ld->flush_buffer(tty);
112 +                       tty_ldisc_deref(ld);
113 +               }
114 +               
115                 if (tty->ldisc.flush_buffer)
116                         tty->ldisc.flush_buffer(tty);
117  
118 @@ -1227,9 +1240,8 @@
119  
120         wake_up_interruptible(&tty->write_wait);
121         wake_up_interruptible(&tty->poll_wait);
122 -       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
123 -               (tty->ldisc.write_wakeup)(tty);
124 -
125 +       tty_wakeup(tty);
126 +       
127  } /* End pc_flush_buffer */
128  
129  /* ------------------ Begin pc_flush_chars  ---------------------- */
130 @@ -2443,9 +2455,7 @@
131                                 { /* Begin if LOWWAIT */
132  
133                                         ch->statusflags &= ~LOWWAIT;
134 -                                       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
135 -                                                 tty->ldisc.write_wakeup)
136 -                                               (tty->ldisc.write_wakeup)(tty);
137 +                                       tty_wakeup(tty);
138                                         wake_up_interruptible(&tty->write_wait);
139                                         wake_up_interruptible(&tty->poll_wait);
140                                 } /* End if LOWWAIT */
141 @@ -2462,9 +2472,7 @@
142                                 { /* Begin if EMPTYWAIT */
143  
144                                         ch->statusflags &= ~EMPTYWAIT;
145 -                                       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
146 -                                                 tty->ldisc.write_wakeup)
147 -                                               (tty->ldisc.write_wakeup)(tty);
148 +                                       tty_wakeup(tty);
149  
150                                         wake_up_interruptible(&tty->write_wait);
151                                         wake_up_interruptible(&tty->poll_wait);
152 @@ -3327,6 +3335,7 @@
153                                 tty_wait_until_sent(tty, 0);
154                         }
155                         else 
156 +                       /* ldisc lock already held in ioctl */
157                         {
158                                 if (tty->ldisc.flush_buffer)
159                                         tty->ldisc.flush_buffer(tty);
160 diff -urN linux-2.2.26.orig/drivers/char/generic_serial.c linux-2.2.26/drivers/char/generic_serial.c
161 --- linux-2.2.26.orig/drivers/char/generic_serial.c     2001-03-25 18:31:27.000000000 +0200
162 +++ linux-2.2.26/drivers/char/generic_serial.c  2004-10-31 08:46:56.000000000 +0100
163 @@ -453,9 +453,7 @@
164         restore_flags(flags);
165  
166         wake_up_interruptible(&tty->write_wait);
167 -       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
168 -           tty->ldisc.write_wakeup)
169 -               (tty->ldisc.write_wakeup)(tty);
170 +       tty_wakeup(tty);
171         func_exit ();
172  }
173  
174 @@ -595,9 +593,7 @@
175         if (!tty) return;
176  
177         if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
178 -               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
179 -                   tty->ldisc.write_wakeup)
180 -                       (tty->ldisc.write_wakeup)(tty);
181 +               tty_wakeup(tty);
182                 wake_up_interruptible(&tty->write_wait);
183         }
184         func_exit ();
185 @@ -740,8 +736,9 @@
186  {
187         unsigned long flags;
188         struct gs_port *port;
189 -
190 -       func_enter ();
191 +       struct tty_ldisc *ld;
192
193 +       func_enter();
194  
195         if (!tty) return;
196  
197 @@ -818,8 +815,12 @@
198  
199         if (tty->driver.flush_buffer)
200                 tty->driver.flush_buffer(tty);
201 -       if (tty->ldisc.flush_buffer)
202 -               tty->ldisc.flush_buffer(tty);
203 +       ld = tty_ldisc_ref(tty);
204 +       if (ld != NULL) {
205 +               if (ld->flush_buffer) 
206 +                       ld->flush_buffer(tty);
207 +               tty_ldisc_deref(ld);
208 +       }
209         tty->closing = 0;
210  
211         port->event = 0;
212 diff -urN linux-2.2.26.orig/drivers/char/isicom.c linux-2.2.26/drivers/char/isicom.c
213 --- linux-2.2.26.orig/drivers/char/isicom.c     2001-03-25 18:31:27.000000000 +0200
214 +++ linux-2.2.26/drivers/char/isicom.c  2004-10-31 08:56:09.000000000 +0100
215 @@ -621,10 +621,8 @@
216         
217         if (!tty)
218                 return;
219 -       
220 -       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
221 -           tty->ldisc.write_wakeup)
222 -               (tty->ldisc.write_wakeup)(tty);
223 +
224 +       tty_wakeup(tty);
225         wake_up_interruptible(&tty->write_wait);
226  }              
227                 
228 @@ -1349,7 +1347,8 @@
229         struct isi_port * port = (struct isi_port *) tty->driver_data;
230         struct isi_board * card;
231         unsigned long flags;
232 -       
233 +       struct tty_ldisc *ld;
234 +
235  #ifdef ISICOM_DEBUG            
236         printk(KERN_DEBUG "ISICOM: Close start!!!.\n");
237  #endif 
238 @@ -1417,6 +1416,12 @@
239         isicom_shutdown_port(port);
240         if (tty->driver.flush_buffer)
241                 tty->driver.flush_buffer(tty);
242 +       ld = tty_ldisc_ref(tty);
243 +       if (ld != NULL) {
244 +               if (ld->flush_buffer)
245 +               ld->flush_buffer(tty);
246 +               tty_ldisc_deref(ld);
247 +       }
248         if (tty->ldisc.flush_buffer)
249                 tty->ldisc.flush_buffer(tty);
250  
251 @@ -1912,9 +1917,7 @@
252         spin_unlock_irqrestore(&card->card_lock, flags);
253         
254         wake_up_interruptible(&tty->write_wait);
255 -       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
256 -           tty->ldisc.write_wakeup)
257 -               (tty->ldisc.write_wakeup)(tty);
258 +       tty_wakeup(tty);
259  }
260  
261  
262 diff -urN linux-2.2.26.orig/drivers/char/moxa.c linux-2.2.26/drivers/char/moxa.c
263 --- linux-2.2.26.orig/drivers/char/moxa.c       2001-11-02 17:39:06.000000000 +0100
264 +++ linux-2.2.26/drivers/char/moxa.c    2004-10-31 09:02:00.000000000 +0100
265 @@ -616,6 +616,7 @@
266  {
267         struct moxa_str *ch;
268         int port;
269 +       struct tty_ldisc *ld;
270  
271         port = PORTNO(tty);
272         if (port == MAX_PORTS) {
273 @@ -673,8 +674,13 @@
274  
275         if (tty->driver.flush_buffer)
276                 tty->driver.flush_buffer(tty);
277 -       if (tty->ldisc.flush_buffer)
278 -               tty->ldisc.flush_buffer(tty);
279 +
280 +       ld = tty_ldisc_ref(tty);
281 +       if (ld != NULL) {
282 +               if (ld->flush_buffer)
283 +                       ld->flush_buffer(tty);
284 +               tty_ldisc_deref(ld);
285 +       }
286         tty->closing = 0;
287         ch->event = 0;
288         ch->tty = 0;
289 @@ -750,9 +756,7 @@
290         if (ch == NULL)
291                 return;
292         MoxaPortFlushData(ch->port, 1);
293 -       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
294 -           tty->ldisc.write_wakeup)
295 -               (tty->ldisc.write_wakeup) (tty);
296 +       tty_wakeup(tty);
297         wake_up_interruptible(&tty->write_wait);
298         wake_up_interruptible(&tty->poll_wait);
299  }
300 @@ -989,7 +993,6 @@
301                 moxaTimer.function = moxa_poll;
302                 moxaTimer.expires = jiffies + (HZ / 50);
303                 moxaTimer_on = 1;
304 -               add_timer(&moxaTimer);
305                 return;
306         }
307         for (card = 0; card < MAX_BOARDS; card++) {
308 @@ -1008,9 +1011,7 @@
309                                 if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) {
310                                         if (!tp->stopped) {
311                                                 ch->statusflags &= ~LOWWAIT;
312 -                                               if ((tp->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
313 -                                                 tp->ldisc.write_wakeup)
314 -                                                       (tp->ldisc.write_wakeup) (tp);
315 +                                               tty_wakeup(tp);
316                                                 wake_up_interruptible(&tp->write_wait);
317                                                 wake_up_interruptible(&tp->poll_wait);
318                                         }
319 @@ -1199,9 +1200,7 @@
320         if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
321                 if (MoxaPortTxQueue(ch->port) == 0) {
322                         ch->statusflags &= ~EMPTYWAIT;
323 -                       if ((ch->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
324 -                           ch->tty->ldisc.write_wakeup)
325 -                               (ch->tty->ldisc.write_wakeup) (ch->tty);
326 +                       tty_wakeup(ch->tty);
327                         wake_up_interruptible(&ch->tty->write_wait);
328                         wake_up_interruptible(&ch->tty->poll_wait);
329                         return;
330 diff -urN linux-2.2.26.orig/drivers/char/mxser.c linux-2.2.26/drivers/char/mxser.c
331 --- linux-2.2.26.orig/drivers/char/mxser.c      2001-03-25 18:31:28.000000000 +0200
332 +++ linux-2.2.26/drivers/char/mxser.c   2004-10-31 09:06:54.000000000 +0100
333 @@ -712,9 +712,7 @@
334         if (!tty)
335                 return;
336         if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) {
337 -               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
338 -                   tty->ldisc.write_wakeup)
339 -                       (tty->ldisc.write_wakeup) (tty);
340 +               tty_wakeup(tty);
341                 wake_up_interruptible(&tty->write_wait);
342                 wake_up_interruptible(&tty->poll_wait);
343         }
344 @@ -796,6 +794,7 @@
345         struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
346         unsigned long flags;
347         unsigned long timeout;
348 +       struct tty_ldisc *ld;
349  
350         if (PORTNO(tty) == MXSER_PORTS)
351                 return;
352 @@ -876,6 +875,12 @@
353         mxser_shutdown(info);
354         if (tty->driver.flush_buffer)
355                 tty->driver.flush_buffer(tty);
356 +       ld = tty_ldisc_ref(tty);
357 +       if (ld) {
358 +               if (ld->flush_buffer)
359 +                       ld->flush_buffer(tty);
360 +                       tty_ldisc_deref(ld);
361 +       }
362         if (tty->ldisc.flush_buffer)
363                 tty->ldisc.flush_buffer(tty);
364         tty->closing = 0;
365 @@ -1013,9 +1018,7 @@
366         restore_flags(flags);
367         wake_up_interruptible(&tty->write_wait);
368         wake_up_interruptible(&tty->poll_wait);
369 -       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
370 -           tty->ldisc.write_wakeup)
371 -               (tty->ldisc.write_wakeup) (tty);
372 +       tty_wakeup(tty);
373  }
374  
375  static int mxser_ioctl(struct tty_struct *tty, struct file *file,
376 diff -urN linux-2.2.26.orig/drivers/char/n_tty.c linux-2.2.26/drivers/char/n_tty.c
377 --- linux-2.2.26.orig/drivers/char/n_tty.c      2001-03-25 18:31:25.000000000 +0200
378 +++ linux-2.2.26/drivers/char/n_tty.c   2004-10-31 13:27:14.177336648 +0100
379 @@ -78,11 +78,18 @@
380         spin_unlock_irqrestore(&tty->read_lock, flags);
381  }
382  
383 -/* 
384 +/*
385 + * check_unthrottle - allow new receive data
386 + * @tty; tty device
387 + *
388   * Check whether to call the driver.unthrottle function.
389   * We test the TTY_THROTTLED bit first so that it always
390 - * indicates the current state.
391 - */
392 + * indicates the current state. The decision about whether
393 + * it is worth allowing more input has been taken by the caller.
394 + * Can sleep, may be called under the atomic_read semaphore but
395 + * this is not guaranteed.
396 +*/
397 +
398  static void check_unthrottle(struct tty_struct * tty)
399  {
400         if (tty->count &&
401 @@ -92,10 +99,14 @@
402  }
403  
404  /*
405 + * reset_buffer_flags - reset buffer state
406 + * @tty: terminal to reset
407 + *
408   * Reset the read buffer counters, clear the flags, 
409   * and make sure the driver is unthrottled. Called
410   * from n_tty_open() and n_tty_flush_buffer().
411   */
412 +
413  static void reset_buffer_flags(struct tty_struct *tty)
414  {
415         unsigned long flags;
416 @@ -109,8 +120,18 @@
417  }
418  
419  /*
420 - * Flush the input buffer
421 + * n_tty_flush_buffer - clean input queue
422 + * @tty: terminal device
423 + *
424 + * Flush the input buffer. Called when the line discipline is
425 + * being closed, when the tty layer wants the buffer flushed (eg
426 + * at hangup) or when the N_TTY line discipline internally has to
427 + * clean the pending queue (for example some signals).
428 + *
429 + * FIXME: tty->ctrl_status is not spinlocked and relies on
430 + * lock_kernel() still.
431   */
432 +
433  void n_tty_flush_buffer(struct tty_struct * tty)
434  {
435         /* clear everything and unthrottle the driver */
436 @@ -127,8 +148,13 @@
437  }
438  
439  /*
440 - * Return number of characters buffered to be delivered to user
441 + * n_tty_chars_in_buffer - report available bytes
442 + * @tty: tty device
443 + *
444 + * Report the number of characters buffered to be delivered to user
445 + * at this instant in time. 
446   */
447 +
448  ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
449  {
450         unsigned long flags;
451 @@ -210,9 +236,19 @@
452  }
453  
454  /*
455 - * opost_block --- to speed up block console writes, among other
456 - * things.
457 + * opost_block - block postprocess
458 + * @tty: terminal device
459 + * @inbuf: user buffer
460 + * @nr: number of bytes
461 + *
462 + * This path is used to speed up block console writes, among other
463 + * things when processing blocks of output data. It handles only
464 + * the simple cases normally found and helps to generate blocks of
465 + * symbols for the console driver and thus improve performance.
466 + *
467 + * Called from write_chan under the tty layer write lock.
468   */
469 +
470  static ssize_t opost_block(struct tty_struct * tty,
471                        const unsigned char * inbuf, unsigned int nr)
472  {
473 @@ -301,6 +337,16 @@
474         }
475  }
476  
477 +/*
478 + * eraser - handle erase function
479 + * @c: character input
480 + * @tty: terminal device
481 + *
482 + * Perform erase and neccessary output when an erase character is
483 + * present in the stream from the driver layer. Handles the complexities
484 + * of UTF-8 multibyte symbols.
485 + */
486 +
487  static void eraser(unsigned char c, struct tty_struct *tty)
488  {
489         enum { ERASE, WERASE, KILL } kill_type;
490 @@ -417,6 +463,18 @@
491                 finish_erasing(tty);
492  }
493  
494 +/*
495 + * isig - handle the ISIG optio
496 + * @sig: signal
497 + * @tty: terminal
498 + * @flush: force flush
499 + *
500 + * Called when a signal is being sent due to terminal input. This
501 + * may caus terminal flushing to take place according to the termios
502 + * settings and character used. Called from the driver receive_buf
503 + * path so serialized.
504 + */
505
506  static inline void isig(int sig, struct tty_struct *tty, int flush)
507  {
508         if (tty->pgrp > 0)
509 @@ -428,6 +486,16 @@
510         }
511  }
512  
513 +/*
514 + * n_tty_receive_break - handle break
515 + * @tty: terminal
516 + *
517 + * An RS232 break event has been hit in the incoming bitstream. This
518 + * can cause a variety of events depending upon the termios settings.
519 + *
520 + * Called from the receive_buf path so single threaded.
521 + */
522 +
523  static inline void n_tty_receive_break(struct tty_struct *tty)
524  {
525         if (I_IGNBRK(tty))
526 @@ -445,19 +513,41 @@
527         wake_up_interruptible(&tty->poll_wait);
528  }
529  
530 +/*
531 + * n_tty_receive_overrun - handle overrun reporting
532 + * @tty: terminal
533 + *
534 + * Data arrived faster than we could process it. While the tty
535 + * driver has flagged this the bits that were missed are gone
536 + * forever.
537 + *
538 + * Called from the receive_buf path so single threaded. Does not
539 + * need locking as num_overrun and overrun_time are function
540 + * private.
541 + */
542 +
543  static inline void n_tty_receive_overrun(struct tty_struct *tty)
544  {
545         char buf[64];
546  
547         tty->num_overrun++;
548         if (time_before(tty->overrun_time, jiffies - HZ)) {
549 -               printk("%s: %d input overrun(s)\n", tty_name(tty, buf),
550 +               printk(KERN_WARNING "%s: %d input overrun(s)\n", tty_name(tty, buf),
551                        tty->num_overrun);
552                 tty->overrun_time = jiffies;
553                 tty->num_overrun = 0;
554         }
555  }
556  
557 +/*
558 + * n_tty_receive_parity_error - error notifier
559 + * @tty: terminal device
560 + * @c: character
561 + *
562 + * Process a parity error and queue the right data to indicate
563 + * the error case if neccessary. Locking as per n_tty_receive_buf.
564 + */
565 +
566  static inline void n_tty_receive_parity_error(struct tty_struct *tty,
567                                               unsigned char c)
568  {
569 @@ -476,6 +566,16 @@
570         wake_up_interruptible(&tty->poll_wait);
571  }
572  
573 +/*
574 + * n_tty_receive_char - perform processing
575 + * @tty: terminal device
576 + * @c: character
577 + *
578 + * Process an individual character of input received from the driver.
579 + * This is serialized with respect to itself by the rules for the 
580 + * driver above.
581 + */
582 +
583  static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
584  {
585         if (tty->raw) {
586 @@ -667,6 +767,16 @@
587         put_tty_queue(c, tty);
588  }      
589  
590 +/*
591 + * n_tty_receive_room - receive space
592 + * @tty: terminal
593 + *
594 + * Called by the driver to find out how much data it is
595 + * permitted to feed to the line discipline without any being lost
596 + * and thus to manage flow control. Not serialized. Answers for the
597 + * "instant".
598 + */
599 +
600  static int n_tty_receive_room(struct tty_struct *tty)
601  {
602         int     left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
603 @@ -685,6 +795,19 @@
604         return 0;
605  }
606  
607 +/*
608 + * n_tty_receive_buf - data receive
609 + * @tty: terminal device
610 + * @cp: buffer
611 + * @fp: flag buffer
612 + * @count: characters
613 + *
614 + * Called by the terminal driver when a block of characters has
615 + * been received. This function must be called from soft contexts
616 + * not from interrupt context. The driver is responsible for making
617 + * calls one at a time and in order (or using queue_ldisc)
618 + */
619 +
620  static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
621                               char *fp, int count)
622  {
623 @@ -770,6 +893,18 @@
624                 current->sig->action[sig-1].sa.sa_handler == SIG_IGN);
625  }
626  
627 +/*
628 + * n_tty_set_termios - termios data changed
629 + * @tty: terminal
630 + * @old: previous data
631 + *
632 + * Called by the tty layer when the user changes termios flags so
633 + * that the line discipline can plan ahead. This function cannot sleep
634 + * and is protected from re-entry by the tty layer. The user is 
635 + * guaranteed that this function will not be re-entered or in progress
636 + * when the ldisc is closed.
637 + */
638 +
639  static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
640  {
641         if (!tty)
642 @@ -785,7 +920,6 @@
643             I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
644             I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
645             I_PARMRK(tty)) {
646 -               cli();
647                 memset(tty->process_char_map, 0, 256/8);
648  
649                 if (I_IGNCR(tty) || I_ICRNL(tty))
650 @@ -821,7 +955,6 @@
651                         set_bit(SUSP_CHAR(tty), &tty->process_char_map);
652                 }
653                 clear_bit(__DISABLED_CHAR, &tty->process_char_map);
654 -               sti();
655                 tty->raw = 0;
656                 tty->real_raw = 0;
657         } else {
658 @@ -835,6 +968,16 @@
659         }
660  }
661  
662 +/*
663 + * n_tty_close - close the ldisc for this tty
664 + * @tty: device
665 + *
666 + * Called from the terminal layer when this line discipline is 
667 + * being shut down, either because of a close or becsuse of a 
668 + * discipline change. The function will not be called while other
669 + * ldisc methods are in progress.
670 + */
671 +
672  static void n_tty_close(struct tty_struct *tty)
673  {
674         n_tty_flush_buffer(tty);
675 @@ -844,6 +987,16 @@
676         }
677  }
678  
679 +/*
680 + * n_tty_open - open an ldisc
681 + * @tty: terminal to open
682 + *
683 + * Called when this line discipline is being attached to the 
684 + * terminal device. Can sleep. Called serialized so that no
685 + * other events will occur in parallel. No further open will occur
686 + * until a close.
687 + */
688 +
689  static int n_tty_open(struct tty_struct *tty)
690  {
691         if (!tty)
692 @@ -876,13 +1029,22 @@
693  }
694  
695  /*
696 - * Helper function to speed up read_chan.  It is only called when
697 + * copy_from_read_buf - copy read data directly
698 + * @tty: terminal device
699 + * @b: user data
700 + * @nr: size of data
701 + *
702 + * Helper function to speed up read_chan. It is only called when
703   * ICANON is off; it copies characters straight from the tty queue to
704 - * user space directly.  It can be profitably called twice; once to
705 + * user space directly. It can be profitably called twice; once to
706   * drain the space from the tail pointer to the (physical) end of the
707   * buffer, and once to drain the space from the (physical) beginning of
708   * the buffer to head pointer.
709 + *
710 + * Called under the tty->atomic_read sem and with TTY_DONT_FLIP set
711 + *
712   */
713 +
714  static inline int copy_from_read_buf(struct tty_struct *tty,
715                                       unsigned char **b,
716                                       size_t *nr)
717 @@ -910,25 +1072,18 @@
718         return retval;
719  }
720  
721 -static ssize_t read_chan(struct tty_struct *tty, struct file *file,
722 -                        unsigned char *buf, size_t nr)
723 +/**
724 + * job_control - check job control
725 + * @tty: tty
726 + * @file: file handle
727 + *
728 + * Perform job control management checks on this file/tty descriptor
729 + * and if appropriate send any needed signals and return a negative
730 + * error code if action should be taken.
731 +*/
732
733 +static int job_control(struct tty_struct *tty, struct file *file)
734  {
735 -       unsigned char *b = buf;
736 -       struct wait_queue wait = { current, NULL };
737 -       int c;
738 -       int minimum, time;
739 -       ssize_t retval = 0;
740 -       ssize_t size;
741 -       long timeout;
742 -       unsigned long flags;
743 -
744 -do_it_again:
745 -
746 -       if (!tty->read_buf) {
747 -               printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
748 -               return -EIO;
749 -       }
750 -
751         /* Job control check -- must be done at start and after
752            every sleep (POSIX.1 7.1.1.4). */
753         /* NOTE: not yet done after every sleep pending a thorough
754 @@ -947,7 +1102,48 @@
755                         return -ERESTARTSYS;
756                 }
757         }
758 +return 0;
759 +
760 +}
761 +
762 +/**
763 + * read_chan - read function for tty
764 + * @tty: tty device
765 + * @file: file object
766 + * @buf: userspace buffer pointer
767 + * @nr: size of I/O
768 + *
769 + * Perform reads for the line discipline. We are guaranteed that the
770 + * line discipline will not be closed under us but we may get multiple
771 + * parallel readers and must handle this ourselves. We may also get
772 + * a hangup. Always called in user context, may sleep.
773 + *
774 + * This code must be sure never to sleep through a hangup.
775 + */
776
777 +static ssize_t read_chan(struct tty_struct *tty, struct file *file,
778 +       unsigned char *buf, size_t nr)
779 +{
780 +       unsigned char *b = buf;
781 +       DECLARE_WAITQUEUE(wait, current);
782 +       int c;
783 +       int minimum, time;
784 +       ssize_t retval = 0;
785 +       ssize_t size;
786 +       long timeout;
787 +       unsigned long flags;
788  
789 +       do_it_again:
790 +       
791 +       if (!tty->read_buf) {
792 +               printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
793 +               return -EIO;
794 +       }
795 +       
796 +       c = job_control(tty, file);
797 +       if(c < 0)
798 +               return c;
799 +       
800         minimum = time = 0;
801         timeout = MAX_SCHEDULE_TIMEOUT;
802         if (!tty->icanon) {
803 @@ -969,6 +1165,9 @@
804                 }
805         }
806  
807 +       /*
808 +        * Internal serialization of reads.
809 +        */
810         if (file->f_flags & O_NONBLOCK) {
811                 if (down_trylock(&tty->atomic_read))
812                         return -EAGAIN;
813 @@ -1103,6 +1302,21 @@
814         return retval;
815  }
816  
817 +/*
818 + * write_chan - write function for tty
819 + * @tty: tty device
820 + * @file: file object
821 + * @buf: userspace buffer pointer
822 + * @nr: size of I/O
823 + *
824 + * Write function of the terminal device. This is serialized with
825 + * respect to other write callers but not to termios changes, reads
826 + * and other such events. We must be careful with N_TTY as the receive
827 + * code will echo characters, thus calling driver write methods.
828 + *
829 + * This code must be sure never to sleep through a hangup.
830 + */
831 +
832  static ssize_t write_chan(struct tty_struct * tty, struct file * file,
833                           const unsigned char * buf, size_t nr)
834  {
835 @@ -1172,6 +1386,25 @@
836         return (b - buf) ? b - buf : retval;
837  }
838  
839 +/*
840 + * normal_poll - poll method for N_TTY
841 + * @tty: terminal device
842 + * @file: file accessing it
843 + * @wait: poll table
844 + *
845 + * Called when the line discipline is asked to poll() for data or
846 + * for special events. This code is not serialized with respect to
847 + * other events save open/close.
848 + *
849 + * This code must be sure never to sleep through a hangup.
850 + * Called without the kernel lock held - fine
851 + *
852 + * FIXME: if someone changes the VMIN or discipline settings for the
853 + * terminal while another process is in poll() the poll does not
854 + * recompute the new limits. Possibly set_termios should issue
855 + * a read wakeup to fix this bug.
856 + */
857 +
858  static unsigned int normal_poll(struct tty_struct * tty, struct file * file, poll_table *wait)
859  {
860         unsigned int mask = 0;
861 diff -urN linux-2.2.26.orig/drivers/char/pcxx.c linux-2.2.26/drivers/char/pcxx.c
862 --- linux-2.2.26.orig/drivers/char/pcxx.c       2001-03-25 18:31:25.000000000 +0200
863 +++ linux-2.2.26/drivers/char/pcxx.c    2004-10-31 09:34:16.000000000 +0100
864 @@ -621,10 +621,10 @@
865  ** please send me a note.  brian@ilinx.com
866  ** Don't know either what this is supposed to do clameter@waterf.org.
867  */
868 -               if(tty->ldisc.num != ldiscs[N_TTY].num) {
869 +               if(tty->ldisc.num != N_TTY) {
870                         if(tty->ldisc.close)
871                                 (tty->ldisc.close)(tty);
872 -                       tty->ldisc = ldiscs[N_TTY];
873 +                       tty->ldisc = *(tty_ldisc_get(N_TTY));
874                         tty->termios->c_line = N_TTY;
875                         if(tty->ldisc.open)
876                                 (tty->ldisc.open)(tty);
877 diff -urN linux-2.2.26.orig/drivers/char/pty.c linux-2.2.26/drivers/char/pty.c
878 --- linux-2.2.26.orig/drivers/char/pty.c        2001-03-25 18:31:24.000000000 +0200
879 +++ linux-2.2.26/drivers/char/pty.c     2004-10-31 09:17:13.000000000 +0100
880 @@ -134,6 +134,10 @@
881   *   (2) avoid redundant copying for cases where count >> receive_room
882   * N.B. Calls from user space may now return an error code instead of
883   * a count.
884 + *
885 + * FIXME: Our pty_write method is called with our ldisc lock held but
886 + * not our partners. We can't just take the other one blindly without
887 + + * risking deadlocks. There is also the small matter of TTY_DONT_FLIP
888   */
889  static int pty_write(struct tty_struct * tty, int from_user,
890                        const unsigned char *buf, int count)
891 diff -urN linux-2.2.26.orig/drivers/char/riscom8.c linux-2.2.26/drivers/char/riscom8.c
892 --- linux-2.2.26.orig/drivers/char/riscom8.c    2001-11-02 17:39:06.000000000 +0100
893 +++ linux-2.2.26/drivers/char/riscom8.c 2004-10-31 09:21:17.000000000 +0100
894 @@ -1110,7 +1110,8 @@
895         struct riscom_board *bp;
896         unsigned long flags;
897         unsigned long timeout;
898 -       
899 +       struct tty_ldisc *ld;
900 +
901         if (!port || rc_paranoia_check(port, tty->device, "close"))
902                 return;
903         
904 @@ -1180,6 +1181,12 @@
905         rc_shutdown_port(bp, port);
906         if (tty->driver.flush_buffer)
907                 tty->driver.flush_buffer(tty);
908 +       ld = tty_ldisc_ref(tty);
909 +       if (ld != NULL) {
910 +               if(ld->flush_buffer)
911 +                       ld->flush_buffer(tty);
912 +               tty_ldisc_deref(ld);
913 +       }
914         if (tty->ldisc.flush_buffer)
915                 tty->ldisc.flush_buffer(tty);
916         tty->closing = 0;
917 @@ -1358,9 +1365,7 @@
918         
919         wake_up_interruptible(&tty->write_wait);
920         wake_up_interruptible(&tty->poll_wait);
921 -       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
922 -           tty->ldisc.write_wakeup)
923 -               (tty->ldisc.write_wakeup)(tty);
924 +       tty_wakeup(tty);
925  }
926  
927  static int rc_get_modem_info(struct riscom_port * port, unsigned int *value)
928 @@ -1736,9 +1741,7 @@
929                 return;
930  
931         if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
932 -               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
933 -                   tty->ldisc.write_wakeup)
934 -                       (tty->ldisc.write_wakeup)(tty);
935 +               tty_wakeup(tty);
936                 wake_up_interruptible(&tty->write_wait);
937                 wake_up_interruptible(&tty->poll_wait);
938         }
939 diff -urN linux-2.2.26.orig/drivers/char/selection.c linux-2.2.26/drivers/char/selection.c
940 --- linux-2.2.26.orig/drivers/char/selection.c  2001-03-25 18:31:25.000000000 +0200
941 +++ linux-2.2.26/drivers/char/selection.c       2004-10-31 09:22:38.000000000 +0100
942 @@ -296,9 +296,11 @@
943  {
944         struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
945         int     pasted = 0, count;
946 +       struct tty_ldisc *ld;
947         struct wait_queue wait = { current, NULL };
948  
949         poke_blanked_console();
950 +       ld = tty_ldisc_ref_wait(tty);
951         add_wait_queue(&vt->paste_wait, &wait);
952         while (sel_buffer && sel_buffer_lth > pasted) {
953                 current->state = TASK_INTERRUPTIBLE;
954 @@ -313,6 +315,8 @@
955         }
956         remove_wait_queue(&vt->paste_wait, &wait);
957         current->state = TASK_RUNNING;
958 +
959 +       tty_ldisc_deref(ld);
960         return 0;
961  }
962  
963 diff -urN linux-2.2.26.orig/drivers/char/serial167.c linux-2.2.26/drivers/char/serial167.c
964 --- linux-2.2.26.orig/drivers/char/serial167.c  2001-03-25 18:31:26.000000000 +0200
965 +++ linux-2.2.26/drivers/char/serial167.c       2004-10-31 09:36:07.000000000 +0100
966 @@ -1943,10 +1943,10 @@
967         tty->ldisc.flush_buffer(tty);
968      info->event = 0;
969      info->tty = 0;
970 -    if (tty->ldisc.num != ldiscs[N_TTY].num) {
971 +    if (tty->ldisc.num != N_TTY) {
972         if (tty->ldisc.close)
973             (tty->ldisc.close)(tty);
974 -       tty->ldisc = ldiscs[N_TTY];
975 +       tty->ldisc = *(tty_ldisc_get(N_TTY));
976         tty->termios->c_line = N_TTY;
977         if (tty->ldisc.open)
978             (tty->ldisc.open)(tty);
979 diff -urN linux-2.2.26.orig/drivers/char/synclink.c linux-2.2.26/drivers/char/synclink.c
980 --- linux-2.2.26.orig/drivers/char/synclink.c   2001-11-02 17:39:06.000000000 +0100
981 +++ linux-2.2.26/drivers/char/synclink.c        2004-10-31 09:30:48.000000000 +0100
982 @@ -990,6 +990,42 @@
983         return 0;
984  }
985  
986 +/**
987 + * line discipline callback wrappers
988 + *
989 + * The wrappers maintain line discipline references
990 + * while calling into the line discipline.
991 + *
992 + * ldisc_flush_buffer - flush line discipline receive buffers
993 + * ldisc_receive_buf - pass receive data to line discipline
994 + */
995 +
996 +static void ldisc_flush_buffer(struct tty_struct *tty)
997 +{
998 +       struct tty_ldisc *ld = tty_ldisc_ref(tty);
999 +       
1000 +       if (ld) {
1001 +               if (ld->flush_buffer)
1002 +                       ld->flush_buffer(tty);
1003 +       tty_ldisc_deref(ld);
1004 +       }
1005 +}
1006 +
1007 +static void ldisc_receive_buf(struct tty_struct *tty,
1008 +       const __u8 *data, char *flags, int count)
1009 +{
1010 +       struct tty_ldisc *ld;
1011 +       
1012 +       if (!tty)
1013 +               return;
1014 +       ld = tty_ldisc_ref(tty);
1015 +       if (ld) {
1016 +               if (ld->receive_buf)
1017 +               ld->receive_buf(tty, data, flags, count);
1018 +               tty_ldisc_deref(ld);
1019 +       }
1020 +}
1021 +
1022  /* mgsl_stop()         throttle (stop) transmitter
1023   *     
1024   * Arguments:          tty     pointer to tty info structure
1025 @@ -1141,13 +1177,7 @@
1026                         __FILE__,__LINE__,info->device_name);
1027  
1028         if (tty) {
1029 -               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1030 -                   tty->ldisc.write_wakeup) {
1031 -                       if ( debug_level >= DEBUG_LEVEL_BH )
1032 -                               printk( "%s(%d):calling ldisc.write_wakeup on %s\n",
1033 -                                       __FILE__,__LINE__,info->device_name);
1034 -                       (tty->ldisc.write_wakeup)(tty);
1035 -               }
1036 +               tty_wakeup(tty);
1037                 wake_up_interruptible(&tty->write_wait);
1038         }
1039  
1040 @@ -2392,11 +2422,8 @@
1041         spin_unlock_irqrestore(&info->irq_spinlock,flags);
1042         
1043         wake_up_interruptible(&tty->write_wait);
1044 -       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1045 -           tty->ldisc.write_wakeup)
1046 -               (tty->ldisc.write_wakeup)(tty);
1047 -               
1048 -}      /* end of mgsl_flush_buffer() */
1049 +       tty_wakeup(tty);
1050 +}
1051  
1052  /* mgsl_send_xchar()
1053   *
1054 @@ -3297,10 +3324,8 @@
1055  
1056         if (tty->driver.flush_buffer)
1057                 tty->driver.flush_buffer(tty);
1058 -               
1059 -       if (tty->ldisc.flush_buffer)
1060 -               tty->ldisc.flush_buffer(tty);
1061 -               
1062 +       
1063 +       ldisc_flush_buffer(tty);                
1064         shutdown(info);
1065         
1066         tty->closing = 0;
1067 @@ -6999,11 +7024,7 @@
1068                         } 
1069                         else
1070  #endif
1071 -                       {
1072 -                               /* Call the line discipline receive callback directly. */
1073 -                               if ( tty && tty->ldisc.receive_buf )
1074 -                               tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
1075 -                       }
1076 +                       ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
1077                 }
1078         }
1079         /* Free the buffers used by this frame. */
1080 @@ -7175,9 +7196,7 @@
1081                         memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize);
1082                         info->icount.rxok++;
1083  
1084 -                       /* Call the line discipline receive callback directly. */
1085 -                       if ( tty && tty->ldisc.receive_buf )
1086 -                               tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
1087 +                       ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
1088                 }
1089  
1090                 /* Free the buffers used by this frame. */
1091 diff -urN linux-2.2.26.orig/drivers/char/tty_io.c linux-2.2.26/drivers/char/tty_io.c
1092 --- linux-2.2.26.orig/drivers/char/tty_io.c     2004-10-31 11:15:19.128606952 +0100
1093 +++ linux-2.2.26/drivers/char/tty_io.c  2004-10-31 12:02:45.000000000 +0100
1094 @@ -101,9 +101,13 @@
1095  #define TTY_PARANOIA_CHECK 1
1096  #define CHECK_TTY_COUNT 1
1097  
1098 +#define __builtin_expect(x, expected_value) (x)
1099 +#define likely(x)       __builtin_expect((x),1)
1100 +
1101 +/* Lock for tty_termios changes - private to tty_io/tty_ioctl */
1102 +spinlock_t tty_termios_lock = SPIN_LOCK_UNLOCKED;
1103  struct termios tty_std_termios;                /* for the benefit of tty drivers  */
1104  struct tty_driver *tty_drivers = NULL; /* linked list of tty drivers */
1105 -struct tty_ldisc ldiscs[NR_LDISCS];    /* line disc dispatch table     */
1106  
1107  #ifdef CONFIG_UNIX98_PTYS
1108  extern struct tty_driver ptm_driver[]; /* Unix98 pty masters; for /dev/ptmx */
1109 @@ -204,44 +208,256 @@
1110         return 0;
1111  }
1112  
1113 +/*
1114 + * This is probably overkill for real world processors but
1115 + * they are not on hot paths so a little discipline won't do
1116 + * any harm.
1117 + */ 
1118 +
1119 +static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
1120 +{
1121 + unsigned long flags;
1122 + spin_lock_irqsave(&tty_termios_lock, flags);
1123 + tty->termios->c_line = num;
1124 + spin_unlock_irqrestore(&tty_termios_lock, flags);
1125 +}
1126 +
1127 +/*
1128 + * This guards the refcounted line discipline lists. The lock
1129 + * must be taken with irqs off because there are hangup path
1130 + * callers who will do ldisc lookups and cannot sleep.
1131 + */
1132 +
1133 +spinlock_t tty_ldisc_lock = SPIN_LOCK_UNLOCKED;
1134 +DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
1135 +struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */
1136 +
1137  int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
1138  {
1139 +
1140 + unsigned long flags;
1141 + int ret = 0;
1142 +
1143         if (disc < N_TTY || disc >= NR_LDISCS)
1144                 return -EINVAL;
1145 -       
1146 +
1147 +       spin_lock_irqsave(&tty_ldisc_lock, flags);
1148         if (new_ldisc) {
1149 -               ldiscs[disc] = *new_ldisc;
1150 -               ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
1151 -               ldiscs[disc].num = disc;
1152 -       } else
1153 -               memset(&ldiscs[disc], 0, sizeof(struct tty_ldisc));
1154 +           tty_ldiscs[disc] = *new_ldisc;
1155 +           tty_ldiscs[disc].num = disc;
1156 +           tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
1157 +           tty_ldiscs[disc].refcount = 0;
1158 +       } else {
1159 +       if(tty_ldiscs[disc].refcount)
1160 +           ret = -EBUSY;
1161 +       else
1162 +           tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
1163 +       }
1164 +       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
1165         
1166 -       return 0;
1167 +       return ret;
1168  }
1169  
1170 -/* Set the discipline of a tty line. */
1171 +EXPORT_SYMBOL(tty_register_ldisc);
1172 +
1173 +struct tty_ldisc *tty_ldisc_get(int disc)
1174 +{
1175 +       unsigned long flags;
1176 +       struct tty_ldisc *ld;
1177 +
1178 +        if (disc < N_TTY || disc >= NR_LDISCS)
1179 +               return NULL;
1180 +
1181 +        spin_lock_irqsave(&tty_ldisc_lock, flags);
1182 +
1183 +        ld = &tty_ldiscs[disc];
1184 +        /* Check the entry is defined */
1185 +        if(ld->flags & LDISC_FLAG_DEFINED)
1186 +               ld->refcount++;
1187 +        else
1188 +               ld = NULL;
1189 +       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
1190 +       return ld;
1191 +}
1192 +
1193 +EXPORT_SYMBOL_GPL(tty_ldisc_get);
1194 +
1195 +void tty_ldisc_put(int disc)
1196 +{
1197 +        struct tty_ldisc *ld;
1198 +        unsigned long flags;
1199 +
1200 +        if (disc < N_TTY || disc >= NR_LDISCS)
1201 +               BUG();
1202 +
1203 +        spin_lock_irqsave(&tty_ldisc_lock, flags);
1204 +        ld = &tty_ldiscs[disc];
1205 +        if(ld->refcount <= 0)
1206 +               BUG();
1207 +        ld->refcount--;
1208 +        spin_unlock_irqrestore(&tty_ldisc_lock, flags);
1209 +}
1210
1211 +EXPORT_SYMBOL_GPL(tty_ldisc_put);
1212 +
1213 +void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
1214 +{
1215 +        tty->ldisc = *ld;
1216 +        tty->ldisc.refcount = 0;
1217 +}
1218 +
1219 +/**
1220 + * tty_ldisc_try - internal helper
1221 + * @tty: the tty
1222 + *
1223 + * Make a single attempt to grab and bump the refcount on
1224 + * the tty ldisc. Return 0 on failure or 1 on success. This is
1225 + * used to implement both the waiting and non waiting versions
1226 + * of tty_ldisc_ref
1227 + */
1228 +
1229 +static int tty_ldisc_try(struct tty_struct *tty)
1230 +{
1231 +        unsigned long flags;
1232 +        struct tty_ldisc *ld;
1233 +        int ret = 0;
1234 +
1235 +        spin_lock_irqsave(&tty_ldisc_lock, flags);
1236 +        ld = &tty->ldisc;
1237 +        if(test_bit(TTY_LDISC, &tty->flags)) {
1238 +               ld->refcount++;
1239 +               ret = 1;
1240 +       }
1241 +    spin_unlock_irqrestore(&tty_ldisc_lock, flags);
1242 +    return ret;
1243 +}
1244 +
1245 +/**
1246 + * tty_ldisc_ref_wait - wait for the tty ldisc
1247 + * @tty: tty device
1248 + *
1249 + * Dereference the line discipline for the terminal and take a
1250 + * reference to it. If the line discipline is in flux then
1251 + * wait patiently until it changes.
1252 + *
1253 + * Note: Must not be called from an IRQ/timer context. The caller
1254 + * must also be careful not to hold other locks that will deadlock
1255 + * against a discipline change, such as an existing ldisc reference
1256 + * (which we check for)
1257 + */
1258 +
1259 +struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
1260 +{
1261 +        /* wait_event is a macro */
1262 +        wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
1263 +        return &tty->ldisc;
1264 +}
1265 +
1266 +EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
1267 +
1268 +/**
1269 + * tty_ldisc_ref - get the tty ldisc
1270 + * @tty: tty device
1271 + *
1272 + * Dereference the line discipline for the terminal and take a
1273 + * reference to it. If the line discipline is in flux then
1274 + * return NULL. Can be called from IRQ and timer functions.
1275 + */
1276 +
1277 +struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
1278 +{
1279 +        if(tty_ldisc_try(tty))
1280 +               return &tty->ldisc;
1281 +        return NULL;
1282 +}
1283 +
1284 +EXPORT_SYMBOL_GPL(tty_ldisc_ref);
1285 +
1286 +void tty_ldisc_deref(struct tty_ldisc *ld)
1287 +{
1288 +        unsigned long flags;
1289 +
1290 +       if(ld == NULL)
1291 +           BUG();
1292 +
1293 +        spin_lock_irqsave(&tty_ldisc_lock, flags);
1294 +       if(ld->refcount == 0)
1295 +               printk(KERN_EMERG "tty_ldisc_deref: no references.\n");
1296 +        else
1297 +               ld->refcount--;
1298 +        if(ld->refcount == 0)
1299 +               wake_up(&tty_ldisc_wait);
1300 +        spin_unlock_irqrestore(&tty_ldisc_lock, flags);
1301 +}
1302 +
1303 +EXPORT_SYMBOL_GPL(tty_ldisc_deref);
1304 +
1305 +/**
1306 + * tty_set_ldisc - set line discipline
1307 + * @tty: the terminal to set
1308 + * @ldisc: the line discipline
1309 + *
1310 + * Set the discipline of a tty line. Must be called from a process
1311 + * context.
1312 + */
1313 +
1314  static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
1315  {
1316         int     retval = 0;
1317         struct  tty_ldisc o_ldisc;
1318         char buf[64];
1319 +       int work;
1320 +       unsigned long flags;
1321 +       struct tty_ldisc *ld;
1322  
1323         if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
1324                 return -EINVAL;
1325 +
1326 +       restart:
1327 +
1328 +       if (tty->ldisc.num == ldisc)
1329 +           return 0; /* We are already in the desired discipline */
1330 +
1331 +       ld = tty_ldisc_get(ldisc);
1332         /* Eduardo Blanco <ejbs@cs.cs.com.uy> */
1333         /* Cyrus Durgin <cider@speakeasy.org> */
1334 -       if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) {
1335 +       if (ld == NULL) {
1336                 char modname [20];
1337                 sprintf(modname, "tty-ldisc-%d", ldisc);
1338                 request_module (modname);
1339 -       }
1340 -       if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED))
1341 +               ld = tty_ldisc_get(ldisc);      }
1342 +       if (ld == NULL)
1343                 return -EINVAL;
1344  
1345 -       if (tty->ldisc.num == ldisc)
1346 -               return 0;       /* We are already in the desired discipline */
1347 -       o_ldisc = tty->ldisc;
1348 +       /*
1349 +       * Make sure we don't change while someone holds a
1350 +       * reference to the line discipline. The TTY_LDISC bit
1351 +       * prevents anyone taking a reference once it is clear.
1352 +       * We need the lock to avoid racing reference takers.
1353 +       */
1354 +
1355 +       spin_lock_irqsave(&tty_ldisc_lock, flags);
1356 +       if(tty->ldisc.refcount)
1357 +       {
1358 +           /* Free the new ldisc we grabbed. Must drop the lock
1359 +             first. */
1360 +           spin_unlock_irqrestore(&tty_ldisc_lock, flags);
1361 +           tty_ldisc_put(ldisc);
1362 +           if(wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
1363 +                   return -ERESTARTSYS;
1364 +           goto restart;
1365 +       }
1366 +       clear_bit(TTY_LDISC, &tty->flags);
1367 +       clear_bit(TTY_DONT_FLIP, &tty->flags);
1368 +       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
1369 +                    
1370 +       /*
1371 +        * From this point on we know nobody has an ldisc
1372 +        * usage reference, nor can they obtain one until
1373 +        * we say so later on.
1374 +        */
1375  
1376 +       o_ldisc = tty->ldisc;
1377         tty_wait_until_sent(tty, 0);
1378         
1379         /* Shutdown the current discipline. */
1380 @@ -249,16 +465,20 @@
1381                 (tty->ldisc.close)(tty);
1382  
1383         /* Now set up the new line discipline. */
1384 -       tty->ldisc = ldiscs[ldisc];
1385 -       tty->termios->c_line = ldisc;
1386 +       tty_ldisc_assign(tty, ld);
1387 +       tty_set_termios_ldisc(tty, ldisc);
1388         if (tty->ldisc.open)
1389                 retval = (tty->ldisc.open)(tty);
1390         if (retval < 0) {
1391 -               tty->ldisc = o_ldisc;
1392 -               tty->termios->c_line = tty->ldisc.num;
1393 +               tty_ldisc_put(ldisc);
1394 +               /* There is an outstanding reference here so this is safe */
1395 +               tty_ldisc_assign(tty, tty_ldisc_get(o_ldisc.num));
1396 +               tty_set_termios_ldisc(tty, tty->ldisc.num);
1397                 if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) {
1398 -                       tty->ldisc = ldiscs[N_TTY];
1399 -                       tty->termios->c_line = N_TTY;
1400 +                       tty_ldisc_put(o_ldisc.num);
1401 +                       /* This driver is always present */
1402 +                       tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
1403 +                       tty_set_termios_ldisc(tty, N_TTY);
1404                         if (tty->ldisc.open) {
1405                                 int r = tty->ldisc.open(tty);
1406  
1407 @@ -269,8 +489,23 @@
1408                         }
1409                 }
1410         }
1411 +       /* At this point we hold a reference to the new ldisc and a
1412 +       reference to the old ldisc. If we ended up flipping back
1413 +       to the existing ldisc we have two references to it */
1414 +
1415         if (tty->ldisc.num != o_ldisc.num && tty->driver.set_ldisc)
1416                 tty->driver.set_ldisc(tty);
1417 +
1418 +       tty_ldisc_put(o_ldisc.num);
1419 +
1420 +       /*
1421 +        * Allow ldisc referencing to occur as soon as the driver
1422 +        * ldisc callback completes.
1423 +       */
1424 +
1425 +       set_bit(TTY_LDISC, &tty->flags);
1426 +       wake_up(&tty_ldisc_wait);
1427 +       
1428         return retval;
1429  }
1430  
1431 @@ -385,6 +620,25 @@
1432  };
1433  
1434  /*
1435 + * Internal and external helper for wakeups of tty
1436 + */
1437 +
1438 +void tty_wakeup(struct tty_struct *tty)
1439 +{
1440 +       struct tty_ldisc *ld;
1441 +
1442 +       if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) {
1443 +           ld = tty_ldisc_ref(tty);
1444 +           if(ld) {
1445 +                   if(ld->write_wakeup)
1446 +                       ld->write_wakeup(tty);
1447 +                   tty_ldisc_deref(ld);
1448 +           }
1449 +       }
1450 +}
1451 +
1452 +EXPORT_SYMBOL_GPL(tty_wakeup);
1453 +/*
1454   * This can be called through the "tq_scheduler" 
1455   * task-list. That is process synchronous, but
1456   * doesn't hold any locks, so we need to make
1457 @@ -397,6 +651,7 @@
1458         struct file * filp;
1459         struct file * cons_filp = NULL;
1460         struct task_struct *p;
1461 +       struct tty_ldisc *ld;
1462         int    closecount = 0, n;
1463  
1464         if (!tty)
1465 @@ -426,19 +681,18 @@
1466         }
1467         
1468         /* FIXME! What are the locking issues here? This may me overdoing things.. */
1469 -       {
1470 -               unsigned long flags;
1471 -
1472 -               save_flags(flags); cli();
1473 -               if (tty->ldisc.flush_buffer)
1474 -                       tty->ldisc.flush_buffer(tty);
1475 +               ld = tty_ldisc_ref(tty);
1476 +               if(ld != NULL)  
1477 +               {
1478 +               if (ld->flush_buffer)
1479 +                       ld->flush_buffer(tty);
1480                 if (tty->driver.flush_buffer)
1481                         tty->driver.flush_buffer(tty);
1482 -               if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
1483 -                   tty->ldisc.write_wakeup)
1484 -                       (tty->ldisc.write_wakeup)(tty);
1485 -               restore_flags(flags);
1486 -       }
1487 +               if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && ld->write_wakeup)
1488 +                   ld->write_wakeup(tty);
1489 +                   //if (ld->hangup)
1490 +               // ld->hangup(tty);
1491 +               }
1492  
1493         wake_up_interruptible(&tty->write_wait);
1494         wake_up_interruptible(&tty->read_wait);
1495 @@ -448,20 +702,17 @@
1496          * Shutdown the current line discipline, and reset it to
1497          * N_TTY.
1498          */
1499 +
1500         if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS)
1501 +       {
1502 +               unsigned long flags;
1503 +               spin_lock_irqsave(&tty_termios_lock, flags);
1504                 *tty->termios = tty->driver.init_termios;
1505 -       if (tty->ldisc.num != ldiscs[N_TTY].num) {
1506 -               if (tty->ldisc.close)
1507 -                       (tty->ldisc.close)(tty);
1508 -               tty->ldisc = ldiscs[N_TTY];
1509 -               tty->termios->c_line = N_TTY;
1510 -               if (tty->ldisc.open) {
1511 -                       int i = (tty->ldisc.open)(tty);
1512 -                       if (i < 0)
1513 -                               printk("do_tty_hangup: N_TTY open: error %d\n",
1514 -                                      -i);
1515 -               }
1516 +               spin_unlock_irqrestore(&tty_termios_lock, flags);
1517         }
1518 +
1519 +       /* Defer ldisc switch */
1520 +       /* tty_deferred_ldisc_switch(N_TTY); */
1521         
1522         read_lock(&tasklist_lock);
1523         for_each_task(p) {
1524 @@ -493,6 +744,15 @@
1525                                 tty->driver.close(tty, cons_filp);
1526         } else if (tty->driver.hangup)
1527                 (tty->driver.hangup)(tty);
1528 +
1529 +       /* We don't want to have driver/ldisc interactions beyond
1530 +          the ones we did here. The driver layer expects no
1531 +          calls after ->hangup() from the ldisc side. However we
1532 +          can't yet guarantee all that */
1533 +
1534 +       set_bit(TTY_HUPPED, &tty->flags);
1535 +       if(ld)
1536 +           tty_ldisc_deref(ld);
1537         unlock_kernel();
1538  }
1539  
1540 @@ -602,9 +862,8 @@
1541         }
1542         if (tty->driver.start)
1543                 (tty->driver.start)(tty);
1544 -       if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
1545 -           tty->ldisc.write_wakeup)
1546 -               (tty->ldisc.write_wakeup)(tty);
1547 +       /* If we have a running line discipline it may need kicking */
1548 +           tty_wakeup(tty);    
1549         wake_up_interruptible(&tty->write_wait);
1550         wake_up_interruptible(&tty->poll_wait);
1551  }
1552 @@ -615,6 +874,7 @@
1553         int i;
1554         struct tty_struct * tty;
1555         struct inode *inode;
1556 +       struct tty_ldisc *ld;
1557  
1558         /* Can't seek (pread) on ttys.  */
1559         if (ppos != &file->f_pos)
1560 @@ -643,10 +903,16 @@
1561                         return -ERESTARTSYS;
1562                 }
1563  #endif
1564 -       if (tty->ldisc.read)
1565 -               i = (tty->ldisc.read)(tty,file,buf,count);
1566 +       /* We want to wait for the line discipline to sort out in this
1567 +          situation */
1568 +       ld = tty_ldisc_ref_wait(tty);
1569 +       lock_kernel();
1570 +       if (ld->read)
1571 +               i = (ld->read)(tty,file,buf,count);
1572         else
1573                 i = -EIO;
1574 +       tty_ldisc_deref(ld);
1575 +       unlock_kernel();
1576         if (i > 0)
1577                 inode->i_atime = CURRENT_TIME;
1578         return i;
1579 @@ -717,7 +983,9 @@
1580         int is_console;
1581         struct tty_struct * tty;
1582         struct inode *inode;
1583 -
1584 +       ssize_t ret;
1585 +       struct tty_ldisc *ld;
1586 +       
1587         /* Can't seek (pwrite) on ttys.  */
1588         if (ppos != &file->f_pos)
1589                 return -ESPIPE;
1590 @@ -749,10 +1017,15 @@
1591                 }
1592         }
1593  #endif
1594 -       if (!tty->ldisc.write)
1595 -               return -EIO;
1596 -       return do_tty_write(tty->ldisc.write, tty, file,
1597 -                           (const unsigned char *)buf, count);
1598 +
1599 +       ld = tty_ldisc_ref_wait(tty);
1600 +       if (!ld->write)
1601 +               ret = -EIO;
1602 +       else
1603 +               ret = do_tty_write(ld->write, tty, file,
1604 +                               (const unsigned char *) buf, count);
1605 +               tty_ldisc_deref(ld);
1606 +       return ret;
1607  }
1608  
1609  /* Semaphore to protect creating and releasing a tty */
1610 @@ -917,7 +1190,9 @@
1611                                 (tty->ldisc.close)(tty);
1612                         goto release_mem_out;
1613                 }
1614 -       }
1615 +       set_bit(TTY_LDISC, &o_tty->flags);
1616 +         }
1617 +       set_bit(TTY_LDISC, &tty->flags);
1618         goto success;
1619  
1620         /*
1621 @@ -945,7 +1220,9 @@
1622         }
1623         tty->count++;
1624         tty->driver = *driver; /* N.B. why do this every time?? */
1625 -
1626 +       /* FIXME */
1627 +       if(!test_bit(TTY_LDISC, &tty->flags))
1628 +               printk(KERN_ERR "init_dev but no ldisc\n");
1629  success:
1630         *ret_tty = tty;
1631         
1632 @@ -1023,6 +1300,7 @@
1633         int     pty_master, tty_closing, o_tty_closing, do_sleep;
1634         int     idx;
1635         char    buf[64];
1636 +       unsigned long flags;
1637         
1638         tty = (struct tty_struct *)filp->private_data;
1639         if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "release_dev"))
1640 @@ -1225,17 +1503,51 @@
1641  #endif
1642  
1643         /*
1644 +        * Prevent flush_to_ldisc() from rescheduling the work for later. Then
1645 +        * kill any delayed work. As this is the final close it does not
1646 +        * race with the set_ldisc code path.
1647 +        */
1648 +       clear_bit(TTY_LDISC, &tty->flags);
1649 +       clear_bit(TTY_DONT_FLIP, &tty->flags);
1650 +
1651 +       /*
1652 +       * Wait for any short term users (we know they are just driver
1653 +       * side waiters as the file is closing so user count on the file
1654 +       * side is zero.
1655 +       */
1656 +       
1657 +       spin_lock_irqsave(&tty_ldisc_lock, flags);
1658 +       while(tty->ldisc.refcount)
1659 +       {
1660 +               spin_unlock_irqrestore(&tty_ldisc_lock, flags);
1661 +               wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0);
1662 +               spin_lock_irqsave(&tty_ldisc_lock, flags);
1663 +       }
1664 +       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
1665 +       
1666 +       /*
1667          * Shutdown the current line discipline, and reset it to N_TTY.
1668          * N.B. why reset ldisc when we're releasing the memory??
1669 +        * FIXME: this MUST get fixed for the new reflocking
1670          */
1671         if (tty->ldisc.close)
1672                 (tty->ldisc.close)(tty);
1673 -       tty->ldisc = ldiscs[N_TTY];
1674 -       tty->termios->c_line = N_TTY;
1675 +       tty_ldisc_put(tty->ldisc.num);
1676 +
1677 +       /*
1678 +        * Switch the line discipline back
1679 +        */
1680 +       tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
1681 +       tty_set_termios_ldisc(tty,N_TTY); 
1682 +       
1683         if (o_tty) {
1684 +               /* FIXME: could o_tty be in setldisc here ? */
1685 +               clear_bit(TTY_LDISC, &o_tty->flags);
1686                 if (o_tty->ldisc.close)
1687                         (o_tty->ldisc.close)(o_tty);
1688 -               o_tty->ldisc = ldiscs[N_TTY];
1689 +               tty_ldisc_put(o_tty->ldisc.num);
1690 +               tty_ldisc_assign(o_tty, tty_ldisc_get(N_TTY));
1691 +               tty_set_termios_ldisc(o_tty,N_TTY);
1692         }
1693         
1694         /*
1695 @@ -1409,14 +1721,18 @@
1696  static unsigned int tty_poll(struct file * filp, poll_table * wait)
1697  {
1698         struct tty_struct * tty;
1699 +       struct tty_ldisc *ld;
1700 +       int ret = 0;
1701  
1702         tty = (struct tty_struct *)filp->private_data;
1703         if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "tty_poll"))
1704                 return 0;
1705  
1706 -       if (tty->ldisc.poll)
1707 -               return (tty->ldisc.poll)(tty, filp, wait);
1708 -       return 0;
1709 +       ld = tty_ldisc_ref_wait(tty);
1710 +       if (ld->poll)
1711 +               ret = (ld->poll)(tty, filp, wait);
1712 +       tty_ldisc_deref(ld);
1713 +       return ret;
1714  }
1715  
1716  /*
1717 @@ -1493,12 +1809,15 @@
1718  static int tiocsti(struct tty_struct *tty, char * arg)
1719  {
1720         char ch, mbz = 0;
1721 +       struct tty_ldisc *ld;
1722  
1723         if ((current->tty != tty) && !suser())
1724                 return -EPERM;
1725         if (get_user(ch, arg))
1726                 return -EFAULT;
1727 -       tty->ldisc.receive_buf(tty, &ch, &mbz, 1);
1728 +       ld = tty_ldisc_ref_wait(tty);
1729 +       ld->receive_buf(tty, &ch, &mbz, 1);
1730 +       tty_ldisc_deref(ld);
1731         return 0;
1732  }
1733  
1734 @@ -1679,6 +1998,7 @@
1735  {
1736         struct tty_struct *tty, *real_tty;
1737         int retval;
1738 +       struct tty_ldisc *ld;
1739         
1740         tty = (struct tty_struct *)file->private_data;
1741         if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl"))
1742 @@ -1766,6 +2086,7 @@
1743                 case TIOCGSID:
1744                         return tiocgsid(tty, real_tty, (pid_t *) arg);
1745                 case TIOCGETD:
1746 +                       /* FIXME: check this is ok */
1747                         return put_user(tty->ldisc.num, (int *) arg);
1748                 case TIOCSETD:
1749                         return tiocsetd(tty, (int *) arg);
1750 @@ -1799,16 +2120,20 @@
1751                         return send_break(tty, arg ? arg*(HZ/10) : HZ/4);
1752         }
1753         if (tty->driver.ioctl) {
1754 -               int retval = (tty->driver.ioctl)(tty, file, cmd, arg);
1755 +               retval = (tty->driver.ioctl)(tty, file, cmd, arg);
1756                 if (retval != -ENOIOCTLCMD)
1757                         return retval;
1758         }
1759 -       if (tty->ldisc.ioctl) {
1760 -               int retval = (tty->ldisc.ioctl)(tty, file, cmd, arg);
1761 -               if (retval != -ENOIOCTLCMD)
1762 -                       return retval;
1763 +       ld = tty_ldisc_ref_wait(tty);
1764 +       retval = -EINVAL;
1765 +       if (ld->ioctl) {
1766 +               if(likely(test_bit(TTY_LDISC, &tty->flags)))
1767 +                       retval = ld->ioctl(tty, file, cmd, arg);
1768 +               if (retval == -ENOIOCTLCMD)
1769 +                       retval = -EINVAL;
1770         }
1771 -       return -EINVAL;
1772 +       tty_ldisc_deref(ld);
1773 +       return retval;
1774  }
1775  
1776  
1777 @@ -1833,14 +2158,20 @@
1778         int session;
1779         int             i;
1780         struct file     *filp;
1781 +       struct tty_ldisc *disc;
1782         
1783         if (!tty)
1784                 return;
1785         session  = tty->session;
1786 -       if (tty->ldisc.flush_buffer)
1787 -               tty->ldisc.flush_buffer(tty);
1788 +       /* We don't want an ldisc switch during this */
1789 +       disc = tty_ldisc_ref(tty);
1790 +       if (disc && disc->flush_buffer)
1791 +               disc->flush_buffer(tty);
1792 +       tty_ldisc_deref(disc);
1793 +
1794         if (tty->driver.flush_buffer)
1795                 tty->driver.flush_buffer(tty);
1796 +
1797         read_lock(&tasklist_lock);
1798         for_each_task(p) {
1799                 if ((p->tty == tty) ||
1800 @@ -1872,10 +2203,15 @@
1801         char            *fp;
1802         int             count;
1803         unsigned long flags;
1804 +       struct tty_ldisc *disc;
1805 +
1806 +       disc = tty_ldisc_ref(tty);
1807 +       if (disc == NULL) /* !TTY_LDISC */
1808 +               return;
1809  
1810         if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
1811                 queue_task(&tty->flip.tqueue, &tq_timer);
1812 -               return;
1813 +               goto out;
1814         }
1815         if (tty->flip.buf_num) {
1816                 cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
1817 @@ -1897,8 +2233,31 @@
1818         count = tty->flip.count;
1819         tty->flip.count = 0;
1820         restore_flags(flags);
1821 -       
1822 -       tty->ldisc.receive_buf(tty, cp, fp, count);
1823 +       disc->receive_buf(tty, cp, fp, count);
1824 +       out:
1825 +                   tty_ldisc_deref(disc);
1826 +}
1827 +
1828 +/*
1829 + * Call the ldisc flush directly from a driver. This function may
1830 + * return an error and need retrying by the user.
1831 + */
1832 +
1833 +int tty_push_data(struct tty_struct *tty, unsigned char *cp, unsigned char *fp, int count)
1834 +{
1835 +       int ret = 0;
1836 +       struct tty_ldisc *disc;
1837 +        
1838 +       disc = tty_ldisc_ref(tty);
1839 +       if(test_bit(TTY_DONT_FLIP, &tty->flags))
1840 +               ret = -EAGAIN;
1841 +       else if(disc == NULL)
1842 +               ret = -EIO;
1843 +       else
1844 +               disc->receive_buf(tty, cp, fp, count);
1845 +               tty_ldisc_deref(disc);
1846 +       return ret;
1847 +
1848  }
1849  
1850  /*
1851 @@ -1960,7 +2319,7 @@
1852  {
1853         memset(tty, 0, sizeof(struct tty_struct));
1854         tty->magic = TTY_MAGIC;
1855 -       tty->ldisc = ldiscs[N_TTY];
1856 +       tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
1857         tty->pgrp = -1;
1858         tty->flip.char_buf_ptr = tty->flip.char_buf;
1859         tty->flip.flag_buf_ptr = tty->flip.flag_buf;
1860 @@ -2080,7 +2439,7 @@
1861  long __init console_init(long kmem_start, long kmem_end)
1862  {
1863         /* Setup the default TTY line discipline. */
1864 -       memset(ldiscs, 0, sizeof(ldiscs));
1865 +       memset(tty_ldiscs, 0, NR_LDISCS*sizeof(struct tty_ldisc));
1866         (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
1867  
1868         /*
1869 diff -urN linux-2.2.26.orig/drivers/char/tty_ioctl.c linux-2.2.26/drivers/char/tty_ioctl.c
1870 --- linux-2.2.26.orig/drivers/char/tty_ioctl.c  2001-03-25 18:31:24.000000000 +0200
1871 +++ linux-2.2.26/drivers/char/tty_ioctl.c       2004-10-31 12:06:32.000000000 +0100
1872 @@ -33,6 +33,8 @@
1873  # define       PRINTK(x)       /**/
1874  #endif
1875  
1876 +extern spinlock_t tty_termios_lock;
1877 +
1878  /*
1879   * Internal flag options for termios setting behavior
1880   */
1881 @@ -100,8 +102,17 @@
1882  {
1883         int canon_change;
1884         struct termios old_termios = *tty->termios;
1885 +       struct tty_ldisc *ld;
1886 +       unsigned long flags;
1887 +
1888 +       /*
1889 +        * Perform the actual termios internal changes under lock.
1890 +        */
1891 +
1892 +       /* FIXME: we need to decide on some locking/ordering semantics
1893 +           for the set_termios notification eventually */
1894 +       spin_lock_irqsave(&tty_termios_lock, flags);
1895  
1896 -       cli();
1897         *tty->termios = *new_termios;
1898         unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
1899         canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
1900 @@ -111,7 +122,7 @@
1901                 tty->canon_data = 0;
1902                 tty->erasing = 0;
1903         }
1904 -       sti();
1905 +       
1906         if (canon_change && !L_ICANON(tty) && tty->read_cnt)
1907         {
1908                 /* Get characters left over from canonical mode. */
1909 @@ -142,16 +153,21 @@
1910         if (tty->driver.set_termios)
1911                 (*tty->driver.set_termios)(tty, &old_termios);
1912  
1913 -       if (tty->ldisc.set_termios)
1914 -               (*tty->ldisc.set_termios)(tty, &old_termios);
1915 +       ld = tty_ldisc_ref(tty);
1916 +       if (ld != NULL) {
1917 +               if (ld->set_termios)
1918 +                       (ld->set_termios)(tty, &old_termios);
1919 +       tty_ldisc_deref(ld);
1920 +       }
1921 +       spin_unlock_irqrestore(&tty_termios_lock, flags);
1922  }
1923  
1924  static int set_termios(struct tty_struct * tty, unsigned long arg, int opt)
1925  {
1926         struct termios tmp_termios;
1927 -       int retval;
1928 +       struct tty_ldisc *ld;
1929 +       int retval = tty_check_change(tty);
1930  
1931 -       retval = tty_check_change(tty);
1932         if (retval)
1933                 return retval;
1934  
1935 @@ -164,9 +180,13 @@
1936                         return -EFAULT;
1937         }
1938  
1939 -       if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer)
1940 -               tty->ldisc.flush_buffer(tty);
1941 +       ld = tty_ldisc_ref(tty);
1942  
1943 +       if (ld != NULL) {
1944 +               if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
1945 +                   ld->flush_buffer(tty);
1946 +               tty_ldisc_deref(ld);
1947 +       }
1948         if (opt & TERMIOS_WAIT) {
1949                 tty_wait_until_sent(tty, 0);
1950                 if (signal_pending(current))
1951 @@ -230,12 +250,16 @@
1952  static int get_sgttyb(struct tty_struct * tty, struct sgttyb * sgttyb)
1953  {
1954         struct sgttyb tmp;
1955 +       unsigned long flags;
1956  
1957 +       spin_lock_irqsave(&tty_termios_lock, flags);
1958         tmp.sg_ispeed = 0;
1959         tmp.sg_ospeed = 0;
1960         tmp.sg_erase = tty->termios->c_cc[VERASE];
1961         tmp.sg_kill = tty->termios->c_cc[VKILL];
1962         tmp.sg_flags = get_sgflags(tty);
1963 +       spin_unlock_irqrestore(&tty_termios_lock, flags);
1964 +
1965         if (copy_to_user(sgttyb, &tmp, sizeof(tmp)))
1966                 return -EFAULT;
1967         return 0;
1968 @@ -275,12 +299,15 @@
1969         retval = tty_check_change(tty);
1970         if (retval)
1971                 return retval;
1972 -       termios =  *tty->termios;
1973 +       
1974         if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
1975                 return -EFAULT;
1976 +       spin_lock_irqsave(&tty_termios_lock, flags);
1977 +       termios = *tty->termios;
1978         termios.c_cc[VERASE] = tmp.sg_erase;
1979         termios.c_cc[VKILL] = tmp.sg_kill;
1980         set_sgflags(&termios, tmp.sg_flags);
1981 +       spin_unlock_irqrestore(&tty_termios_lock, flags);
1982         change_termios(tty, &termios);
1983         return 0;
1984  }
1985 @@ -374,6 +401,8 @@
1986  {
1987         struct tty_struct * real_tty;
1988         int retval;
1989 +       struct tty_ldisc *ld;
1990 +       unsigned long flags;
1991  
1992         if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
1993             tty->driver.subtype == PTY_TYPE_MASTER)
1994 @@ -423,6 +452,8 @@
1995                         retval = tty_check_change(tty);
1996                         if (retval)
1997                                 return retval;
1998 +
1999 +                       ld = tty_ldisc_ref(tty);
2000                         switch (arg) {
2001                         case TCOOFF:
2002                                 if (!tty->flow_stopped) {
2003 @@ -454,20 +485,22 @@
2004                                 return retval;
2005                         switch (arg) {
2006                         case TCIFLUSH:
2007 -                               if (tty->ldisc.flush_buffer)
2008 -                                       tty->ldisc.flush_buffer(tty);
2009 +                               if (ld->flush_buffer)
2010 +                                       ld->flush_buffer(tty);
2011                                 break;
2012                         case TCIOFLUSH:
2013 -                               if (tty->ldisc.flush_buffer)
2014 -                                       tty->ldisc.flush_buffer(tty);
2015 +                               if (ld->flush_buffer)
2016 +                                       ld->flush_buffer(tty);
2017                                 /* fall through */
2018                         case TCOFLUSH:
2019                                 if (tty->driver.flush_buffer)
2020                                         tty->driver.flush_buffer(tty);
2021                                 break;
2022                         default:
2023 +                       tty_ldisc_deref(ld);
2024                                 return -EINVAL;
2025                         }
2026 +                       tty_ldisc_deref(ld);
2027                         return 0;
2028                 case TIOCOUTQ:
2029                         return put_user(tty->driver.chars_in_buffer ?
2030 @@ -515,9 +548,11 @@
2031                         retval = get_user(arg, (unsigned int *) arg);
2032                         if (retval)
2033                                 return retval;
2034 +                       spin_lock_irqsave(&tty_termios_lock, flags);
2035                         tty->termios->c_cflag =
2036                                 ((tty->termios->c_cflag & ~CLOCAL) |
2037                                  (arg ? CLOCAL : 0));
2038 +                       spin_unlock_irqrestore(&tty_termios_lock, flags);
2039                         return 0;
2040                 default:
2041                         return -ENOIOCTLCMD;
2042 diff -urN linux-2.2.26.orig/drivers/net/slip.c linux-2.2.26/drivers/net/slip.c
2043 --- linux-2.2.26.orig/drivers/net/slip.c        2001-03-25 18:31:15.000000000 +0200
2044 +++ linux-2.2.26/drivers/net/slip.c     2004-10-24 11:09:19.428600744 +0200
2045 @@ -669,7 +669,9 @@
2046   * Handle the 'receiver data ready' interrupt.
2047   * This function is called by the 'tty_io' module in the kernel when
2048   * a block of SLIP data has been received, which can now be decapsulated
2049 - * and sent on to some IP layer for further processing.
2050 + * and sent on to some IP layer for further processing. This will not
2051 + * be re-entered while running but other ldisc functions may be called
2052 + * in parallel
2053   */
2054   
2055  static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
2056 @@ -824,9 +826,11 @@
2057   * SLIP line discipline is called for.  Because we are
2058   * sure the tty line exists, we only have to link it to
2059   * a free SLIP channel...
2060 + *
2061 + * Called in process context serialized from other ldisc calls.
2062   */
2063 -static int
2064 -slip_open(struct tty_struct *tty)
2065 +
2066 +static int slip_open(struct tty_struct *tty)
2067  {
2068         struct slip *sl;
2069         int err;
2070 @@ -908,6 +912,9 @@
2071  }
2072  
2073  /*
2074 +
2075 + FIXME: 1,2 are fixed 3 was never true anyway.
2076
2077     Let me to blame a bit.
2078     1. TTY module calls this funstion on soft interrupt.
2079     2. TTY module calls this function WITH MASKED INTERRUPTS!
2080 @@ -926,9 +933,8 @@
2081  
2082  /*
2083   * Close down a SLIP channel.
2084 - * This means flushing out any pending queues, and then restoring the
2085 - * TTY line discipline to what it was before it got hooked to SLIP
2086 - * (which usually is TTY again).
2087 + * This means flushing out any pending queues, and then returning. This
2088 + * call is serialized against other ldisc functions 
2089   */
2090  static void
2091  slip_close(struct tty_struct *tty)
2092 diff -urN linux-2.2.26.orig/drivers/sbus/char/zs.c linux-2.2.26/drivers/sbus/char/zs.c
2093 --- linux-2.2.26.orig/drivers/sbus/char/zs.c    2001-11-02 17:39:07.000000000 +0100
2094 +++ linux-2.2.26/drivers/sbus/char/zs.c 2004-10-31 09:43:01.192501208 +0100
2095 @@ -1606,10 +1606,10 @@
2096         tty->closing = 0;
2097         info->event = 0;
2098         info->tty = 0;
2099 -       if (tty->ldisc.num != ldiscs[N_TTY].num) {
2100 +       if (tty->ldisc.num != N_TTY) {
2101                 if (tty->ldisc.close)
2102                         (tty->ldisc.close)(tty);
2103 -               tty->ldisc = ldiscs[N_TTY];
2104 +               tty->ldisc = *(tty_ldisc_get(N_TTY));
2105                 tty->termios->c_line = N_TTY;
2106                 if (tty->ldisc.open)
2107                         (tty->ldisc.open)(tty);
2108 diff -urN linux-2.2.26.orig/drivers/sgi/char/sgiserial.c linux-2.2.26/drivers/sgi/char/sgiserial.c
2109 --- linux-2.2.26.orig/drivers/sgi/char/sgiserial.c      2001-03-25 18:31:41.000000000 +0200
2110 +++ linux-2.2.26/drivers/sgi/char/sgiserial.c   2004-10-31 09:38:06.825251832 +0100
2111 @@ -1465,10 +1465,10 @@
2112         tty->closing = 0;
2113         info->event = 0;
2114         info->tty = 0;
2115 -       if (tty->ldisc.num != ldiscs[N_TTY].num) {
2116 +       if (tty->ldisc.num != N_TTY) {
2117                 if (tty->ldisc.close)
2118                         (tty->ldisc.close)(tty);
2119 -               tty->ldisc = ldiscs[N_TTY];
2120 +               tty->ldisc = *(tty_ldisc_get(N_TTY));
2121                 tty->termios->c_line = N_TTY;
2122                 if (tty->ldisc.open)
2123                         (tty->ldisc.open)(tty);
2124 diff -urN linux-2.2.26.orig/fs/proc/proc_tty.c linux-2.2.26/fs/proc/proc_tty.c
2125 --- linux-2.2.26.orig/fs/proc/proc_tty.c        2004-02-24 14:48:05.000000000 +0100
2126 +++ linux-2.2.26/fs/proc/proc_tty.c     2004-10-31 13:07:51.212134232 +0100
2127 @@ -15,8 +15,6 @@
2128  #include <asm/bitops.h>
2129  
2130  extern struct tty_driver *tty_drivers; /* linked list of tty drivers */
2131 -extern struct tty_ldisc ldiscs[];
2132 -
2133  
2134  static int tty_drivers_read_proc(char *page, char **start, off_t off,
2135                                  int count, int *eof, void *data);
2136 @@ -112,16 +110,20 @@
2137         int     len = 0;
2138         off_t   begin = 0;
2139         off_t   end;
2140 +       struct tty_ldisc *ld;
2141  
2142         end = off + count;      /* XXX: undefined on overflow per ISO C99 */
2143         if (end < off)
2144                 return -EINVAL;
2145  
2146         for (i=0; i < NR_LDISCS; i++) {
2147 -               if (!(ldiscs[i].flags & LDISC_FLAG_DEFINED))
2148 +               ld = tty_ldisc_get(i);
2149 +               if (ld == NULL)
2150 +               
2151                         continue;
2152                 len += sprintf(page+len, "%-10s %2d\n",
2153 -                              ldiscs[i].name ? ldiscs[i].name : "???", i);
2154 +                       ld->name ? ld->name : "???", i);
2155 +                       tty_ldisc_put(i);
2156                 if (len+begin > end)
2157                         break;
2158                 if (len+begin < off) {
2159 diff -urN linux-2.2.26.orig/include/linux/tty.h linux-2.2.26/include/linux/tty.h
2160 --- linux-2.2.26.orig/include/linux/tty.h       2004-02-24 18:33:31.000000000 +0100
2161 +++ linux-2.2.26/include/linux/tty.h    2004-10-24 10:59:54.653459616 +0200
2162 @@ -319,19 +319,21 @@
2163   * tty->write.  Thus, you must use the inline functions set_bit() and
2164   * clear_bit() to make things atomic.
2165   */
2166 -#define TTY_THROTTLED 0
2167 -#define TTY_IO_ERROR 1
2168 -#define TTY_OTHER_CLOSED 2
2169 -#define TTY_EXCLUSIVE 3
2170 -#define TTY_DEBUG 4
2171 -#define TTY_DO_WRITE_WAKEUP 5
2172 -#define TTY_PUSH 6
2173 -#define TTY_CLOSING 7
2174 -#define TTY_DONT_FLIP 8
2175 -#define TTY_HW_COOK_OUT 14
2176 -#define TTY_HW_COOK_IN 15
2177 -#define TTY_PTY_LOCK 16
2178 -#define TTY_NO_WRITE_SPLIT 17
2179 +#define TTY_THROTTLED 0                /* Call unthrottle() at threshold min */
2180 +#define TTY_IO_ERROR 1         /* Canse an I/O error (may be no ldisc too) */
2181 +#define TTY_OTHER_CLOSED 2     /* Other side (if any) has closed */
2182 +#define TTY_EXCLUSIVE 3                /* Exclusive open mode */
2183 +#define TTY_DEBUG 4            /* Debugging */
2184 +#define TTY_DO_WRITE_WAKEUP 5  /* Call write_wakeup after queuing new */
2185 +#define TTY_PUSH 6             /* n_tty private */
2186 +#define TTY_CLOSING 7          /* ->close() in progress */
2187 +#define TTY_DONT_FLIP 8                /* Defer buffer flip */
2188 +#define TTY_LDISC 9            /* Line discipline attached */
2189 +#define TTY_HW_COOK_OUT 14     /* Hardware can do output cooking */
2190 +#define TTY_HW_COOK_IN 15      /* Hardware can do input cooking */
2191 +#define TTY_PTY_LOCK 16                /* pty private */
2192 +#define TTY_NO_WRITE_SPLIT 17  /* Preserve write boundaries to driver */
2193 +#define TTY_HUPPED 18          /* Post driver->hangup() */
2194  
2195  #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
2196  
2197 @@ -339,7 +341,7 @@
2198  
2199  extern struct termios tty_std_termios;
2200  extern struct tty_struct * redirect;
2201 -extern struct tty_ldisc ldiscs[];
2202 +extern struct tty_ldisc tty_ldiscs[];
2203  extern int fg_console, last_console, want_console;
2204  
2205  extern int kmsg_redirect;
2206 @@ -393,6 +395,16 @@
2207  extern void tty_flip_buffer_push(struct tty_struct *tty);
2208  extern int tty_get_baud_rate(struct tty_struct *tty);
2209  
2210 +extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
2211 +extern void tty_ldisc_deref(struct tty_ldisc *);
2212 +extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
2213 +
2214 +extern struct tty_ldisc *tty_ldisc_get(int);
2215 +extern void tty_ldisc_put(int);
2216 +
2217 +extern void tty_wakeup(struct tty_struct *tty);
2218 +
2219 +
2220  /* n_tty.c */
2221  extern struct tty_ldisc tty_ldisc_N_TTY;
2222  
2223 diff -urN linux-2.2.26.orig/include/linux/tty_ldisc.h linux-2.2.26/include/linux/tty_ldisc.h
2224 --- linux-2.2.26.orig/include/linux/tty_ldisc.h 2004-02-24 18:33:31.000000000 +0100
2225 +++ linux-2.2.26/include/linux/tty_ldisc.h      2004-10-24 11:04:07.991946312 +0200
2226 @@ -129,6 +129,7 @@
2227                                char *fp, int count);
2228         int     (*receive_room)(struct tty_struct *);
2229         void    (*write_wakeup)(struct tty_struct *);
2230 +int refcount;
2231  };
2232  
2233  #define TTY_LDISC_MAGIC        0x5403
This page took 0.20557 seconds and 3 git commands to generate.