diff options
author | Jeff Dike <jdike@addtoit.com> | 2006-01-06 03:18:58 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-06 11:33:46 -0500 |
commit | e4dcee8099802c71437a15b940f66106d9f88b2f (patch) | |
tree | b4831639d38369fce2e20fd40730425ca702102c /arch/um | |
parent | 9159c9dfffe1746d58b015ceaa3b7b8e99ee9d5c (diff) |
[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>
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/drivers/chan_kern.c | 26 | ||||
-rw-r--r-- | arch/um/drivers/line.c | 29 | ||||
-rw-r--r-- | arch/um/drivers/ssl.c | 14 | ||||
-rw-r--r-- | arch/um/drivers/stdio_console.c | 2 | ||||
-rw-r--r-- | arch/um/include/chan_kern.h | 2 | ||||
-rw-r--r-- | arch/um/include/line.h | 4 |
6 files changed, 63 insertions, 14 deletions
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 36df55ad64c2..cd13b91b9ff6 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c | |||
@@ -312,6 +312,32 @@ void close_chan(struct list_head *chans, int delay_free_irq) | |||
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 | int write_chan(struct list_head *chans, const char *buf, int len, | 341 | int write_chan(struct list_head *chans, const char *buf, int len, |
316 | int write_irq) | 342 | int write_irq) |
317 | { | 343 | { |
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 851a7c8caae5..b8e3e800ee41 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
@@ -36,8 +36,9 @@ static void line_timer_cb(void *arg) | |||
36 | { | 36 | { |
37 | struct line *line = arg; | 37 | struct line *line = arg; |
38 | 38 | ||
39 | chan_interrupt(&line->chan_list, &line->task, line->tty, | 39 | if(!line->throttled) |
40 | line->driver->read_irq); | 40 | chan_interrupt(&line->chan_list, &line->task, line->tty, |
41 | line->driver->read_irq); | ||
41 | } | 42 | } |
42 | 43 | ||
43 | /* Returns the free space inside the ring buffer of this line. | 44 | /* Returns the free space inside the ring buffer of this line. |
@@ -340,6 +341,30 @@ int line_ioctl(struct tty_struct *tty, struct file * file, | |||
340 | return ret; | 341 | return ret; |
341 | } | 342 | } |
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); | ||
366 | } | ||
367 | |||
343 | static irqreturn_t line_write_interrupt(int irq, void *data, | 368 | static irqreturn_t line_write_interrupt(int irq, void *data, |
344 | struct pt_regs *unused) | 369 | struct pt_regs *unused) |
345 | { | 370 | { |
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 6823dc5d665c..a32ef55cb244 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c | |||
@@ -109,16 +109,6 @@ static void ssl_flush_buffer(struct tty_struct *tty) | |||
109 | return; | 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 | static void ssl_stop(struct tty_struct *tty) | 112 | static void ssl_stop(struct tty_struct *tty) |
123 | { | 113 | { |
124 | printk(KERN_ERR "Someone should implement ssl_stop\n"); | 114 | printk(KERN_ERR "Someone should implement ssl_stop\n"); |
@@ -145,9 +135,9 @@ static struct tty_operations ssl_ops = { | |||
145 | .flush_chars = line_flush_chars, | 135 | .flush_chars = line_flush_chars, |
146 | .set_termios = line_set_termios, | 136 | .set_termios = line_set_termios, |
147 | .ioctl = line_ioctl, | 137 | .ioctl = line_ioctl, |
138 | .throttle = line_throttle, | ||
139 | .unthrottle = line_unthrottle, | ||
148 | #if 0 | 140 | #if 0 |
149 | .throttle = ssl_throttle, | ||
150 | .unthrottle = ssl_unthrottle, | ||
151 | .stop = ssl_stop, | 141 | .stop = ssl_stop, |
152 | .start = ssl_start, | 142 | .start = ssl_start, |
153 | .hangup = ssl_hangup, | 143 | .hangup = ssl_hangup, |
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 6d4edda9b510..61db8b2fc83f 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c | |||
@@ -122,6 +122,8 @@ static struct tty_operations console_ops = { | |||
122 | .flush_chars = line_flush_chars, | 122 | .flush_chars = line_flush_chars, |
123 | .set_termios = line_set_termios, | 123 | .set_termios = line_set_termios, |
124 | .ioctl = line_ioctl, | 124 | .ioctl = line_ioctl, |
125 | .throttle = line_throttle, | ||
126 | .unthrottle = line_unthrottle, | ||
125 | }; | 127 | }; |
126 | 128 | ||
127 | static void uml_console_write(struct console *console, const char *string, | 129 | static void uml_console_write(struct console *console, const char *string, |
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h index 84d1f64f9795..1bb5e9d94270 100644 --- a/arch/um/include/chan_kern.h +++ b/arch/um/include/chan_kern.h | |||
@@ -38,6 +38,8 @@ extern int console_write_chan(struct list_head *chans, const char *buf, | |||
38 | int len); | 38 | int len); |
39 | extern int console_open_chan(struct line *line, struct console *co, | 39 | extern int console_open_chan(struct line *line, struct console *co, |
40 | struct chan_opts *opts); | 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 | extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); | 43 | extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); |
42 | extern void enable_chan(struct line *line); | 44 | extern void enable_chan(struct line *line); |
43 | extern void close_chan(struct list_head *chans, int delay_free_irq); | 45 | extern void close_chan(struct list_head *chans, int delay_free_irq); |
diff --git a/arch/um/include/line.h b/arch/um/include/line.h index e6cc3abfd4db..6f4d680dc1d4 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h | |||
@@ -38,6 +38,7 @@ struct line { | |||
38 | struct list_head chan_list; | 38 | struct list_head chan_list; |
39 | int valid; | 39 | int valid; |
40 | int count; | 40 | int count; |
41 | int throttled; | ||
41 | /*This lock is actually, mostly, local to*/ | 42 | /*This lock is actually, mostly, local to*/ |
42 | spinlock_t lock; | 43 | spinlock_t lock; |
43 | 44 | ||
@@ -60,6 +61,7 @@ struct line { | |||
60 | { init_str : str, \ | 61 | { init_str : str, \ |
61 | init_pri : INIT_STATIC, \ | 62 | init_pri : INIT_STATIC, \ |
62 | valid : 1, \ | 63 | valid : 1, \ |
64 | throttled : 0, \ | ||
63 | lock : SPIN_LOCK_UNLOCKED, \ | 65 | lock : SPIN_LOCK_UNLOCKED, \ |
64 | buffer : NULL, \ | 66 | buffer : NULL, \ |
65 | head : NULL, \ | 67 | head : NULL, \ |
@@ -88,6 +90,8 @@ extern void line_flush_chars(struct tty_struct *tty); | |||
88 | extern int line_write_room(struct tty_struct *tty); | 90 | extern int line_write_room(struct tty_struct *tty); |
89 | extern int line_ioctl(struct tty_struct *tty, struct file * file, | 91 | extern int line_ioctl(struct tty_struct *tty, struct file * file, |
90 | unsigned int cmd, unsigned long arg); | 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 | extern char *add_xterm_umid(char *base); | 96 | extern char *add_xterm_umid(char *base); |
93 | extern int line_setup_irq(int fd, int input, int output, struct line *line, | 97 | extern int line_setup_irq(int fd, int input, int output, struct line *line, |