Commit e4dcee8099802c71437a15b940f66106d9f88b2f
Committed by
Linus Torvalds
1 parent
9159c9dfff
Exists in
master
and in
7 other branches
[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, |