summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2006-01-06 00:18:58 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 08:33:46 -0800
commite4dcee8099802c71437a15b940f66106d9f88b2f (patch)
treeb4831639d38369fce2e20fd40730425ca702102c
parent9159c9dfffe1746d58b015ceaa3b7b8e99ee9d5c (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>
-rw-r--r--arch/um/drivers/chan_kern.c26
-rw-r--r--arch/um/drivers/line.c29
-rw-r--r--arch/um/drivers/ssl.c14
-rw-r--r--arch/um/drivers/stdio_console.c2
-rw-r--r--arch/um/include/chan_kern.h2
-rw-r--r--arch/um/include/line.h4
6 files changed, 63 insertions, 14 deletions
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 36df55ad64c..cd13b91b9ff 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)
}
}
+void deactivate_chan(struct list_head *chans, int irq)
+{
+ struct list_head *ele;
+
+ struct chan *chan;
+ list_for_each(ele, chans) {
+ chan = list_entry(ele, struct chan, list);
+
+ if(chan->enabled && chan->input)
+ deactivate_fd(chan->fd, irq);
+ }
+}
+
+void reactivate_chan(struct list_head *chans, int irq)
+{
+ struct list_head *ele;
+ struct chan *chan;
+
+ list_for_each(ele, chans) {
+ chan = list_entry(ele, struct chan, list);
+
+ if(chan->enabled && chan->input)
+ reactivate_fd(chan->fd, irq);
+ }
+}
+
int write_chan(struct list_head *chans, const char *buf, int len,
int write_irq)
{
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 851a7c8caae..b8e3e800ee4 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -36,8 +36,9 @@ static void line_timer_cb(void *arg)
{
struct line *line = arg;
- chan_interrupt(&line->chan_list, &line->task, line->tty,
- line->driver->read_irq);
+ if(!line->throttled)
+ chan_interrupt(&line->chan_list, &line->task, line->tty,
+ line->driver->read_irq);
}
/* 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,
return ret;
}
+void line_throttle(struct tty_struct *tty)
+{
+ struct line *line = tty->driver_data;
+
+ deactivate_chan(&line->chan_list, line->driver->read_irq);
+ line->throttled = 1;
+}
+
+void line_unthrottle(struct tty_struct *tty)
+{
+ struct line *line = tty->driver_data;
+
+ line->throttled = 0;
+ chan_interrupt(&line->chan_list, &line->task, tty,
+ line->driver->read_irq);
+
+ /* Maybe there is enough stuff pending that calling the interrupt
+ * throttles us again. In this case, line->throttled will be 1
+ * again and we shouldn't turn the interrupt back on.
+ */
+ if(!line->throttled)
+ reactivate_chan(&line->chan_list, line->driver->read_irq);
+}
+
static irqreturn_t line_write_interrupt(int irq, void *data,
struct pt_regs *unused)
{
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 6823dc5d665..a32ef55cb24 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)
return;
}
-static void ssl_throttle(struct tty_struct * tty)
-{
- printk(KERN_ERR "Someone should implement ssl_throttle\n");
-}
-
-static void ssl_unthrottle(struct tty_struct * tty)
-{
- printk(KERN_ERR "Someone should implement ssl_unthrottle\n");
-}
-
static void ssl_stop(struct tty_struct *tty)
{
printk(KERN_ERR "Someone should implement ssl_stop\n");
@@ -145,9 +135,9 @@ static struct tty_operations ssl_ops = {
.flush_chars = line_flush_chars,
.set_termios = line_set_termios,
.ioctl = line_ioctl,
+ .throttle = line_throttle,
+ .unthrottle = line_unthrottle,
#if 0
- .throttle = ssl_throttle,
- .unthrottle = ssl_unthrottle,
.stop = ssl_stop,
.start = ssl_start,
.hangup = ssl_hangup,
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 6d4edda9b51..61db8b2fc83 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 = {
.flush_chars = line_flush_chars,
.set_termios = line_set_termios,
.ioctl = line_ioctl,
+ .throttle = line_throttle,
+ .unthrottle = line_unthrottle,
};
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 84d1f64f979..1bb5e9d9427 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,
int len);
extern int console_open_chan(struct line *line, struct console *co,
struct chan_opts *opts);
+extern void deactivate_chan(struct list_head *chans, int irq);
+extern void reactivate_chan(struct list_head *chans, int irq);
extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
extern void enable_chan(struct line *line);
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 e6cc3abfd4d..6f4d680dc1d 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -38,6 +38,7 @@ struct line {
struct list_head chan_list;
int valid;
int count;
+ int throttled;
/*This lock is actually, mostly, local to*/
spinlock_t lock;
@@ -60,6 +61,7 @@ struct line {
{ init_str : str, \
init_pri : INIT_STATIC, \
valid : 1, \
+ throttled : 0, \
lock : SPIN_LOCK_UNLOCKED, \
buffer : NULL, \
head : NULL, \
@@ -88,6 +90,8 @@ extern void line_flush_chars(struct tty_struct *tty);
extern int line_write_room(struct tty_struct *tty);
extern int line_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg);
+extern void line_throttle(struct tty_struct *tty);
+extern void line_unthrottle(struct tty_struct *tty);
extern char *add_xterm_umid(char *base);
extern int line_setup_irq(int fd, int input, int output, struct line *line,