[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>
This commit is contained in:
parent
9159c9dfff
commit
e4dcee8099
|
@ -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_chan(struct list_head *chans, const char *buf, int len,
|
||||||
int write_irq)
|
int write_irq)
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,6 +36,7 @@ static void line_timer_cb(void *arg)
|
||||||
{
|
{
|
||||||
struct line *line = arg;
|
struct line *line = arg;
|
||||||
|
|
||||||
|
if(!line->throttled)
|
||||||
chan_interrupt(&line->chan_list, &line->task, line->tty,
|
chan_interrupt(&line->chan_list, &line->task, line->tty,
|
||||||
line->driver->read_irq);
|
line->driver->read_irq);
|
||||||
}
|
}
|
||||||
|
@ -340,6 +341,30 @@ int line_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
return ret;
|
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,
|
static irqreturn_t line_write_interrupt(int irq, void *data,
|
||||||
struct pt_regs *unused)
|
struct pt_regs *unused)
|
||||||
{
|
{
|
||||||
|
|
|
@ -109,16 +109,6 @@ static void ssl_flush_buffer(struct tty_struct *tty)
|
||||||
return;
|
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)
|
static void ssl_stop(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
printk(KERN_ERR "Someone should implement ssl_stop\n");
|
printk(KERN_ERR "Someone should implement ssl_stop\n");
|
||||||
|
@ -145,9 +135,9 @@ static struct tty_operations ssl_ops = {
|
||||||
.flush_chars = line_flush_chars,
|
.flush_chars = line_flush_chars,
|
||||||
.set_termios = line_set_termios,
|
.set_termios = line_set_termios,
|
||||||
.ioctl = line_ioctl,
|
.ioctl = line_ioctl,
|
||||||
|
.throttle = line_throttle,
|
||||||
|
.unthrottle = line_unthrottle,
|
||||||
#if 0
|
#if 0
|
||||||
.throttle = ssl_throttle,
|
|
||||||
.unthrottle = ssl_unthrottle,
|
|
||||||
.stop = ssl_stop,
|
.stop = ssl_stop,
|
||||||
.start = ssl_start,
|
.start = ssl_start,
|
||||||
.hangup = ssl_hangup,
|
.hangup = ssl_hangup,
|
||||||
|
|
|
@ -122,6 +122,8 @@ static struct tty_operations console_ops = {
|
||||||
.flush_chars = line_flush_chars,
|
.flush_chars = line_flush_chars,
|
||||||
.set_termios = line_set_termios,
|
.set_termios = line_set_termios,
|
||||||
.ioctl = line_ioctl,
|
.ioctl = line_ioctl,
|
||||||
|
.throttle = line_throttle,
|
||||||
|
.unthrottle = line_unthrottle,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void uml_console_write(struct console *console, const char *string,
|
static void uml_console_write(struct console *console, const char *string,
|
||||||
|
|
|
@ -38,6 +38,8 @@ extern int console_write_chan(struct list_head *chans, const char *buf,
|
||||||
int len);
|
int len);
|
||||||
extern int console_open_chan(struct line *line, struct console *co,
|
extern int console_open_chan(struct line *line, struct console *co,
|
||||||
struct chan_opts *opts);
|
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 chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
|
||||||
extern void enable_chan(struct line *line);
|
extern void enable_chan(struct line *line);
|
||||||
extern void close_chan(struct list_head *chans, int delay_free_irq);
|
extern void close_chan(struct list_head *chans, int delay_free_irq);
|
||||||
|
|
|
@ -38,6 +38,7 @@ struct line {
|
||||||
struct list_head chan_list;
|
struct list_head chan_list;
|
||||||
int valid;
|
int valid;
|
||||||
int count;
|
int count;
|
||||||
|
int throttled;
|
||||||
/*This lock is actually, mostly, local to*/
|
/*This lock is actually, mostly, local to*/
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
|
||||||
|
@ -60,6 +61,7 @@ struct line {
|
||||||
{ init_str : str, \
|
{ init_str : str, \
|
||||||
init_pri : INIT_STATIC, \
|
init_pri : INIT_STATIC, \
|
||||||
valid : 1, \
|
valid : 1, \
|
||||||
|
throttled : 0, \
|
||||||
lock : SPIN_LOCK_UNLOCKED, \
|
lock : SPIN_LOCK_UNLOCKED, \
|
||||||
buffer : NULL, \
|
buffer : NULL, \
|
||||||
head : 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_write_room(struct tty_struct *tty);
|
||||||
extern int line_ioctl(struct tty_struct *tty, struct file * file,
|
extern int line_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
unsigned int cmd, unsigned long arg);
|
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 char *add_xterm_umid(char *base);
|
||||||
extern int line_setup_irq(int fd, int input, int output, struct line *line,
|
extern int line_setup_irq(int fd, int input, int output, struct line *line,
|
||||||
|
|
Loading…
Reference in New Issue