Commit e4dcee8099802c71437a15b940f66106d9f88b2f

Authored by Jeff Dike
Committed by Linus Torvalds
1 parent 9159c9dfff

[PATCH] uml: Add throttling to console driver

This patch adds support for throttling and unthrottling input when the tty
driver can't handle it.

Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 6 changed files with 63 additions and 14 deletions Side-by-side Diff

arch/um/drivers/chan_kern.c
... ... @@ -312,6 +312,32 @@
312 312 }
313 313 }
314 314  
  315 +void deactivate_chan(struct list_head *chans, int irq)
  316 +{
  317 + struct list_head *ele;
  318 +
  319 + struct chan *chan;
  320 + list_for_each(ele, chans) {
  321 + chan = list_entry(ele, struct chan, list);
  322 +
  323 + if(chan->enabled && chan->input)
  324 + deactivate_fd(chan->fd, irq);
  325 + }
  326 +}
  327 +
  328 +void reactivate_chan(struct list_head *chans, int irq)
  329 +{
  330 + struct list_head *ele;
  331 + struct chan *chan;
  332 +
  333 + list_for_each(ele, chans) {
  334 + chan = list_entry(ele, struct chan, list);
  335 +
  336 + if(chan->enabled && chan->input)
  337 + reactivate_fd(chan->fd, irq);
  338 + }
  339 +}
  340 +
315 341 int write_chan(struct list_head *chans, const char *buf, int len,
316 342 int write_irq)
317 343 {
arch/um/drivers/line.c
... ... @@ -36,8 +36,9 @@
36 36 {
37 37 struct line *line = arg;
38 38  
39   - chan_interrupt(&line->chan_list, &line->task, line->tty,
40   - line->driver->read_irq);
  39 + if(!line->throttled)
  40 + chan_interrupt(&line->chan_list, &line->task, line->tty,
  41 + line->driver->read_irq);
41 42 }
42 43  
43 44 /* Returns the free space inside the ring buffer of this line.
... ... @@ -338,6 +339,30 @@
338 339 break;
339 340 }
340 341 return ret;
  342 +}
  343 +
  344 +void line_throttle(struct tty_struct *tty)
  345 +{
  346 + struct line *line = tty->driver_data;
  347 +
  348 + deactivate_chan(&line->chan_list, line->driver->read_irq);
  349 + line->throttled = 1;
  350 +}
  351 +
  352 +void line_unthrottle(struct tty_struct *tty)
  353 +{
  354 + struct line *line = tty->driver_data;
  355 +
  356 + line->throttled = 0;
  357 + chan_interrupt(&line->chan_list, &line->task, tty,
  358 + line->driver->read_irq);
  359 +
  360 + /* Maybe there is enough stuff pending that calling the interrupt
  361 + * throttles us again. In this case, line->throttled will be 1
  362 + * again and we shouldn't turn the interrupt back on.
  363 + */
  364 + if(!line->throttled)
  365 + reactivate_chan(&line->chan_list, line->driver->read_irq);
341 366 }
342 367  
343 368 static irqreturn_t line_write_interrupt(int irq, void *data,
arch/um/drivers/ssl.c
... ... @@ -109,16 +109,6 @@
109 109 return;
110 110 }
111 111  
112   -static void ssl_throttle(struct tty_struct * tty)
113   -{
114   - printk(KERN_ERR "Someone should implement ssl_throttle\n");
115   -}
116   -
117   -static void ssl_unthrottle(struct tty_struct * tty)
118   -{
119   - printk(KERN_ERR "Someone should implement ssl_unthrottle\n");
120   -}
121   -
122 112 static void ssl_stop(struct tty_struct *tty)
123 113 {
124 114 printk(KERN_ERR "Someone should implement ssl_stop\n");
125 115  
... ... @@ -145,9 +135,9 @@
145 135 .flush_chars = line_flush_chars,
146 136 .set_termios = line_set_termios,
147 137 .ioctl = line_ioctl,
  138 + .throttle = line_throttle,
  139 + .unthrottle = line_unthrottle,
148 140 #if 0
149   - .throttle = ssl_throttle,
150   - .unthrottle = ssl_unthrottle,
151 141 .stop = ssl_stop,
152 142 .start = ssl_start,
153 143 .hangup = ssl_hangup,
arch/um/drivers/stdio_console.c
... ... @@ -122,6 +122,8 @@
122 122 .flush_chars = line_flush_chars,
123 123 .set_termios = line_set_termios,
124 124 .ioctl = line_ioctl,
  125 + .throttle = line_throttle,
  126 + .unthrottle = line_unthrottle,
125 127 };
126 128  
127 129 static void uml_console_write(struct console *console, const char *string,
arch/um/include/chan_kern.h
... ... @@ -38,6 +38,8 @@
38 38 int len);
39 39 extern int console_open_chan(struct line *line, struct console *co,
40 40 struct chan_opts *opts);
  41 +extern void deactivate_chan(struct list_head *chans, int irq);
  42 +extern void reactivate_chan(struct list_head *chans, int irq);
41 43 extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
42 44 extern void enable_chan(struct line *line);
43 45 extern void close_chan(struct list_head *chans, int delay_free_irq);
arch/um/include/line.h
... ... @@ -38,6 +38,7 @@
38 38 struct list_head chan_list;
39 39 int valid;
40 40 int count;
  41 + int throttled;
41 42 /*This lock is actually, mostly, local to*/
42 43 spinlock_t lock;
43 44  
... ... @@ -60,6 +61,7 @@
60 61 { init_str : str, \
61 62 init_pri : INIT_STATIC, \
62 63 valid : 1, \
  64 + throttled : 0, \
63 65 lock : SPIN_LOCK_UNLOCKED, \
64 66 buffer : NULL, \
65 67 head : NULL, \
... ... @@ -88,6 +90,8 @@
88 90 extern int line_write_room(struct tty_struct *tty);
89 91 extern int line_ioctl(struct tty_struct *tty, struct file * file,
90 92 unsigned int cmd, unsigned long arg);
  93 +extern void line_throttle(struct tty_struct *tty);
  94 +extern void line_unthrottle(struct tty_struct *tty);
91 95  
92 96 extern char *add_xterm_umid(char *base);
93 97 extern int line_setup_irq(int fd, int input, int output, struct line *line,