Merge branch 'for-linus-3.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml
Pull UML changes from Richard Weinberger: "Mostly bug fixes and cleanups" * 'for-linus-3.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: (35 commits) um: Update defconfig um: Switch to large mcmodel on x86_64 MTD: Relax dependencies um: Wire CONFIG_GENERIC_IO up um: Serve io_remap_pfn_range() Introduce CONFIG_GENERIC_IO um: allow SUBARCH=x86 um: most of the SUBARCH uses can be killed um: deadlock in line_write_interrupt() um: don't bother trying to rebuild CHECKFLAGS for USER_OBJS um: use the right ifdef around exports in user_syms.c um: a bunch of headers can be killed by using generic-y um: ptrace-generic.h doesn't need user.h um: kill HOST_TASK_PID um: remove pointless include of asm/fixmap.h from asm/pgtable.h um: asm-offsets.h might as well come from underlying arch... um: merge processor_{32,64}.h a bit... um: switch close_chan() to struct line um: race fix: initialize delayed_work *before* registering IRQ um: line->have_irq is never checked... ...
Esse commit está contido em:
@@ -27,24 +27,24 @@ struct chan {
|
||||
void *data;
|
||||
};
|
||||
|
||||
extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
|
||||
extern void chan_interrupt(struct line *line,
|
||||
struct tty_struct *tty, int irq);
|
||||
extern int parse_chan_pair(char *str, struct line *line, int device,
|
||||
const struct chan_opts *opts, char **error_out);
|
||||
extern int write_chan(struct list_head *chans, const char *buf, int len,
|
||||
extern int write_chan(struct chan *chan, const char *buf, int len,
|
||||
int write_irq);
|
||||
extern int console_write_chan(struct list_head *chans, const char *buf,
|
||||
extern int console_write_chan(struct chan *chan, const char *buf,
|
||||
int len);
|
||||
extern int console_open_chan(struct line *line, struct console *co);
|
||||
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 deactivate_chan(struct chan *chan, int irq);
|
||||
extern void reactivate_chan(struct chan *chan, int irq);
|
||||
extern void chan_enable_winch(struct chan *chan, struct tty_struct *tty);
|
||||
extern int enable_chan(struct line *line);
|
||||
extern void close_chan(struct list_head *chans, int delay_free_irq);
|
||||
extern int chan_window_size(struct list_head *chans,
|
||||
extern void close_chan(struct line *line);
|
||||
extern int chan_window_size(struct line *line,
|
||||
unsigned short *rows_out,
|
||||
unsigned short *cols_out);
|
||||
extern int chan_config_string(struct list_head *chans, char *str, int size,
|
||||
extern int chan_config_string(struct line *line, char *str, int size,
|
||||
char **error_out);
|
||||
|
||||
#endif
|
||||
|
@@ -140,18 +140,18 @@ static int open_chan(struct list_head *chans)
|
||||
return err;
|
||||
}
|
||||
|
||||
void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
|
||||
void chan_enable_winch(struct chan *chan, struct tty_struct *tty)
|
||||
{
|
||||
struct list_head *ele;
|
||||
struct chan *chan;
|
||||
if (chan && chan->primary && chan->ops->winch)
|
||||
register_winch(chan->fd, tty);
|
||||
}
|
||||
|
||||
list_for_each(ele, chans) {
|
||||
chan = list_entry(ele, struct chan, list);
|
||||
if (chan->primary && chan->output && chan->ops->winch) {
|
||||
register_winch(chan->fd, tty);
|
||||
return;
|
||||
}
|
||||
}
|
||||
static void line_timer_cb(struct work_struct *work)
|
||||
{
|
||||
struct line *line = container_of(work, struct line, task.work);
|
||||
|
||||
if (!line->throttled)
|
||||
chan_interrupt(line, line->tty, line->driver->read_irq);
|
||||
}
|
||||
|
||||
int enable_chan(struct line *line)
|
||||
@@ -160,6 +160,8 @@ int enable_chan(struct line *line)
|
||||
struct chan *chan;
|
||||
int err;
|
||||
|
||||
INIT_DELAYED_WORK(&line->task, line_timer_cb);
|
||||
|
||||
list_for_each(ele, &line->chan_list) {
|
||||
chan = list_entry(ele, struct chan, list);
|
||||
err = open_one_chan(chan);
|
||||
@@ -183,7 +185,7 @@ int enable_chan(struct line *line)
|
||||
return 0;
|
||||
|
||||
out_close:
|
||||
close_chan(&line->chan_list, 0);
|
||||
close_chan(line);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -244,7 +246,7 @@ static void close_one_chan(struct chan *chan, int delay_free_irq)
|
||||
chan->fd = -1;
|
||||
}
|
||||
|
||||
void close_chan(struct list_head *chans, int delay_free_irq)
|
||||
void close_chan(struct line *line)
|
||||
{
|
||||
struct chan *chan;
|
||||
|
||||
@@ -253,77 +255,50 @@ void close_chan(struct list_head *chans, int delay_free_irq)
|
||||
* state. Then, the first one opened will have the original state,
|
||||
* so it must be the last closed.
|
||||
*/
|
||||
list_for_each_entry_reverse(chan, chans, list) {
|
||||
close_one_chan(chan, delay_free_irq);
|
||||
list_for_each_entry_reverse(chan, &line->chan_list, list) {
|
||||
close_one_chan(chan, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void deactivate_chan(struct list_head *chans, int irq)
|
||||
void deactivate_chan(struct chan *chan, 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);
|
||||
}
|
||||
if (chan && chan->enabled)
|
||||
deactivate_fd(chan->fd, irq);
|
||||
}
|
||||
|
||||
void reactivate_chan(struct list_head *chans, int irq)
|
||||
void reactivate_chan(struct chan *chan, 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);
|
||||
}
|
||||
if (chan && chan->enabled)
|
||||
reactivate_fd(chan->fd, irq);
|
||||
}
|
||||
|
||||
int write_chan(struct list_head *chans, const char *buf, int len,
|
||||
int write_chan(struct chan *chan, const char *buf, int len,
|
||||
int write_irq)
|
||||
{
|
||||
struct list_head *ele;
|
||||
struct chan *chan = NULL;
|
||||
int n, ret = 0;
|
||||
|
||||
if (len == 0)
|
||||
if (len == 0 || !chan || !chan->ops->write)
|
||||
return 0;
|
||||
|
||||
list_for_each(ele, chans) {
|
||||
chan = list_entry(ele, struct chan, list);
|
||||
if (!chan->output || (chan->ops->write == NULL))
|
||||
continue;
|
||||
|
||||
n = chan->ops->write(chan->fd, buf, len, chan->data);
|
||||
if (chan->primary) {
|
||||
ret = n;
|
||||
if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len)))
|
||||
reactivate_fd(chan->fd, write_irq);
|
||||
}
|
||||
n = chan->ops->write(chan->fd, buf, len, chan->data);
|
||||
if (chan->primary) {
|
||||
ret = n;
|
||||
if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len)))
|
||||
reactivate_fd(chan->fd, write_irq);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int console_write_chan(struct list_head *chans, const char *buf, int len)
|
||||
int console_write_chan(struct chan *chan, const char *buf, int len)
|
||||
{
|
||||
struct list_head *ele;
|
||||
struct chan *chan;
|
||||
int n, ret = 0;
|
||||
|
||||
list_for_each(ele, chans) {
|
||||
chan = list_entry(ele, struct chan, list);
|
||||
if (!chan->output || (chan->ops->console_write == NULL))
|
||||
continue;
|
||||
if (!chan || !chan->ops->console_write)
|
||||
return 0;
|
||||
|
||||
n = chan->ops->console_write(chan->fd, buf, len);
|
||||
if (chan->primary)
|
||||
ret = n;
|
||||
}
|
||||
n = chan->ops->console_write(chan->fd, buf, len);
|
||||
if (chan->primary)
|
||||
ret = n;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -340,20 +315,24 @@ int console_open_chan(struct line *line, struct console *co)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chan_window_size(struct list_head *chans, unsigned short *rows_out,
|
||||
int chan_window_size(struct line *line, unsigned short *rows_out,
|
||||
unsigned short *cols_out)
|
||||
{
|
||||
struct list_head *ele;
|
||||
struct chan *chan;
|
||||
|
||||
list_for_each(ele, chans) {
|
||||
chan = list_entry(ele, struct chan, list);
|
||||
if (chan->primary) {
|
||||
if (chan->ops->window_size == NULL)
|
||||
return 0;
|
||||
return chan->ops->window_size(chan->fd, chan->data,
|
||||
rows_out, cols_out);
|
||||
}
|
||||
chan = line->chan_in;
|
||||
if (chan && chan->primary) {
|
||||
if (chan->ops->window_size == NULL)
|
||||
return 0;
|
||||
return chan->ops->window_size(chan->fd, chan->data,
|
||||
rows_out, cols_out);
|
||||
}
|
||||
chan = line->chan_out;
|
||||
if (chan && chan->primary) {
|
||||
if (chan->ops->window_size == NULL)
|
||||
return 0;
|
||||
return chan->ops->window_size(chan->fd, chan->data,
|
||||
rows_out, cols_out);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -429,21 +408,15 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
|
||||
return n;
|
||||
}
|
||||
|
||||
int chan_config_string(struct list_head *chans, char *str, int size,
|
||||
int chan_config_string(struct line *line, char *str, int size,
|
||||
char **error_out)
|
||||
{
|
||||
struct list_head *ele;
|
||||
struct chan *chan, *in = NULL, *out = NULL;
|
||||
struct chan *in = line->chan_in, *out = line->chan_out;
|
||||
|
||||
list_for_each(ele, chans) {
|
||||
chan = list_entry(ele, struct chan, list);
|
||||
if (!chan->primary)
|
||||
continue;
|
||||
if (chan->input)
|
||||
in = chan;
|
||||
if (chan->output)
|
||||
out = chan;
|
||||
}
|
||||
if (in && !in->primary)
|
||||
in = NULL;
|
||||
if (out && !out->primary)
|
||||
out = NULL;
|
||||
|
||||
return chan_pair_config_string(in, out, str, size, error_out);
|
||||
}
|
||||
@@ -547,10 +520,14 @@ int parse_chan_pair(char *str, struct line *line, int device,
|
||||
char *in, *out;
|
||||
|
||||
if (!list_empty(chans)) {
|
||||
line->chan_in = line->chan_out = NULL;
|
||||
free_chan(chans);
|
||||
INIT_LIST_HEAD(chans);
|
||||
}
|
||||
|
||||
if (!str)
|
||||
return 0;
|
||||
|
||||
out = strchr(str, ',');
|
||||
if (out != NULL) {
|
||||
in = str;
|
||||
@@ -562,6 +539,7 @@ int parse_chan_pair(char *str, struct line *line, int device,
|
||||
|
||||
new->input = 1;
|
||||
list_add(&new->list, chans);
|
||||
line->chan_in = new;
|
||||
|
||||
new = parse_chan(line, out, device, opts, error_out);
|
||||
if (new == NULL)
|
||||
@@ -569,6 +547,7 @@ int parse_chan_pair(char *str, struct line *line, int device,
|
||||
|
||||
list_add(&new->list, chans);
|
||||
new->output = 1;
|
||||
line->chan_out = new;
|
||||
}
|
||||
else {
|
||||
new = parse_chan(line, str, device, opts, error_out);
|
||||
@@ -578,43 +557,42 @@ int parse_chan_pair(char *str, struct line *line, int device,
|
||||
list_add(&new->list, chans);
|
||||
new->input = 1;
|
||||
new->output = 1;
|
||||
line->chan_in = line->chan_out = new;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void chan_interrupt(struct list_head *chans, struct delayed_work *task,
|
||||
struct tty_struct *tty, int irq)
|
||||
void chan_interrupt(struct line *line, struct tty_struct *tty, int irq)
|
||||
{
|
||||
struct list_head *ele, *next;
|
||||
struct chan *chan;
|
||||
struct chan *chan = line->chan_in;
|
||||
int err;
|
||||
char c;
|
||||
|
||||
list_for_each_safe(ele, next, chans) {
|
||||
chan = list_entry(ele, struct chan, list);
|
||||
if (!chan->input || (chan->ops->read == NULL))
|
||||
continue;
|
||||
do {
|
||||
if (tty && !tty_buffer_request_room(tty, 1)) {
|
||||
schedule_delayed_work(task, 1);
|
||||
goto out;
|
||||
}
|
||||
err = chan->ops->read(chan->fd, &c, chan->data);
|
||||
if (err > 0)
|
||||
tty_receive_char(tty, c);
|
||||
} while (err > 0);
|
||||
if (!chan || !chan->ops->read)
|
||||
goto out;
|
||||
|
||||
if (err == 0)
|
||||
reactivate_fd(chan->fd, irq);
|
||||
if (err == -EIO) {
|
||||
if (chan->primary) {
|
||||
if (tty != NULL)
|
||||
tty_hangup(tty);
|
||||
close_chan(chans, 1);
|
||||
return;
|
||||
}
|
||||
else close_one_chan(chan, 1);
|
||||
do {
|
||||
if (tty && !tty_buffer_request_room(tty, 1)) {
|
||||
schedule_delayed_work(&line->task, 1);
|
||||
goto out;
|
||||
}
|
||||
err = chan->ops->read(chan->fd, &c, chan->data);
|
||||
if (err > 0)
|
||||
tty_receive_char(tty, c);
|
||||
} while (err > 0);
|
||||
|
||||
if (err == 0)
|
||||
reactivate_fd(chan->fd, irq);
|
||||
if (err == -EIO) {
|
||||
if (chan->primary) {
|
||||
if (tty != NULL)
|
||||
tty_hangup(tty);
|
||||
if (line->chan_out != chan)
|
||||
close_one_chan(line->chan_out, 1);
|
||||
}
|
||||
close_one_chan(chan, 1);
|
||||
if (chan->primary)
|
||||
return;
|
||||
}
|
||||
out:
|
||||
if (tty)
|
||||
|
@@ -14,8 +14,6 @@ struct chan_opts {
|
||||
const int raw;
|
||||
};
|
||||
|
||||
enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
|
||||
|
||||
struct chan_ops {
|
||||
char *type;
|
||||
void *(*init)(char *, int, const struct chan_opts *);
|
||||
|
@@ -21,19 +21,10 @@ static irqreturn_t line_interrupt(int irq, void *data)
|
||||
struct line *line = chan->line;
|
||||
|
||||
if (line)
|
||||
chan_interrupt(&line->chan_list, &line->task, line->tty, irq);
|
||||
chan_interrupt(line, line->tty, irq);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void line_timer_cb(struct work_struct *work)
|
||||
{
|
||||
struct line *line = container_of(work, struct line, task.work);
|
||||
|
||||
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.
|
||||
*
|
||||
@@ -145,7 +136,7 @@ static int flush_buffer(struct line *line)
|
||||
/* line->buffer + LINE_BUFSIZE is the end of the buffer! */
|
||||
count = line->buffer + LINE_BUFSIZE - line->head;
|
||||
|
||||
n = write_chan(&line->chan_list, line->head, count,
|
||||
n = write_chan(line->chan_out, line->head, count,
|
||||
line->driver->write_irq);
|
||||
if (n < 0)
|
||||
return n;
|
||||
@@ -162,7 +153,7 @@ static int flush_buffer(struct line *line)
|
||||
}
|
||||
|
||||
count = line->tail - line->head;
|
||||
n = write_chan(&line->chan_list, line->head, count,
|
||||
n = write_chan(line->chan_out, line->head, count,
|
||||
line->driver->write_irq);
|
||||
|
||||
if (n < 0)
|
||||
@@ -206,7 +197,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
|
||||
if (line->head != line->tail)
|
||||
ret = buffer_data(line, buf, len);
|
||||
else {
|
||||
n = write_chan(&line->chan_list, buf, len,
|
||||
n = write_chan(line->chan_out, buf, len,
|
||||
line->driver->write_irq);
|
||||
if (n < 0) {
|
||||
ret = n;
|
||||
@@ -318,7 +309,7 @@ void line_throttle(struct tty_struct *tty)
|
||||
{
|
||||
struct line *line = tty->driver_data;
|
||||
|
||||
deactivate_chan(&line->chan_list, line->driver->read_irq);
|
||||
deactivate_chan(line->chan_in, line->driver->read_irq);
|
||||
line->throttled = 1;
|
||||
}
|
||||
|
||||
@@ -327,8 +318,7 @@ 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);
|
||||
chan_interrupt(line, tty, line->driver->read_irq);
|
||||
|
||||
/*
|
||||
* Maybe there is enough stuff pending that calling the interrupt
|
||||
@@ -336,7 +326,7 @@ void line_unthrottle(struct tty_struct *tty)
|
||||
* again and we shouldn't turn the interrupt back on.
|
||||
*/
|
||||
if (!line->throttled)
|
||||
reactivate_chan(&line->chan_list, line->driver->read_irq);
|
||||
reactivate_chan(line->chan_in, line->driver->read_irq);
|
||||
}
|
||||
|
||||
static irqreturn_t line_write_interrupt(int irq, void *data)
|
||||
@@ -347,13 +337,14 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Interrupts are disabled here because we registered the interrupt with
|
||||
* IRQF_DISABLED (see line_setup_irq).
|
||||
* Interrupts are disabled here because genirq keep irqs disabled when
|
||||
* calling the action handler.
|
||||
*/
|
||||
|
||||
spin_lock(&line->lock);
|
||||
err = flush_buffer(line);
|
||||
if (err == 0) {
|
||||
spin_unlock(&line->lock);
|
||||
return IRQ_NONE;
|
||||
} else if (err < 0) {
|
||||
line->head = line->buffer;
|
||||
@@ -371,7 +362,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
|
||||
int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
|
||||
{
|
||||
const struct line_driver *driver = line->driver;
|
||||
int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM;
|
||||
int err = 0, flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM;
|
||||
|
||||
if (input)
|
||||
err = um_request_irq(driver->read_irq, fd, IRQ_READ,
|
||||
@@ -383,7 +374,6 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
|
||||
err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
|
||||
line_write_interrupt, flags,
|
||||
driver->write_irq_name, data);
|
||||
line->have_irq = 1;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -409,7 +399,7 @@ int line_open(struct line *lines, struct tty_struct *tty)
|
||||
struct line *line = &lines[tty->index];
|
||||
int err = -ENODEV;
|
||||
|
||||
spin_lock(&line->count_lock);
|
||||
mutex_lock(&line->count_lock);
|
||||
if (!line->valid)
|
||||
goto out_unlock;
|
||||
|
||||
@@ -421,25 +411,19 @@ int line_open(struct line *lines, struct tty_struct *tty)
|
||||
tty->driver_data = line;
|
||||
line->tty = tty;
|
||||
|
||||
spin_unlock(&line->count_lock);
|
||||
err = enable_chan(line);
|
||||
if (err) /* line_close() will be called by our caller */
|
||||
return err;
|
||||
|
||||
INIT_DELAYED_WORK(&line->task, line_timer_cb);
|
||||
goto out_unlock;
|
||||
|
||||
if (!line->sigio) {
|
||||
chan_enable_winch(&line->chan_list, tty);
|
||||
chan_enable_winch(line->chan_out, tty);
|
||||
line->sigio = 1;
|
||||
}
|
||||
|
||||
chan_window_size(&line->chan_list, &tty->winsize.ws_row,
|
||||
chan_window_size(line, &tty->winsize.ws_row,
|
||||
&tty->winsize.ws_col);
|
||||
|
||||
return 0;
|
||||
|
||||
out_unlock:
|
||||
spin_unlock(&line->count_lock);
|
||||
mutex_unlock(&line->count_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -459,7 +443,7 @@ void line_close(struct tty_struct *tty, struct file * filp)
|
||||
/* We ignore the error anyway! */
|
||||
flush_buffer(line);
|
||||
|
||||
spin_lock(&line->count_lock);
|
||||
mutex_lock(&line->count_lock);
|
||||
BUG_ON(!line->valid);
|
||||
|
||||
if (--line->count)
|
||||
@@ -468,17 +452,13 @@ void line_close(struct tty_struct *tty, struct file * filp)
|
||||
line->tty = NULL;
|
||||
tty->driver_data = NULL;
|
||||
|
||||
spin_unlock(&line->count_lock);
|
||||
|
||||
if (line->sigio) {
|
||||
unregister_winch(tty);
|
||||
line->sigio = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
out_unlock:
|
||||
spin_unlock(&line->count_lock);
|
||||
mutex_unlock(&line->count_lock);
|
||||
}
|
||||
|
||||
void close_lines(struct line *lines, int nlines)
|
||||
@@ -486,34 +466,60 @@ void close_lines(struct line *lines, int nlines)
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nlines; i++)
|
||||
close_chan(&lines[i].chan_list, 0);
|
||||
close_chan(&lines[i]);
|
||||
}
|
||||
|
||||
static int setup_one_line(struct line *lines, int n, char *init, int init_prio,
|
||||
char **error_out)
|
||||
int setup_one_line(struct line *lines, int n, char *init,
|
||||
const struct chan_opts *opts, char **error_out)
|
||||
{
|
||||
struct line *line = &lines[n];
|
||||
struct tty_driver *driver = line->driver->driver;
|
||||
int err = -EINVAL;
|
||||
|
||||
spin_lock(&line->count_lock);
|
||||
mutex_lock(&line->count_lock);
|
||||
|
||||
if (line->count) {
|
||||
*error_out = "Device is already open";
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (line->init_pri <= init_prio) {
|
||||
line->init_pri = init_prio;
|
||||
if (!strcmp(init, "none"))
|
||||
if (!strcmp(init, "none")) {
|
||||
if (line->valid) {
|
||||
line->valid = 0;
|
||||
else {
|
||||
line->init_str = init;
|
||||
line->valid = 1;
|
||||
kfree(line->init_str);
|
||||
tty_unregister_device(driver, n);
|
||||
parse_chan_pair(NULL, line, n, opts, error_out);
|
||||
err = 0;
|
||||
}
|
||||
} else {
|
||||
char *new = kstrdup(init, GFP_KERNEL);
|
||||
if (!new) {
|
||||
*error_out = "Failed to allocate memory";
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (line->valid) {
|
||||
tty_unregister_device(driver, n);
|
||||
kfree(line->init_str);
|
||||
}
|
||||
line->init_str = new;
|
||||
line->valid = 1;
|
||||
err = parse_chan_pair(new, line, n, opts, error_out);
|
||||
if (!err) {
|
||||
struct device *d = tty_register_device(driver, n, NULL);
|
||||
if (IS_ERR(d)) {
|
||||
*error_out = "Failed to register device";
|
||||
err = PTR_ERR(d);
|
||||
parse_chan_pair(NULL, line, n, opts, error_out);
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
line->init_str = NULL;
|
||||
line->valid = 0;
|
||||
kfree(new);
|
||||
}
|
||||
}
|
||||
err = 0;
|
||||
out:
|
||||
spin_unlock(&line->count_lock);
|
||||
mutex_unlock(&line->count_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -524,54 +530,43 @@ out:
|
||||
* @error_out is an error string in the case of failure;
|
||||
*/
|
||||
|
||||
int line_setup(struct line *lines, unsigned int num, char *init,
|
||||
char **error_out)
|
||||
int line_setup(char **conf, unsigned int num, char **def,
|
||||
char *init, char *name)
|
||||
{
|
||||
int i, n, err;
|
||||
char *end;
|
||||
char *error;
|
||||
|
||||
if (*init == '=') {
|
||||
/*
|
||||
* We said con=/ssl= instead of con#=, so we are configuring all
|
||||
* consoles at once.
|
||||
*/
|
||||
n = -1;
|
||||
}
|
||||
else {
|
||||
n = simple_strtoul(init, &end, 0);
|
||||
if (*end != '=') {
|
||||
*error_out = "Couldn't parse device number";
|
||||
return -EINVAL;
|
||||
}
|
||||
init = end;
|
||||
}
|
||||
init++;
|
||||
*def = init + 1;
|
||||
} else {
|
||||
char *end;
|
||||
unsigned n = simple_strtoul(init, &end, 0);
|
||||
|
||||
if (n >= (signed int) num) {
|
||||
*error_out = "Device number out of range";
|
||||
return -EINVAL;
|
||||
}
|
||||
else if (n >= 0) {
|
||||
err = setup_one_line(lines, n, init, INIT_ONE, error_out);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
else {
|
||||
for(i = 0; i < num; i++) {
|
||||
err = setup_one_line(lines, i, init, INIT_ALL,
|
||||
error_out);
|
||||
if (err)
|
||||
return err;
|
||||
if (*end != '=') {
|
||||
error = "Couldn't parse device number";
|
||||
goto out;
|
||||
}
|
||||
if (n >= num) {
|
||||
error = "Device number out of range";
|
||||
goto out;
|
||||
}
|
||||
conf[n] = end + 1;
|
||||
}
|
||||
return n == -1 ? num : n;
|
||||
return 0;
|
||||
|
||||
out:
|
||||
printk(KERN_ERR "Failed to set up %s with "
|
||||
"configuration string \"%s\" : %s\n", name, init, error);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int line_config(struct line *lines, unsigned int num, char *str,
|
||||
const struct chan_opts *opts, char **error_out)
|
||||
{
|
||||
struct line *line;
|
||||
char *new;
|
||||
char *end;
|
||||
int n;
|
||||
|
||||
if (*str == '=') {
|
||||
@@ -579,17 +574,17 @@ int line_config(struct line *lines, unsigned int num, char *str,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
new = kstrdup(str, GFP_KERNEL);
|
||||
if (new == NULL) {
|
||||
*error_out = "Failed to allocate memory";
|
||||
return -ENOMEM;
|
||||
n = simple_strtoul(str, &end, 0);
|
||||
if (*end++ != '=') {
|
||||
*error_out = "Couldn't parse device number";
|
||||
return -EINVAL;
|
||||
}
|
||||
if (n >= num) {
|
||||
*error_out = "Device number out of range";
|
||||
return -EINVAL;
|
||||
}
|
||||
n = line_setup(lines, num, new, error_out);
|
||||
if (n < 0)
|
||||
return n;
|
||||
|
||||
line = &lines[n];
|
||||
return parse_chan_pair(line->init_str, line, n, opts, error_out);
|
||||
return setup_one_line(lines, n, end, opts, error_out);
|
||||
}
|
||||
|
||||
int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
|
||||
@@ -612,13 +607,13 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
|
||||
|
||||
line = &lines[dev];
|
||||
|
||||
spin_lock(&line->count_lock);
|
||||
mutex_lock(&line->count_lock);
|
||||
if (!line->valid)
|
||||
CONFIG_CHUNK(str, size, n, "none", 1);
|
||||
else if (line->tty == NULL)
|
||||
CONFIG_CHUNK(str, size, n, line->init_str, 1);
|
||||
else n = chan_config_string(&line->chan_list, str, size, error_out);
|
||||
spin_unlock(&line->count_lock);
|
||||
else n = chan_config_string(line, str, size, error_out);
|
||||
mutex_unlock(&line->count_lock);
|
||||
|
||||
return n;
|
||||
}
|
||||
@@ -640,25 +635,23 @@ int line_id(char **str, int *start_out, int *end_out)
|
||||
|
||||
int line_remove(struct line *lines, unsigned int num, int n, char **error_out)
|
||||
{
|
||||
int err;
|
||||
char config[sizeof("conxxxx=none\0")];
|
||||
|
||||
sprintf(config, "%d=none", n);
|
||||
err = line_setup(lines, num, config, error_out);
|
||||
if (err >= 0)
|
||||
err = 0;
|
||||
return err;
|
||||
if (n >= num) {
|
||||
*error_out = "Device number out of range";
|
||||
return -EINVAL;
|
||||
}
|
||||
return setup_one_line(lines, n, "none", NULL, error_out);
|
||||
}
|
||||
|
||||
struct tty_driver *register_lines(struct line_driver *line_driver,
|
||||
const struct tty_operations *ops,
|
||||
struct line *lines, int nlines)
|
||||
int register_lines(struct line_driver *line_driver,
|
||||
const struct tty_operations *ops,
|
||||
struct line *lines, int nlines)
|
||||
{
|
||||
int i;
|
||||
struct tty_driver *driver = alloc_tty_driver(nlines);
|
||||
int err;
|
||||
int i;
|
||||
|
||||
if (!driver)
|
||||
return NULL;
|
||||
return -ENOMEM;
|
||||
|
||||
driver->driver_name = line_driver->name;
|
||||
driver->name = line_driver->device_name;
|
||||
@@ -666,54 +659,33 @@ struct tty_driver *register_lines(struct line_driver *line_driver,
|
||||
driver->minor_start = line_driver->minor_start;
|
||||
driver->type = line_driver->type;
|
||||
driver->subtype = line_driver->subtype;
|
||||
driver->flags = TTY_DRIVER_REAL_RAW;
|
||||
driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
driver->init_termios = tty_std_termios;
|
||||
|
||||
for (i = 0; i < nlines; i++) {
|
||||
spin_lock_init(&lines[i].lock);
|
||||
mutex_init(&lines[i].count_lock);
|
||||
lines[i].driver = line_driver;
|
||||
INIT_LIST_HEAD(&lines[i].chan_list);
|
||||
}
|
||||
tty_set_operations(driver, ops);
|
||||
|
||||
if (tty_register_driver(driver)) {
|
||||
err = tty_register_driver(driver);
|
||||
if (err) {
|
||||
printk(KERN_ERR "register_lines : can't register %s driver\n",
|
||||
line_driver->name);
|
||||
put_tty_driver(driver);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i = 0; i < nlines; i++) {
|
||||
if (!lines[i].valid)
|
||||
tty_unregister_device(driver, i);
|
||||
return err;
|
||||
}
|
||||
|
||||
line_driver->driver = driver;
|
||||
mconsole_register_dev(&line_driver->mc);
|
||||
return driver;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(winch_handler_lock);
|
||||
static LIST_HEAD(winch_handlers);
|
||||
|
||||
void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
|
||||
{
|
||||
struct line *line;
|
||||
char *error;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nlines; i++) {
|
||||
line = &lines[i];
|
||||
INIT_LIST_HEAD(&line->chan_list);
|
||||
|
||||
if (line->init_str == NULL)
|
||||
continue;
|
||||
|
||||
line->init_str = kstrdup(line->init_str, GFP_KERNEL);
|
||||
if (line->init_str == NULL)
|
||||
printk(KERN_ERR "lines_init - kstrdup returned NULL\n");
|
||||
|
||||
if (parse_chan_pair(line->init_str, line, i, opts, &error)) {
|
||||
printk(KERN_ERR "parse_chan_pair failed for "
|
||||
"device %d : %s\n", i, error);
|
||||
line->valid = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct winch {
|
||||
struct list_head list;
|
||||
int fd;
|
||||
@@ -777,7 +749,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
|
||||
if (tty != NULL) {
|
||||
line = tty->driver_data;
|
||||
if (line != NULL) {
|
||||
chan_window_size(&line->chan_list, &tty->winsize.ws_row,
|
||||
chan_window_size(line, &tty->winsize.ws_row,
|
||||
&tty->winsize.ws_col);
|
||||
kill_pgrp(tty->pgrp, SIGWINCH, 1);
|
||||
}
|
||||
@@ -807,7 +779,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
|
||||
.stack = stack });
|
||||
|
||||
if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
|
||||
IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
|
||||
IRQF_SHARED | IRQF_SAMPLE_RANDOM,
|
||||
"winch", winch) < 0) {
|
||||
printk(KERN_ERR "register_winch_irq - failed to register "
|
||||
"IRQ\n");
|
||||
|
@@ -15,7 +15,7 @@
|
||||
#include "chan_user.h"
|
||||
#include "mconsole_kern.h"
|
||||
|
||||
/* There's only one modifiable field in this - .mc.list */
|
||||
/* There's only two modifiable fields in this - .mc.list and .driver */
|
||||
struct line_driver {
|
||||
const char *name;
|
||||
const char *device_name;
|
||||
@@ -28,17 +28,18 @@ struct line_driver {
|
||||
const int write_irq;
|
||||
const char *write_irq_name;
|
||||
struct mc_device mc;
|
||||
struct tty_driver *driver;
|
||||
};
|
||||
|
||||
struct line {
|
||||
struct tty_struct *tty;
|
||||
spinlock_t count_lock;
|
||||
struct mutex count_lock;
|
||||
unsigned long count;
|
||||
int valid;
|
||||
|
||||
char *init_str;
|
||||
int init_pri;
|
||||
struct list_head chan_list;
|
||||
struct chan *chan_in, *chan_out;
|
||||
|
||||
/*This lock is actually, mostly, local to*/
|
||||
spinlock_t lock;
|
||||
@@ -55,21 +56,12 @@ struct line {
|
||||
int sigio;
|
||||
struct delayed_work task;
|
||||
const struct line_driver *driver;
|
||||
int have_irq;
|
||||
};
|
||||
|
||||
#define LINE_INIT(str, d) \
|
||||
{ .count_lock = __SPIN_LOCK_UNLOCKED((str).count_lock), \
|
||||
.init_str = str, \
|
||||
.init_pri = INIT_STATIC, \
|
||||
.valid = 1, \
|
||||
.lock = __SPIN_LOCK_UNLOCKED((str).lock), \
|
||||
.driver = d }
|
||||
|
||||
extern void line_close(struct tty_struct *tty, struct file * filp);
|
||||
extern int line_open(struct line *lines, struct tty_struct *tty);
|
||||
extern int line_setup(struct line *lines, unsigned int sizeof_lines,
|
||||
char *init, char **error_out);
|
||||
extern int line_setup(char **conf, unsigned nlines, char **def,
|
||||
char *init, char *name);
|
||||
extern int line_write(struct tty_struct *tty, const unsigned char *buf,
|
||||
int len);
|
||||
extern int line_put_char(struct tty_struct *tty, unsigned char ch);
|
||||
@@ -87,10 +79,11 @@ extern char *add_xterm_umid(char *base);
|
||||
extern int line_setup_irq(int fd, int input, int output, struct line *line,
|
||||
void *data);
|
||||
extern void line_close_chan(struct line *line);
|
||||
extern struct tty_driver *register_lines(struct line_driver *line_driver,
|
||||
const struct tty_operations *driver,
|
||||
struct line *lines, int nlines);
|
||||
extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
|
||||
extern int register_lines(struct line_driver *line_driver,
|
||||
const struct tty_operations *driver,
|
||||
struct line *lines, int nlines);
|
||||
extern int setup_one_line(struct line *lines, int n, char *init,
|
||||
const struct chan_opts *opts, char **error_out);
|
||||
extern void close_lines(struct line *lines, int nlines);
|
||||
|
||||
extern int line_config(struct line *lines, unsigned int sizeof_lines,
|
||||
|
@@ -773,7 +773,7 @@ static int __init mconsole_init(void)
|
||||
register_reboot_notifier(&reboot_notifier);
|
||||
|
||||
err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt,
|
||||
IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
|
||||
IRQF_SHARED | IRQF_SAMPLE_RANDOM,
|
||||
"mconsole", (void *)sock);
|
||||
if (err) {
|
||||
printk(KERN_ERR "Failed to get IRQ for management console\n");
|
||||
|
@@ -161,7 +161,7 @@ static int uml_net_open(struct net_device *dev)
|
||||
}
|
||||
|
||||
err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt,
|
||||
IRQF_DISABLED | IRQF_SHARED, dev->name, dev);
|
||||
IRQF_SHARED, dev->name, dev);
|
||||
if (err != 0) {
|
||||
printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err);
|
||||
err = -ENETUNREACH;
|
||||
|
@@ -100,7 +100,7 @@ static int port_accept(struct port_list *port)
|
||||
.port = port });
|
||||
|
||||
if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt,
|
||||
IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
|
||||
IRQF_SHARED | IRQF_SAMPLE_RANDOM,
|
||||
"telnetd", conn)) {
|
||||
printk(KERN_ERR "port_accept : failed to get IRQ for "
|
||||
"telnetd\n");
|
||||
@@ -184,7 +184,7 @@ void *port_data(int port_num)
|
||||
}
|
||||
|
||||
if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt,
|
||||
IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
|
||||
IRQF_SHARED | IRQF_SAMPLE_RANDOM,
|
||||
"port", port)) {
|
||||
printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num);
|
||||
goto out_close;
|
||||
|
@@ -131,7 +131,7 @@ static int __init rng_init (void)
|
||||
random_fd = err;
|
||||
|
||||
err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,
|
||||
IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random",
|
||||
IRQF_SAMPLE_RANDOM, "random",
|
||||
NULL);
|
||||
if (err)
|
||||
goto err_out_cleanup_hw;
|
||||
|
@@ -20,12 +20,6 @@
|
||||
|
||||
static const int ssl_version = 1;
|
||||
|
||||
/* Referenced only by tty_driver below - presumably it's locked correctly
|
||||
* by the tty driver.
|
||||
*/
|
||||
|
||||
static struct tty_driver *ssl_driver;
|
||||
|
||||
#define NR_PORTS 64
|
||||
|
||||
static void ssl_announce(char *dev_name, int dev)
|
||||
@@ -71,8 +65,9 @@ static struct line_driver driver = {
|
||||
/* The array is initialized by line_init, at initcall time. The
|
||||
* elements are locked individually as needed.
|
||||
*/
|
||||
static struct line serial_lines[NR_PORTS] =
|
||||
{ [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) };
|
||||
static char *conf[NR_PORTS];
|
||||
static char *def_conf = CONFIG_SSL_CHAN;
|
||||
static struct line serial_lines[NR_PORTS];
|
||||
|
||||
static int ssl_config(char *str, char **error_out)
|
||||
{
|
||||
@@ -156,14 +151,14 @@ static void ssl_console_write(struct console *c, const char *string,
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&line->lock, flags);
|
||||
console_write_chan(&line->chan_list, string, len);
|
||||
console_write_chan(line->chan_out, string, len);
|
||||
spin_unlock_irqrestore(&line->lock, flags);
|
||||
}
|
||||
|
||||
static struct tty_driver *ssl_console_device(struct console *c, int *index)
|
||||
{
|
||||
*index = c->index;
|
||||
return ssl_driver;
|
||||
return driver.driver;
|
||||
}
|
||||
|
||||
static int ssl_console_setup(struct console *co, char *options)
|
||||
@@ -186,17 +181,30 @@ static struct console ssl_cons = {
|
||||
static int ssl_init(void)
|
||||
{
|
||||
char *new_title;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
printk(KERN_INFO "Initializing software serial port version %d\n",
|
||||
ssl_version);
|
||||
ssl_driver = register_lines(&driver, &ssl_ops, serial_lines,
|
||||
|
||||
err = register_lines(&driver, &ssl_ops, serial_lines,
|
||||
ARRAY_SIZE(serial_lines));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
new_title = add_xterm_umid(opts.xterm_title);
|
||||
if (new_title != NULL)
|
||||
opts.xterm_title = new_title;
|
||||
|
||||
lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
|
||||
for (i = 0; i < NR_PORTS; i++) {
|
||||
char *error;
|
||||
char *s = conf[i];
|
||||
if (!s)
|
||||
s = def_conf;
|
||||
if (setup_one_line(serial_lines, i, s, &opts, &error))
|
||||
printk(KERN_ERR "setup_one_line failed for "
|
||||
"device %d : %s\n", i, error);
|
||||
}
|
||||
|
||||
ssl_init_done = 1;
|
||||
register_console(&ssl_cons);
|
||||
@@ -214,14 +222,7 @@ __uml_exitcall(ssl_exit);
|
||||
|
||||
static int ssl_chan_setup(char *str)
|
||||
{
|
||||
char *error;
|
||||
int ret;
|
||||
|
||||
ret = line_setup(serial_lines, ARRAY_SIZE(serial_lines), str, &error);
|
||||
if(ret < 0)
|
||||
printk(KERN_ERR "Failed to set up serial line with "
|
||||
"configuration string \"%s\" : %s\n", str, error);
|
||||
|
||||
line_setup(conf, NR_PORTS, &def_conf, str, "serial line");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -27,12 +27,6 @@
|
||||
|
||||
#define MAX_TTYS (16)
|
||||
|
||||
/* Referenced only by tty_driver below - presumably it's locked correctly
|
||||
* by the tty driver.
|
||||
*/
|
||||
|
||||
static struct tty_driver *console_driver;
|
||||
|
||||
static void stdio_announce(char *dev_name, int dev)
|
||||
{
|
||||
printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev,
|
||||
@@ -76,9 +70,9 @@ static struct line_driver driver = {
|
||||
/* The array is initialized by line_init, at initcall time. The
|
||||
* elements are locked individually as needed.
|
||||
*/
|
||||
static struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
|
||||
[ 1 ... MAX_TTYS - 1 ] =
|
||||
LINE_INIT(CONFIG_CON_CHAN, &driver) };
|
||||
static char *vt_conf[MAX_TTYS];
|
||||
static char *def_conf;
|
||||
static struct line vts[MAX_TTYS];
|
||||
|
||||
static int con_config(char *str, char **error_out)
|
||||
{
|
||||
@@ -130,14 +124,14 @@ static void uml_console_write(struct console *console, const char *string,
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&line->lock, flags);
|
||||
console_write_chan(&line->chan_list, string, len);
|
||||
console_write_chan(line->chan_out, string, len);
|
||||
spin_unlock_irqrestore(&line->lock, flags);
|
||||
}
|
||||
|
||||
static struct tty_driver *uml_console_device(struct console *c, int *index)
|
||||
{
|
||||
*index = c->index;
|
||||
return console_driver;
|
||||
return driver.driver;
|
||||
}
|
||||
|
||||
static int uml_console_setup(struct console *co, char *options)
|
||||
@@ -160,18 +154,31 @@ static struct console stdiocons = {
|
||||
static int stdio_init(void)
|
||||
{
|
||||
char *new_title;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
console_driver = register_lines(&driver, &console_ops, vts,
|
||||
err = register_lines(&driver, &console_ops, vts,
|
||||
ARRAY_SIZE(vts));
|
||||
if (console_driver == NULL)
|
||||
return -1;
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
printk(KERN_INFO "Initialized stdio console driver\n");
|
||||
|
||||
new_title = add_xterm_umid(opts.xterm_title);
|
||||
if(new_title != NULL)
|
||||
opts.xterm_title = new_title;
|
||||
|
||||
lines_init(vts, ARRAY_SIZE(vts), &opts);
|
||||
for (i = 0; i < MAX_TTYS; i++) {
|
||||
char *error;
|
||||
char *s = vt_conf[i];
|
||||
if (!s)
|
||||
s = def_conf;
|
||||
if (!s)
|
||||
s = i ? CONFIG_CON_CHAN : CONFIG_CON_ZERO_CHAN;
|
||||
if (setup_one_line(vts, i, s, &opts, &error))
|
||||
printk(KERN_ERR "setup_one_line failed for "
|
||||
"device %d : %s\n", i, error);
|
||||
}
|
||||
|
||||
con_init_done = 1;
|
||||
register_console(&stdiocons);
|
||||
@@ -189,14 +196,7 @@ __uml_exitcall(console_exit);
|
||||
|
||||
static int console_chan_setup(char *str)
|
||||
{
|
||||
char *error;
|
||||
int ret;
|
||||
|
||||
ret = line_setup(vts, ARRAY_SIZE(vts), str, &error);
|
||||
if(ret < 0)
|
||||
printk(KERN_ERR "Failed to set up console with "
|
||||
"configuration string \"%s\" : %s\n", str, error);
|
||||
|
||||
line_setup(vt_conf, MAX_TTYS, &def_conf, str, "console");
|
||||
return 1;
|
||||
}
|
||||
__setup("con", console_chan_setup);
|
||||
|
@@ -19,40 +19,26 @@
|
||||
|
||||
#define UBD_SHIFT 4
|
||||
|
||||
#include "linux/kernel.h"
|
||||
#include "linux/module.h"
|
||||
#include "linux/blkdev.h"
|
||||
#include "linux/ata.h"
|
||||
#include "linux/hdreg.h"
|
||||
#include "linux/init.h"
|
||||
#include "linux/cdrom.h"
|
||||
#include "linux/proc_fs.h"
|
||||
#include "linux/seq_file.h"
|
||||
#include "linux/ctype.h"
|
||||
#include "linux/capability.h"
|
||||
#include "linux/mm.h"
|
||||
#include "linux/slab.h"
|
||||
#include "linux/vmalloc.h"
|
||||
#include "linux/mutex.h"
|
||||
#include "linux/blkpg.h"
|
||||
#include "linux/genhd.h"
|
||||
#include "linux/spinlock.h"
|
||||
#include "linux/platform_device.h"
|
||||
#include "linux/scatterlist.h"
|
||||
#include "asm/segment.h"
|
||||
#include "asm/uaccess.h"
|
||||
#include "asm/irq.h"
|
||||
#include "asm/types.h"
|
||||
#include "asm/tlbflush.h"
|
||||
#include "mem_user.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/ata.h>
|
||||
#include <linux/hdreg.h>
|
||||
#include <linux/cdrom.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include "kern_util.h"
|
||||
#include "mconsole_kern.h"
|
||||
#include "init.h"
|
||||
#include "irq_user.h"
|
||||
#include "irq_kern.h"
|
||||
#include "ubd_user.h"
|
||||
#include "ubd.h"
|
||||
#include "os.h"
|
||||
#include "mem.h"
|
||||
#include "cow.h"
|
||||
|
||||
enum ubd_req { UBD_READ, UBD_WRITE };
|
||||
@@ -1115,7 +1101,7 @@ static int __init ubd_driver_init(void){
|
||||
return 0;
|
||||
}
|
||||
err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
|
||||
IRQF_DISABLED, "ubd", ubd_devs);
|
||||
0, "ubd", ubd_devs);
|
||||
if(err != 0)
|
||||
printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
|
||||
return 0;
|
||||
|
@@ -15,14 +15,12 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/param.h>
|
||||
#include "asm/types.h"
|
||||
#include "ubd_user.h"
|
||||
#include "os.h"
|
||||
#include "cow.h"
|
||||
|
||||
#include <endian.h>
|
||||
#include <byteswap.h>
|
||||
|
||||
#include "ubd.h"
|
||||
#include "os.h"
|
||||
|
||||
void ignore_sigwinch_sig(void)
|
||||
{
|
||||
signal(SIGWINCH, SIG_IGN);
|
||||
|
@@ -50,7 +50,7 @@ int xterm_fd(int socket, int *pid_out)
|
||||
init_completion(&data->ready);
|
||||
|
||||
err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
|
||||
IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
|
||||
IRQF_SHARED | IRQF_SAMPLE_RANDOM,
|
||||
"xterm", data);
|
||||
if (err) {
|
||||
printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
|
||||
|
Referência em uma nova issue
Block a user