diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
| commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
| tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /arch/um/drivers | |
| parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) | |
Patched in Tegra support.
Diffstat (limited to 'arch/um/drivers')
48 files changed, 872 insertions, 921 deletions
diff --git a/arch/um/drivers/chan.h b/arch/um/drivers/chan.h deleted file mode 100644 index 02b5a76e98d..00000000000 --- a/arch/um/drivers/chan.h +++ /dev/null | |||
| @@ -1,50 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __CHAN_KERN_H__ | ||
| 7 | #define __CHAN_KERN_H__ | ||
| 8 | |||
| 9 | #include <linux/tty.h> | ||
| 10 | #include <linux/list.h> | ||
| 11 | #include <linux/console.h> | ||
| 12 | #include "chan_user.h" | ||
| 13 | #include "line.h" | ||
| 14 | |||
| 15 | struct chan { | ||
| 16 | struct list_head list; | ||
| 17 | struct list_head free_list; | ||
| 18 | struct line *line; | ||
| 19 | char *dev; | ||
| 20 | unsigned int primary:1; | ||
| 21 | unsigned int input:1; | ||
| 22 | unsigned int output:1; | ||
| 23 | unsigned int opened:1; | ||
| 24 | unsigned int enabled:1; | ||
| 25 | int fd; | ||
| 26 | const struct chan_ops *ops; | ||
| 27 | void *data; | ||
| 28 | }; | ||
| 29 | |||
| 30 | extern void chan_interrupt(struct line *line, | ||
| 31 | struct tty_struct *tty, int irq); | ||
| 32 | extern int parse_chan_pair(char *str, struct line *line, int device, | ||
| 33 | const struct chan_opts *opts, char **error_out); | ||
| 34 | extern int write_chan(struct chan *chan, const char *buf, int len, | ||
| 35 | int write_irq); | ||
| 36 | extern int console_write_chan(struct chan *chan, const char *buf, | ||
| 37 | int len); | ||
| 38 | extern int console_open_chan(struct line *line, struct console *co); | ||
| 39 | extern void deactivate_chan(struct chan *chan, int irq); | ||
| 40 | extern void reactivate_chan(struct chan *chan, int irq); | ||
| 41 | extern void chan_enable_winch(struct chan *chan, struct tty_struct *tty); | ||
| 42 | extern int enable_chan(struct line *line); | ||
| 43 | extern void close_chan(struct line *line); | ||
| 44 | extern int chan_window_size(struct line *line, | ||
| 45 | unsigned short *rows_out, | ||
| 46 | unsigned short *cols_out); | ||
| 47 | extern int chan_config_string(struct line *line, char *str, int size, | ||
| 48 | char **error_out); | ||
| 49 | |||
| 50 | #endif | ||
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index e9a0abc6a32..d4191fe1ced 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c | |||
| @@ -6,9 +6,8 @@ | |||
| 6 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
| 7 | #include <linux/tty.h> | 7 | #include <linux/tty.h> |
| 8 | #include <linux/tty_flip.h> | 8 | #include <linux/tty_flip.h> |
| 9 | #include "chan.h" | 9 | #include "chan_kern.h" |
| 10 | #include <os.h> | 10 | #include "os.h" |
| 11 | #include <irq_kern.h> | ||
| 12 | 11 | ||
| 13 | #ifdef CONFIG_NOCONFIG_CHAN | 12 | #ifdef CONFIG_NOCONFIG_CHAN |
| 14 | static void *not_configged_init(char *str, int device, | 13 | static void *not_configged_init(char *str, int device, |
| @@ -83,8 +82,21 @@ static const struct chan_ops not_configged_ops = { | |||
| 83 | 82 | ||
| 84 | static void tty_receive_char(struct tty_struct *tty, char ch) | 83 | static void tty_receive_char(struct tty_struct *tty, char ch) |
| 85 | { | 84 | { |
| 86 | if (tty) | 85 | if (tty == NULL) |
| 87 | tty_insert_flip_char(tty, ch, TTY_NORMAL); | 86 | return; |
| 87 | |||
| 88 | if (I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) { | ||
| 89 | if (ch == STOP_CHAR(tty)) { | ||
| 90 | stop_tty(tty); | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | else if (ch == START_CHAR(tty)) { | ||
| 94 | start_tty(tty); | ||
| 95 | return; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | tty_insert_flip_char(tty, ch, TTY_NORMAL); | ||
| 88 | } | 100 | } |
| 89 | 101 | ||
| 90 | static int open_one_chan(struct chan *chan) | 102 | static int open_one_chan(struct chan *chan) |
| @@ -128,20 +140,18 @@ static int open_chan(struct list_head *chans) | |||
| 128 | return err; | 140 | return err; |
| 129 | } | 141 | } |
| 130 | 142 | ||
| 131 | void chan_enable_winch(struct chan *chan, struct tty_struct *tty) | 143 | void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) |
| 132 | { | 144 | { |
| 133 | if (chan && chan->primary && chan->ops->winch) | 145 | struct list_head *ele; |
| 134 | register_winch(chan->fd, tty); | 146 | struct chan *chan; |
| 135 | } | ||
| 136 | |||
| 137 | static void line_timer_cb(struct work_struct *work) | ||
| 138 | { | ||
| 139 | struct line *line = container_of(work, struct line, task.work); | ||
| 140 | struct tty_struct *tty = tty_port_tty_get(&line->port); | ||
| 141 | 147 | ||
| 142 | if (!line->throttled) | 148 | list_for_each(ele, chans) { |
| 143 | chan_interrupt(line, tty, line->driver->read_irq); | 149 | chan = list_entry(ele, struct chan, list); |
| 144 | tty_kref_put(tty); | 150 | if (chan->primary && chan->output && chan->ops->winch) { |
| 151 | register_winch(chan->fd, tty); | ||
| 152 | return; | ||
| 153 | } | ||
| 154 | } | ||
| 145 | } | 155 | } |
| 146 | 156 | ||
| 147 | int enable_chan(struct line *line) | 157 | int enable_chan(struct line *line) |
| @@ -150,8 +160,6 @@ int enable_chan(struct line *line) | |||
| 150 | struct chan *chan; | 160 | struct chan *chan; |
| 151 | int err; | 161 | int err; |
| 152 | 162 | ||
| 153 | INIT_DELAYED_WORK(&line->task, line_timer_cb); | ||
| 154 | |||
| 155 | list_for_each(ele, &line->chan_list) { | 163 | list_for_each(ele, &line->chan_list) { |
| 156 | chan = list_entry(ele, struct chan, list); | 164 | chan = list_entry(ele, struct chan, list); |
| 157 | err = open_one_chan(chan); | 165 | err = open_one_chan(chan); |
| @@ -175,7 +183,7 @@ int enable_chan(struct line *line) | |||
| 175 | return 0; | 183 | return 0; |
| 176 | 184 | ||
| 177 | out_close: | 185 | out_close: |
| 178 | close_chan(line); | 186 | close_chan(&line->chan_list, 0); |
| 179 | return err; | 187 | return err; |
| 180 | } | 188 | } |
| 181 | 189 | ||
| @@ -203,9 +211,9 @@ void free_irqs(void) | |||
| 203 | chan = list_entry(ele, struct chan, free_list); | 211 | chan = list_entry(ele, struct chan, free_list); |
| 204 | 212 | ||
| 205 | if (chan->input && chan->enabled) | 213 | if (chan->input && chan->enabled) |
| 206 | um_free_irq(chan->line->driver->read_irq, chan); | 214 | free_irq(chan->line->driver->read_irq, chan); |
| 207 | if (chan->output && chan->enabled) | 215 | if (chan->output && chan->enabled) |
| 208 | um_free_irq(chan->line->driver->write_irq, chan); | 216 | free_irq(chan->line->driver->write_irq, chan); |
| 209 | chan->enabled = 0; | 217 | chan->enabled = 0; |
| 210 | } | 218 | } |
| 211 | } | 219 | } |
| @@ -224,9 +232,9 @@ static void close_one_chan(struct chan *chan, int delay_free_irq) | |||
| 224 | } | 232 | } |
| 225 | else { | 233 | else { |
| 226 | if (chan->input && chan->enabled) | 234 | if (chan->input && chan->enabled) |
| 227 | um_free_irq(chan->line->driver->read_irq, chan); | 235 | free_irq(chan->line->driver->read_irq, chan); |
| 228 | if (chan->output && chan->enabled) | 236 | if (chan->output && chan->enabled) |
| 229 | um_free_irq(chan->line->driver->write_irq, chan); | 237 | free_irq(chan->line->driver->write_irq, chan); |
| 230 | chan->enabled = 0; | 238 | chan->enabled = 0; |
| 231 | } | 239 | } |
| 232 | if (chan->ops->close != NULL) | 240 | if (chan->ops->close != NULL) |
| @@ -236,7 +244,7 @@ static void close_one_chan(struct chan *chan, int delay_free_irq) | |||
| 236 | chan->fd = -1; | 244 | chan->fd = -1; |
| 237 | } | 245 | } |
| 238 | 246 | ||
| 239 | void close_chan(struct line *line) | 247 | void close_chan(struct list_head *chans, int delay_free_irq) |
| 240 | { | 248 | { |
| 241 | struct chan *chan; | 249 | struct chan *chan; |
| 242 | 250 | ||
| @@ -245,50 +253,77 @@ void close_chan(struct line *line) | |||
| 245 | * state. Then, the first one opened will have the original state, | 253 | * state. Then, the first one opened will have the original state, |
| 246 | * so it must be the last closed. | 254 | * so it must be the last closed. |
| 247 | */ | 255 | */ |
| 248 | list_for_each_entry_reverse(chan, &line->chan_list, list) { | 256 | list_for_each_entry_reverse(chan, chans, list) { |
| 249 | close_one_chan(chan, 0); | 257 | close_one_chan(chan, delay_free_irq); |
| 250 | } | 258 | } |
| 251 | } | 259 | } |
| 252 | 260 | ||
| 253 | void deactivate_chan(struct chan *chan, int irq) | 261 | void deactivate_chan(struct list_head *chans, int irq) |
| 254 | { | 262 | { |
| 255 | if (chan && chan->enabled) | 263 | struct list_head *ele; |
| 256 | deactivate_fd(chan->fd, irq); | 264 | |
| 265 | struct chan *chan; | ||
| 266 | list_for_each(ele, chans) { | ||
| 267 | chan = list_entry(ele, struct chan, list); | ||
| 268 | |||
| 269 | if (chan->enabled && chan->input) | ||
| 270 | deactivate_fd(chan->fd, irq); | ||
| 271 | } | ||
| 257 | } | 272 | } |
| 258 | 273 | ||
| 259 | void reactivate_chan(struct chan *chan, int irq) | 274 | void reactivate_chan(struct list_head *chans, int irq) |
| 260 | { | 275 | { |
| 261 | if (chan && chan->enabled) | 276 | struct list_head *ele; |
| 262 | reactivate_fd(chan->fd, irq); | 277 | struct chan *chan; |
| 278 | |||
| 279 | list_for_each(ele, chans) { | ||
| 280 | chan = list_entry(ele, struct chan, list); | ||
| 281 | |||
| 282 | if (chan->enabled && chan->input) | ||
| 283 | reactivate_fd(chan->fd, irq); | ||
| 284 | } | ||
| 263 | } | 285 | } |
| 264 | 286 | ||
| 265 | int write_chan(struct chan *chan, const char *buf, int len, | 287 | int write_chan(struct list_head *chans, const char *buf, int len, |
| 266 | int write_irq) | 288 | int write_irq) |
| 267 | { | 289 | { |
| 290 | struct list_head *ele; | ||
| 291 | struct chan *chan = NULL; | ||
| 268 | int n, ret = 0; | 292 | int n, ret = 0; |
| 269 | 293 | ||
| 270 | if (len == 0 || !chan || !chan->ops->write) | 294 | if (len == 0) |
| 271 | return 0; | 295 | return 0; |
| 272 | 296 | ||
| 273 | n = chan->ops->write(chan->fd, buf, len, chan->data); | 297 | list_for_each(ele, chans) { |
| 274 | if (chan->primary) { | 298 | chan = list_entry(ele, struct chan, list); |
| 275 | ret = n; | 299 | if (!chan->output || (chan->ops->write == NULL)) |
| 276 | if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len))) | 300 | continue; |
| 277 | reactivate_fd(chan->fd, write_irq); | 301 | |
| 302 | n = chan->ops->write(chan->fd, buf, len, chan->data); | ||
| 303 | if (chan->primary) { | ||
| 304 | ret = n; | ||
| 305 | if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len))) | ||
| 306 | reactivate_fd(chan->fd, write_irq); | ||
| 307 | } | ||
| 278 | } | 308 | } |
| 279 | return ret; | 309 | return ret; |
| 280 | } | 310 | } |
| 281 | 311 | ||
| 282 | int console_write_chan(struct chan *chan, const char *buf, int len) | 312 | int console_write_chan(struct list_head *chans, const char *buf, int len) |
| 283 | { | 313 | { |
| 314 | struct list_head *ele; | ||
| 315 | struct chan *chan; | ||
| 284 | int n, ret = 0; | 316 | int n, ret = 0; |
| 285 | 317 | ||
| 286 | if (!chan || !chan->ops->console_write) | 318 | list_for_each(ele, chans) { |
| 287 | return 0; | 319 | chan = list_entry(ele, struct chan, list); |
| 320 | if (!chan->output || (chan->ops->console_write == NULL)) | ||
| 321 | continue; | ||
| 288 | 322 | ||
| 289 | n = chan->ops->console_write(chan->fd, buf, len); | 323 | n = chan->ops->console_write(chan->fd, buf, len); |
| 290 | if (chan->primary) | 324 | if (chan->primary) |
| 291 | ret = n; | 325 | ret = n; |
| 326 | } | ||
| 292 | return ret; | 327 | return ret; |
| 293 | } | 328 | } |
| 294 | 329 | ||
| @@ -305,33 +340,29 @@ int console_open_chan(struct line *line, struct console *co) | |||
| 305 | return 0; | 340 | return 0; |
| 306 | } | 341 | } |
| 307 | 342 | ||
| 308 | int chan_window_size(struct line *line, unsigned short *rows_out, | 343 | int chan_window_size(struct list_head *chans, unsigned short *rows_out, |
| 309 | unsigned short *cols_out) | 344 | unsigned short *cols_out) |
| 310 | { | 345 | { |
| 346 | struct list_head *ele; | ||
| 311 | struct chan *chan; | 347 | struct chan *chan; |
| 312 | 348 | ||
| 313 | chan = line->chan_in; | 349 | list_for_each(ele, chans) { |
| 314 | if (chan && chan->primary) { | 350 | chan = list_entry(ele, struct chan, list); |
| 315 | if (chan->ops->window_size == NULL) | 351 | if (chan->primary) { |
| 316 | return 0; | 352 | if (chan->ops->window_size == NULL) |
| 317 | return chan->ops->window_size(chan->fd, chan->data, | 353 | return 0; |
| 318 | rows_out, cols_out); | 354 | return chan->ops->window_size(chan->fd, chan->data, |
| 319 | } | 355 | rows_out, cols_out); |
| 320 | chan = line->chan_out; | 356 | } |
| 321 | if (chan && chan->primary) { | ||
| 322 | if (chan->ops->window_size == NULL) | ||
| 323 | return 0; | ||
| 324 | return chan->ops->window_size(chan->fd, chan->data, | ||
| 325 | rows_out, cols_out); | ||
| 326 | } | 357 | } |
| 327 | return 0; | 358 | return 0; |
| 328 | } | 359 | } |
| 329 | 360 | ||
| 330 | static void free_one_chan(struct chan *chan) | 361 | static void free_one_chan(struct chan *chan, int delay_free_irq) |
| 331 | { | 362 | { |
| 332 | list_del(&chan->list); | 363 | list_del(&chan->list); |
| 333 | 364 | ||
| 334 | close_one_chan(chan, 0); | 365 | close_one_chan(chan, delay_free_irq); |
| 335 | 366 | ||
| 336 | if (chan->ops->free != NULL) | 367 | if (chan->ops->free != NULL) |
| 337 | (*chan->ops->free)(chan->data); | 368 | (*chan->ops->free)(chan->data); |
| @@ -341,14 +372,14 @@ static void free_one_chan(struct chan *chan) | |||
| 341 | kfree(chan); | 372 | kfree(chan); |
| 342 | } | 373 | } |
| 343 | 374 | ||
| 344 | static void free_chan(struct list_head *chans) | 375 | static void free_chan(struct list_head *chans, int delay_free_irq) |
| 345 | { | 376 | { |
| 346 | struct list_head *ele, *next; | 377 | struct list_head *ele, *next; |
| 347 | struct chan *chan; | 378 | struct chan *chan; |
| 348 | 379 | ||
| 349 | list_for_each_safe(ele, next, chans) { | 380 | list_for_each_safe(ele, next, chans) { |
| 350 | chan = list_entry(ele, struct chan, list); | 381 | chan = list_entry(ele, struct chan, list); |
| 351 | free_one_chan(chan); | 382 | free_one_chan(chan, delay_free_irq); |
| 352 | } | 383 | } |
| 353 | } | 384 | } |
| 354 | 385 | ||
| @@ -398,15 +429,21 @@ static int chan_pair_config_string(struct chan *in, struct chan *out, | |||
| 398 | return n; | 429 | return n; |
| 399 | } | 430 | } |
| 400 | 431 | ||
| 401 | int chan_config_string(struct line *line, char *str, int size, | 432 | int chan_config_string(struct list_head *chans, char *str, int size, |
| 402 | char **error_out) | 433 | char **error_out) |
| 403 | { | 434 | { |
| 404 | struct chan *in = line->chan_in, *out = line->chan_out; | 435 | struct list_head *ele; |
| 436 | struct chan *chan, *in = NULL, *out = NULL; | ||
| 405 | 437 | ||
| 406 | if (in && !in->primary) | 438 | list_for_each(ele, chans) { |
| 407 | in = NULL; | 439 | chan = list_entry(ele, struct chan, list); |
| 408 | if (out && !out->primary) | 440 | if (!chan->primary) |
| 409 | out = NULL; | 441 | continue; |
| 442 | if (chan->input) | ||
| 443 | in = chan; | ||
| 444 | if (chan->output) | ||
| 445 | out = chan; | ||
| 446 | } | ||
| 410 | 447 | ||
| 411 | return chan_pair_config_string(in, out, str, size, error_out); | 448 | return chan_pair_config_string(in, out, str, size, error_out); |
| 412 | } | 449 | } |
| @@ -510,14 +547,10 @@ int parse_chan_pair(char *str, struct line *line, int device, | |||
| 510 | char *in, *out; | 547 | char *in, *out; |
| 511 | 548 | ||
| 512 | if (!list_empty(chans)) { | 549 | if (!list_empty(chans)) { |
| 513 | line->chan_in = line->chan_out = NULL; | 550 | free_chan(chans, 0); |
| 514 | free_chan(chans); | ||
| 515 | INIT_LIST_HEAD(chans); | 551 | INIT_LIST_HEAD(chans); |
| 516 | } | 552 | } |
| 517 | 553 | ||
| 518 | if (!str) | ||
| 519 | return 0; | ||
| 520 | |||
| 521 | out = strchr(str, ','); | 554 | out = strchr(str, ','); |
| 522 | if (out != NULL) { | 555 | if (out != NULL) { |
| 523 | in = str; | 556 | in = str; |
| @@ -529,7 +562,6 @@ int parse_chan_pair(char *str, struct line *line, int device, | |||
| 529 | 562 | ||
| 530 | new->input = 1; | 563 | new->input = 1; |
| 531 | list_add(&new->list, chans); | 564 | list_add(&new->list, chans); |
| 532 | line->chan_in = new; | ||
| 533 | 565 | ||
| 534 | new = parse_chan(line, out, device, opts, error_out); | 566 | new = parse_chan(line, out, device, opts, error_out); |
| 535 | if (new == NULL) | 567 | if (new == NULL) |
| @@ -537,7 +569,6 @@ int parse_chan_pair(char *str, struct line *line, int device, | |||
| 537 | 569 | ||
| 538 | list_add(&new->list, chans); | 570 | list_add(&new->list, chans); |
| 539 | new->output = 1; | 571 | new->output = 1; |
| 540 | line->chan_out = new; | ||
| 541 | } | 572 | } |
| 542 | else { | 573 | else { |
| 543 | new = parse_chan(line, str, device, opts, error_out); | 574 | new = parse_chan(line, str, device, opts, error_out); |
| @@ -547,42 +578,43 @@ int parse_chan_pair(char *str, struct line *line, int device, | |||
| 547 | list_add(&new->list, chans); | 578 | list_add(&new->list, chans); |
| 548 | new->input = 1; | 579 | new->input = 1; |
| 549 | new->output = 1; | 580 | new->output = 1; |
| 550 | line->chan_in = line->chan_out = new; | ||
| 551 | } | 581 | } |
| 552 | return 0; | 582 | return 0; |
| 553 | } | 583 | } |
| 554 | 584 | ||
| 555 | void chan_interrupt(struct line *line, struct tty_struct *tty, int irq) | 585 | void chan_interrupt(struct list_head *chans, struct delayed_work *task, |
| 586 | struct tty_struct *tty, int irq) | ||
| 556 | { | 587 | { |
| 557 | struct chan *chan = line->chan_in; | 588 | struct list_head *ele, *next; |
| 589 | struct chan *chan; | ||
| 558 | int err; | 590 | int err; |
| 559 | char c; | 591 | char c; |
| 560 | 592 | ||
| 561 | if (!chan || !chan->ops->read) | 593 | list_for_each_safe(ele, next, chans) { |
| 562 | goto out; | 594 | chan = list_entry(ele, struct chan, list); |
| 563 | 595 | if (!chan->input || (chan->ops->read == NULL)) | |
| 564 | do { | 596 | continue; |
| 565 | if (tty && !tty_buffer_request_room(tty, 1)) { | 597 | do { |
| 566 | schedule_delayed_work(&line->task, 1); | 598 | if (tty && !tty_buffer_request_room(tty, 1)) { |
| 567 | goto out; | 599 | schedule_delayed_work(task, 1); |
| 568 | } | 600 | goto out; |
| 569 | err = chan->ops->read(chan->fd, &c, chan->data); | 601 | } |
| 570 | if (err > 0) | 602 | err = chan->ops->read(chan->fd, &c, chan->data); |
| 571 | tty_receive_char(tty, c); | 603 | if (err > 0) |
| 572 | } while (err > 0); | 604 | tty_receive_char(tty, c); |
| 573 | 605 | } while (err > 0); | |
| 574 | if (err == 0) | 606 | |
| 575 | reactivate_fd(chan->fd, irq); | 607 | if (err == 0) |
| 576 | if (err == -EIO) { | 608 | reactivate_fd(chan->fd, irq); |
| 577 | if (chan->primary) { | 609 | if (err == -EIO) { |
| 578 | if (tty != NULL) | 610 | if (chan->primary) { |
| 579 | tty_hangup(tty); | 611 | if (tty != NULL) |
| 580 | if (line->chan_out != chan) | 612 | tty_hangup(tty); |
| 581 | close_one_chan(line->chan_out, 1); | 613 | close_chan(chans, 1); |
| 614 | return; | ||
| 615 | } | ||
| 616 | else close_one_chan(chan, 1); | ||
| 582 | } | 617 | } |
| 583 | close_one_chan(chan, 1); | ||
| 584 | if (chan->primary) | ||
| 585 | return; | ||
| 586 | } | 618 | } |
| 587 | out: | 619 | out: |
| 588 | if (tty) | 620 | if (tty) |
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 9be670ad23b..cfeb3f4a44a 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c | |||
| @@ -11,8 +11,10 @@ | |||
| 11 | #include <termios.h> | 11 | #include <termios.h> |
| 12 | #include <sys/ioctl.h> | 12 | #include <sys/ioctl.h> |
| 13 | #include "chan_user.h" | 13 | #include "chan_user.h" |
| 14 | #include <os.h> | 14 | #include "kern_constants.h" |
| 15 | #include <um_malloc.h> | 15 | #include "os.h" |
| 16 | #include "um_malloc.h" | ||
| 17 | #include "user.h" | ||
| 16 | 18 | ||
| 17 | void generic_close(int fd, void *unused) | 19 | void generic_close(int fd, void *unused) |
| 18 | { | 20 | { |
| @@ -281,12 +283,7 @@ void register_winch(int fd, struct tty_struct *tty) | |||
| 281 | return; | 283 | return; |
| 282 | 284 | ||
| 283 | pid = tcgetpgrp(fd); | 285 | pid = tcgetpgrp(fd); |
| 284 | if (is_skas_winch(pid, fd, tty)) { | 286 | if (!is_skas_winch(pid, fd, tty) && (pid == -1)) { |
| 285 | register_winch_irq(-1, fd, -1, tty, 0); | ||
| 286 | return; | ||
| 287 | } | ||
| 288 | |||
| 289 | if (pid == -1) { | ||
| 290 | thread = winch_tramp(fd, tty, &thread_fd, &stack); | 287 | thread = winch_tramp(fd, tty, &thread_fd, &stack); |
| 291 | if (thread < 0) | 288 | if (thread < 0) |
| 292 | return; | 289 | return; |
diff --git a/arch/um/drivers/chan_user.h b/arch/um/drivers/chan_user.h deleted file mode 100644 index dc693298eb8..00000000000 --- a/arch/um/drivers/chan_user.h +++ /dev/null | |||
| @@ -1,53 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __CHAN_USER_H__ | ||
| 7 | #define __CHAN_USER_H__ | ||
| 8 | |||
| 9 | #include <init.h> | ||
| 10 | |||
| 11 | struct chan_opts { | ||
| 12 | void (*const announce)(char *dev_name, int dev); | ||
| 13 | char *xterm_title; | ||
| 14 | const int raw; | ||
| 15 | }; | ||
| 16 | |||
| 17 | struct chan_ops { | ||
| 18 | char *type; | ||
| 19 | void *(*init)(char *, int, const struct chan_opts *); | ||
| 20 | int (*open)(int, int, int, void *, char **); | ||
| 21 | void (*close)(int, void *); | ||
| 22 | int (*read)(int, char *, void *); | ||
| 23 | int (*write)(int, const char *, int, void *); | ||
| 24 | int (*console_write)(int, const char *, int); | ||
| 25 | int (*window_size)(int, void *, unsigned short *, unsigned short *); | ||
| 26 | void (*free)(void *); | ||
| 27 | int winch; | ||
| 28 | }; | ||
| 29 | |||
| 30 | extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, | ||
| 31 | tty_ops, xterm_ops; | ||
| 32 | |||
| 33 | extern void generic_close(int fd, void *unused); | ||
| 34 | extern int generic_read(int fd, char *c_out, void *unused); | ||
| 35 | extern int generic_write(int fd, const char *buf, int n, void *unused); | ||
| 36 | extern int generic_console_write(int fd, const char *buf, int n); | ||
| 37 | extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, | ||
| 38 | unsigned short *cols_out); | ||
| 39 | extern void generic_free(void *data); | ||
| 40 | |||
| 41 | struct tty_struct; | ||
| 42 | extern void register_winch(int fd, struct tty_struct *tty); | ||
| 43 | extern void register_winch_irq(int fd, int tty_fd, int pid, | ||
| 44 | struct tty_struct *tty, unsigned long stack); | ||
| 45 | |||
| 46 | #define __channel_help(fn, prefix) \ | ||
| 47 | __uml_help(fn, prefix "[0-9]*=<channel description>\n" \ | ||
| 48 | " Attach a console or serial line to a host channel. See\n" \ | ||
| 49 | " http://user-mode-linux.sourceforge.net/old/input.html for a complete\n" \ | ||
| 50 | " description of this switch.\n\n" \ | ||
| 51 | ); | ||
| 52 | |||
| 53 | #endif | ||
diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h index 6673508f342..dc36b222100 100644 --- a/arch/um/drivers/cow.h +++ b/arch/um/drivers/cow.h | |||
| @@ -3,6 +3,41 @@ | |||
| 3 | 3 | ||
| 4 | #include <asm/types.h> | 4 | #include <asm/types.h> |
| 5 | 5 | ||
| 6 | #if defined(__KERNEL__) | ||
| 7 | |||
| 8 | # include <asm/byteorder.h> | ||
| 9 | |||
| 10 | # if defined(__BIG_ENDIAN) | ||
| 11 | # define ntohll(x) (x) | ||
| 12 | # define htonll(x) (x) | ||
| 13 | # elif defined(__LITTLE_ENDIAN) | ||
| 14 | # define ntohll(x) be64_to_cpu(x) | ||
| 15 | # define htonll(x) cpu_to_be64(x) | ||
| 16 | # else | ||
| 17 | # error "Could not determine byte order" | ||
| 18 | # endif | ||
| 19 | |||
| 20 | #else | ||
| 21 | /* For the definition of ntohl, htonl and __BYTE_ORDER */ | ||
| 22 | #include <endian.h> | ||
| 23 | #include <netinet/in.h> | ||
| 24 | #if defined(__BYTE_ORDER) | ||
| 25 | |||
| 26 | # if __BYTE_ORDER == __BIG_ENDIAN | ||
| 27 | # define ntohll(x) (x) | ||
| 28 | # define htonll(x) (x) | ||
| 29 | # elif __BYTE_ORDER == __LITTLE_ENDIAN | ||
| 30 | # define ntohll(x) bswap_64(x) | ||
| 31 | # define htonll(x) bswap_64(x) | ||
| 32 | # else | ||
| 33 | # error "Could not determine byte order: __BYTE_ORDER uncorrectly defined" | ||
| 34 | # endif | ||
| 35 | |||
| 36 | #else /* ! defined(__BYTE_ORDER) */ | ||
| 37 | # error "Could not determine byte order: __BYTE_ORDER not defined" | ||
| 38 | #endif | ||
| 39 | #endif /* ! defined(__KERNEL__) */ | ||
| 40 | |||
| 6 | extern int init_cow_file(int fd, char *cow_file, char *backing_file, | 41 | extern int init_cow_file(int fd, char *cow_file, char *backing_file, |
| 7 | int sectorsize, int alignment, int *bitmap_offset_out, | 42 | int sectorsize, int alignment, int *bitmap_offset_out, |
| 8 | unsigned long *bitmap_len_out, int *data_offset_out); | 43 | unsigned long *bitmap_len_out, int *data_offset_out); |
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h index 67cbee63e70..f5701fd2ef9 100644 --- a/arch/um/drivers/cow_sys.h +++ b/arch/um/drivers/cow_sys.h | |||
| @@ -1,9 +1,10 @@ | |||
| 1 | #ifndef __COW_SYS_H__ | 1 | #ifndef __COW_SYS_H__ |
| 2 | #define __COW_SYS_H__ | 2 | #define __COW_SYS_H__ |
| 3 | 3 | ||
| 4 | #include <kern_util.h> | 4 | #include "kern_util.h" |
| 5 | #include <os.h> | 5 | #include "os.h" |
| 6 | #include <um_malloc.h> | 6 | #include "user.h" |
| 7 | #include "um_malloc.h" | ||
| 7 | 8 | ||
| 8 | static inline void *cow_malloc(int size) | 9 | static inline void *cow_malloc(int size) |
| 9 | { | 10 | { |
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c index 0ee9cc6cc4c..9cbb426c0b9 100644 --- a/arch/um/drivers/cow_user.c +++ b/arch/um/drivers/cow_user.c | |||
| @@ -8,10 +8,11 @@ | |||
| 8 | * that. | 8 | * that. |
| 9 | */ | 9 | */ |
| 10 | #include <unistd.h> | 10 | #include <unistd.h> |
| 11 | #include <byteswap.h> | ||
| 11 | #include <errno.h> | 12 | #include <errno.h> |
| 12 | #include <string.h> | 13 | #include <string.h> |
| 13 | #include <arpa/inet.h> | 14 | #include <arpa/inet.h> |
| 14 | #include <endian.h> | 15 | #include <asm/types.h> |
| 15 | #include "cow.h" | 16 | #include "cow.h" |
| 16 | #include "cow_sys.h" | 17 | #include "cow_sys.h" |
| 17 | 18 | ||
| @@ -213,8 +214,8 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, | |||
| 213 | "header\n"); | 214 | "header\n"); |
| 214 | goto out; | 215 | goto out; |
| 215 | } | 216 | } |
| 216 | header->magic = htobe32(COW_MAGIC); | 217 | header->magic = htonl(COW_MAGIC); |
| 217 | header->version = htobe32(COW_VERSION); | 218 | header->version = htonl(COW_VERSION); |
| 218 | 219 | ||
| 219 | err = -EINVAL; | 220 | err = -EINVAL; |
| 220 | if (strlen(backing_file) > sizeof(header->backing_file) - 1) { | 221 | if (strlen(backing_file) > sizeof(header->backing_file) - 1) { |
| @@ -245,10 +246,10 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, | |||
| 245 | goto out_free; | 246 | goto out_free; |
| 246 | } | 247 | } |
| 247 | 248 | ||
| 248 | header->mtime = htobe32(modtime); | 249 | header->mtime = htonl(modtime); |
| 249 | header->size = htobe64(*size); | 250 | header->size = htonll(*size); |
| 250 | header->sectorsize = htobe32(sectorsize); | 251 | header->sectorsize = htonl(sectorsize); |
| 251 | header->alignment = htobe32(alignment); | 252 | header->alignment = htonl(alignment); |
| 252 | header->cow_format = COW_BITMAP; | 253 | header->cow_format = COW_BITMAP; |
| 253 | 254 | ||
| 254 | err = cow_write_file(fd, header, sizeof(*header)); | 255 | err = cow_write_file(fd, header, sizeof(*header)); |
| @@ -300,8 +301,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, | |||
| 300 | magic = header->v1.magic; | 301 | magic = header->v1.magic; |
| 301 | if (magic == COW_MAGIC) | 302 | if (magic == COW_MAGIC) |
| 302 | version = header->v1.version; | 303 | version = header->v1.version; |
| 303 | else if (magic == be32toh(COW_MAGIC)) | 304 | else if (magic == ntohl(COW_MAGIC)) |
| 304 | version = be32toh(header->v1.version); | 305 | version = ntohl(header->v1.version); |
| 305 | /* No error printed because the non-COW case comes through here */ | 306 | /* No error printed because the non-COW case comes through here */ |
| 306 | else goto out; | 307 | else goto out; |
| 307 | 308 | ||
| @@ -326,9 +327,9 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, | |||
| 326 | "header\n"); | 327 | "header\n"); |
| 327 | goto out; | 328 | goto out; |
| 328 | } | 329 | } |
| 329 | *mtime_out = be32toh(header->v2.mtime); | 330 | *mtime_out = ntohl(header->v2.mtime); |
| 330 | *size_out = be64toh(header->v2.size); | 331 | *size_out = ntohll(header->v2.size); |
| 331 | *sectorsize_out = be32toh(header->v2.sectorsize); | 332 | *sectorsize_out = ntohl(header->v2.sectorsize); |
| 332 | *bitmap_offset_out = sizeof(header->v2); | 333 | *bitmap_offset_out = sizeof(header->v2); |
| 333 | *align_out = *sectorsize_out; | 334 | *align_out = *sectorsize_out; |
| 334 | file = header->v2.backing_file; | 335 | file = header->v2.backing_file; |
| @@ -340,10 +341,10 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, | |||
| 340 | "header\n"); | 341 | "header\n"); |
| 341 | goto out; | 342 | goto out; |
| 342 | } | 343 | } |
| 343 | *mtime_out = be32toh(header->v3.mtime); | 344 | *mtime_out = ntohl(header->v3.mtime); |
| 344 | *size_out = be64toh(header->v3.size); | 345 | *size_out = ntohll(header->v3.size); |
| 345 | *sectorsize_out = be32toh(header->v3.sectorsize); | 346 | *sectorsize_out = ntohl(header->v3.sectorsize); |
| 346 | *align_out = be32toh(header->v3.alignment); | 347 | *align_out = ntohl(header->v3.alignment); |
| 347 | if (*align_out == 0) { | 348 | if (*align_out == 0) { |
| 348 | cow_printf("read_cow_header - invalid COW header, " | 349 | cow_printf("read_cow_header - invalid COW header, " |
| 349 | "align == 0\n"); | 350 | "align == 0\n"); |
| @@ -365,16 +366,16 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, | |||
| 365 | * this was used until Dec2005 - 64bits are needed to represent | 366 | * this was used until Dec2005 - 64bits are needed to represent |
| 366 | * 2038+. I.e. we can safely do this truncating cast. | 367 | * 2038+. I.e. we can safely do this truncating cast. |
| 367 | * | 368 | * |
| 368 | * Additionally, we must use be32toh() instead of be64toh(), since | 369 | * Additionally, we must use ntohl() instead of ntohll(), since |
| 369 | * the program used to use the former (tested - I got mtime | 370 | * the program used to use the former (tested - I got mtime |
| 370 | * mismatch "0 vs whatever"). | 371 | * mismatch "0 vs whatever"). |
| 371 | * | 372 | * |
| 372 | * Ever heard about bug-to-bug-compatibility ? ;-) */ | 373 | * Ever heard about bug-to-bug-compatibility ? ;-) */ |
| 373 | *mtime_out = (time32_t) be32toh(header->v3_b.mtime); | 374 | *mtime_out = (time32_t) ntohl(header->v3_b.mtime); |
| 374 | 375 | ||
| 375 | *size_out = be64toh(header->v3_b.size); | 376 | *size_out = ntohll(header->v3_b.size); |
| 376 | *sectorsize_out = be32toh(header->v3_b.sectorsize); | 377 | *sectorsize_out = ntohl(header->v3_b.sectorsize); |
| 377 | *align_out = be32toh(header->v3_b.alignment); | 378 | *align_out = ntohl(header->v3_b.alignment); |
| 378 | if (*align_out == 0) { | 379 | if (*align_out == 0) { |
| 379 | cow_printf("read_cow_header - invalid COW header, " | 380 | cow_printf("read_cow_header - invalid COW header, " |
| 380 | "align == 0\n"); | 381 | "align == 0\n"); |
diff --git a/arch/um/drivers/daemon.h b/arch/um/drivers/daemon.h index c2dd1951559..6e0e891f8a0 100644 --- a/arch/um/drivers/daemon.h +++ b/arch/um/drivers/daemon.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #ifndef __DAEMON_H__ | 6 | #ifndef __DAEMON_H__ |
| 7 | #define __DAEMON_H__ | 7 | #define __DAEMON_H__ |
| 8 | 8 | ||
| 9 | #include <net_user.h> | 9 | #include "net_user.h" |
| 10 | 10 | ||
| 11 | #define SWITCH_VERSION 3 | 11 | #define SWITCH_VERSION 3 |
| 12 | 12 | ||
diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c index 7568cc2f3cd..b4a1522f215 100644 --- a/arch/um/drivers/daemon_kern.c +++ b/arch/um/drivers/daemon_kern.c | |||
| @@ -6,9 +6,9 @@ | |||
| 6 | * Licensed under the GPL. | 6 | * Licensed under the GPL. |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/init.h> | 9 | #include "linux/init.h" |
| 10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
| 11 | #include <net_kern.h> | 11 | #include "net_kern.h" |
| 12 | #include "daemon.h" | 12 | #include "daemon.h" |
| 13 | 13 | ||
| 14 | struct daemon_init { | 14 | struct daemon_init { |
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index 8813c10d017..f8e85e0bdac 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c | |||
| @@ -14,9 +14,10 @@ | |||
| 14 | #include <sys/time.h> | 14 | #include <sys/time.h> |
| 15 | #include <sys/un.h> | 15 | #include <sys/un.h> |
| 16 | #include "daemon.h" | 16 | #include "daemon.h" |
| 17 | #include <net_user.h> | 17 | #include "net_user.h" |
| 18 | #include <os.h> | 18 | #include "os.h" |
| 19 | #include <um_malloc.h> | 19 | #include "um_malloc.h" |
| 20 | #include "user.h" | ||
| 20 | 21 | ||
| 21 | enum request_type { REQ_NEW_CONTROL }; | 22 | enum request_type { REQ_NEW_CONTROL }; |
| 22 | 23 | ||
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index a13a427b996..f5a981a1624 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c | |||
| @@ -9,8 +9,10 @@ | |||
| 9 | #include <errno.h> | 9 | #include <errno.h> |
| 10 | #include <termios.h> | 10 | #include <termios.h> |
| 11 | #include "chan_user.h" | 11 | #include "chan_user.h" |
| 12 | #include <os.h> | 12 | #include "kern_constants.h" |
| 13 | #include <um_malloc.h> | 13 | #include "os.h" |
| 14 | #include "um_malloc.h" | ||
| 15 | #include "user.h" | ||
| 14 | 16 | ||
| 15 | struct fd_chan { | 17 | struct fd_chan { |
| 16 | int fd; | 18 | int fd; |
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c index f99b32a4dbf..84dce3fc590 100644 --- a/arch/um/drivers/harddog_user.c +++ b/arch/um/drivers/harddog_user.c | |||
| @@ -6,7 +6,8 @@ | |||
| 6 | #include <stdio.h> | 6 | #include <stdio.h> |
| 7 | #include <unistd.h> | 7 | #include <unistd.h> |
| 8 | #include <errno.h> | 8 | #include <errno.h> |
| 9 | #include <os.h> | 9 | #include "os.h" |
| 10 | #include "user.h" | ||
| 10 | 11 | ||
| 11 | struct dog_data { | 12 | struct dog_data { |
| 12 | int stdin; | 13 | int stdin; |
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index 9b90fdc4b15..f9f6a4e2059 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c | |||
| @@ -3,15 +3,15 @@ | |||
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/fs.h> | 6 | #include "linux/fs.h" |
| 7 | #include <linux/module.h> | 7 | #include "linux/module.h" |
| 8 | #include <linux/slab.h> | 8 | #include "linux/slab.h" |
| 9 | #include <linux/sound.h> | 9 | #include "linux/sound.h" |
| 10 | #include <linux/soundcard.h> | 10 | #include "linux/soundcard.h" |
| 11 | #include <linux/mutex.h> | 11 | #include "linux/mutex.h" |
| 12 | #include <asm/uaccess.h> | 12 | #include "asm/uaccess.h" |
| 13 | #include <init.h> | 13 | #include "init.h" |
| 14 | #include <os.h> | 14 | #include "os.h" |
| 15 | 15 | ||
| 16 | struct hostaudio_state { | 16 | struct hostaudio_state { |
| 17 | int fd; | 17 | int fd; |
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 9ffc28bd4b7..364c8a15c4c 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
| @@ -3,15 +3,15 @@ | |||
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/irqreturn.h> | 6 | #include "linux/irqreturn.h" |
| 7 | #include <linux/kd.h> | 7 | #include "linux/kd.h" |
| 8 | #include <linux/sched.h> | 8 | #include "linux/sched.h" |
| 9 | #include <linux/slab.h> | 9 | #include "linux/slab.h" |
| 10 | #include "chan.h" | 10 | #include "chan_kern.h" |
| 11 | #include <irq_kern.h> | 11 | #include "irq_kern.h" |
| 12 | #include <irq_user.h> | 12 | #include "irq_user.h" |
| 13 | #include <kern_util.h> | 13 | #include "kern_util.h" |
| 14 | #include <os.h> | 14 | #include "os.h" |
| 15 | 15 | ||
| 16 | #define LINE_BUFSIZE 4096 | 16 | #define LINE_BUFSIZE 4096 |
| 17 | 17 | ||
| @@ -19,14 +19,21 @@ static irqreturn_t line_interrupt(int irq, void *data) | |||
| 19 | { | 19 | { |
| 20 | struct chan *chan = data; | 20 | struct chan *chan = data; |
| 21 | struct line *line = chan->line; | 21 | struct line *line = chan->line; |
| 22 | struct tty_struct *tty = tty_port_tty_get(&line->port); | ||
| 23 | 22 | ||
| 24 | if (line) | 23 | if (line) |
| 25 | chan_interrupt(line, tty, irq); | 24 | chan_interrupt(&line->chan_list, &line->task, line->tty, irq); |
| 26 | tty_kref_put(tty); | ||
| 27 | return IRQ_HANDLED; | 25 | return IRQ_HANDLED; |
| 28 | } | 26 | } |
| 29 | 27 | ||
| 28 | static void line_timer_cb(struct work_struct *work) | ||
| 29 | { | ||
| 30 | struct line *line = container_of(work, struct line, task.work); | ||
| 31 | |||
| 32 | if (!line->throttled) | ||
| 33 | chan_interrupt(&line->chan_list, &line->task, line->tty, | ||
| 34 | line->driver->read_irq); | ||
| 35 | } | ||
| 36 | |||
| 30 | /* | 37 | /* |
| 31 | * Returns the free space inside the ring buffer of this line. | 38 | * Returns the free space inside the ring buffer of this line. |
| 32 | * | 39 | * |
| @@ -138,7 +145,7 @@ static int flush_buffer(struct line *line) | |||
| 138 | /* line->buffer + LINE_BUFSIZE is the end of the buffer! */ | 145 | /* line->buffer + LINE_BUFSIZE is the end of the buffer! */ |
| 139 | count = line->buffer + LINE_BUFSIZE - line->head; | 146 | count = line->buffer + LINE_BUFSIZE - line->head; |
| 140 | 147 | ||
| 141 | n = write_chan(line->chan_out, line->head, count, | 148 | n = write_chan(&line->chan_list, line->head, count, |
| 142 | line->driver->write_irq); | 149 | line->driver->write_irq); |
| 143 | if (n < 0) | 150 | if (n < 0) |
| 144 | return n; | 151 | return n; |
| @@ -155,7 +162,7 @@ static int flush_buffer(struct line *line) | |||
| 155 | } | 162 | } |
| 156 | 163 | ||
| 157 | count = line->tail - line->head; | 164 | count = line->tail - line->head; |
| 158 | n = write_chan(line->chan_out, line->head, count, | 165 | n = write_chan(&line->chan_list, line->head, count, |
| 159 | line->driver->write_irq); | 166 | line->driver->write_irq); |
| 160 | 167 | ||
| 161 | if (n < 0) | 168 | if (n < 0) |
| @@ -199,7 +206,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len) | |||
| 199 | if (line->head != line->tail) | 206 | if (line->head != line->tail) |
| 200 | ret = buffer_data(line, buf, len); | 207 | ret = buffer_data(line, buf, len); |
| 201 | else { | 208 | else { |
| 202 | n = write_chan(line->chan_out, buf, len, | 209 | n = write_chan(&line->chan_list, buf, len, |
| 203 | line->driver->write_irq); | 210 | line->driver->write_irq); |
| 204 | if (n < 0) { | 211 | if (n < 0) { |
| 205 | ret = n; | 212 | ret = n; |
| @@ -221,11 +228,97 @@ void line_set_termios(struct tty_struct *tty, struct ktermios * old) | |||
| 221 | /* nothing */ | 228 | /* nothing */ |
| 222 | } | 229 | } |
| 223 | 230 | ||
| 231 | static const struct { | ||
| 232 | int cmd; | ||
| 233 | char *level; | ||
| 234 | char *name; | ||
| 235 | } tty_ioctls[] = { | ||
| 236 | /* don't print these, they flood the log ... */ | ||
| 237 | { TCGETS, NULL, "TCGETS" }, | ||
| 238 | { TCSETS, NULL, "TCSETS" }, | ||
| 239 | { TCSETSW, NULL, "TCSETSW" }, | ||
| 240 | { TCFLSH, NULL, "TCFLSH" }, | ||
| 241 | { TCSBRK, NULL, "TCSBRK" }, | ||
| 242 | |||
| 243 | /* general tty stuff */ | ||
| 244 | { TCSETSF, KERN_DEBUG, "TCSETSF" }, | ||
| 245 | { TCGETA, KERN_DEBUG, "TCGETA" }, | ||
| 246 | { TIOCMGET, KERN_DEBUG, "TIOCMGET" }, | ||
| 247 | { TCSBRKP, KERN_DEBUG, "TCSBRKP" }, | ||
| 248 | { TIOCMSET, KERN_DEBUG, "TIOCMSET" }, | ||
| 249 | |||
| 250 | /* linux-specific ones */ | ||
| 251 | { TIOCLINUX, KERN_INFO, "TIOCLINUX" }, | ||
| 252 | { KDGKBMODE, KERN_INFO, "KDGKBMODE" }, | ||
| 253 | { KDGKBTYPE, KERN_INFO, "KDGKBTYPE" }, | ||
| 254 | { KDSIGACCEPT, KERN_INFO, "KDSIGACCEPT" }, | ||
| 255 | }; | ||
| 256 | |||
| 257 | int line_ioctl(struct tty_struct *tty, unsigned int cmd, | ||
| 258 | unsigned long arg) | ||
| 259 | { | ||
| 260 | int ret; | ||
| 261 | int i; | ||
| 262 | |||
| 263 | ret = 0; | ||
| 264 | switch(cmd) { | ||
| 265 | #ifdef TIOCGETP | ||
| 266 | case TIOCGETP: | ||
| 267 | case TIOCSETP: | ||
| 268 | case TIOCSETN: | ||
| 269 | #endif | ||
| 270 | #ifdef TIOCGETC | ||
| 271 | case TIOCGETC: | ||
| 272 | case TIOCSETC: | ||
| 273 | #endif | ||
| 274 | #ifdef TIOCGLTC | ||
| 275 | case TIOCGLTC: | ||
| 276 | case TIOCSLTC: | ||
| 277 | #endif | ||
| 278 | /* Note: these are out of date as we now have TCGETS2 etc but this | ||
| 279 | whole lot should probably go away */ | ||
| 280 | case TCGETS: | ||
| 281 | case TCSETSF: | ||
| 282 | case TCSETSW: | ||
| 283 | case TCSETS: | ||
| 284 | case TCGETA: | ||
| 285 | case TCSETAF: | ||
| 286 | case TCSETAW: | ||
| 287 | case TCSETA: | ||
| 288 | case TCXONC: | ||
| 289 | case TCFLSH: | ||
| 290 | case TIOCOUTQ: | ||
| 291 | case TIOCINQ: | ||
| 292 | case TIOCGLCKTRMIOS: | ||
| 293 | case TIOCSLCKTRMIOS: | ||
| 294 | case TIOCPKT: | ||
| 295 | case TIOCGSOFTCAR: | ||
| 296 | case TIOCSSOFTCAR: | ||
| 297 | return -ENOIOCTLCMD; | ||
| 298 | #if 0 | ||
| 299 | case TCwhatever: | ||
| 300 | /* do something */ | ||
| 301 | break; | ||
| 302 | #endif | ||
| 303 | default: | ||
| 304 | for (i = 0; i < ARRAY_SIZE(tty_ioctls); i++) | ||
| 305 | if (cmd == tty_ioctls[i].cmd) | ||
| 306 | break; | ||
| 307 | if (i == ARRAY_SIZE(tty_ioctls)) { | ||
| 308 | printk(KERN_ERR "%s: %s: unknown ioctl: 0x%x\n", | ||
| 309 | __func__, tty->name, cmd); | ||
| 310 | } | ||
| 311 | ret = -ENOIOCTLCMD; | ||
| 312 | break; | ||
| 313 | } | ||
| 314 | return ret; | ||
| 315 | } | ||
| 316 | |||
| 224 | void line_throttle(struct tty_struct *tty) | 317 | void line_throttle(struct tty_struct *tty) |
| 225 | { | 318 | { |
| 226 | struct line *line = tty->driver_data; | 319 | struct line *line = tty->driver_data; |
| 227 | 320 | ||
| 228 | deactivate_chan(line->chan_in, line->driver->read_irq); | 321 | deactivate_chan(&line->chan_list, line->driver->read_irq); |
| 229 | line->throttled = 1; | 322 | line->throttled = 1; |
| 230 | } | 323 | } |
| 231 | 324 | ||
| @@ -234,7 +327,8 @@ void line_unthrottle(struct tty_struct *tty) | |||
| 234 | struct line *line = tty->driver_data; | 327 | struct line *line = tty->driver_data; |
| 235 | 328 | ||
| 236 | line->throttled = 0; | 329 | line->throttled = 0; |
| 237 | chan_interrupt(line, tty, line->driver->read_irq); | 330 | chan_interrupt(&line->chan_list, &line->task, tty, |
| 331 | line->driver->read_irq); | ||
| 238 | 332 | ||
| 239 | /* | 333 | /* |
| 240 | * Maybe there is enough stuff pending that calling the interrupt | 334 | * Maybe there is enough stuff pending that calling the interrupt |
| @@ -242,25 +336,24 @@ void line_unthrottle(struct tty_struct *tty) | |||
| 242 | * again and we shouldn't turn the interrupt back on. | 336 | * again and we shouldn't turn the interrupt back on. |
| 243 | */ | 337 | */ |
| 244 | if (!line->throttled) | 338 | if (!line->throttled) |
| 245 | reactivate_chan(line->chan_in, line->driver->read_irq); | 339 | reactivate_chan(&line->chan_list, line->driver->read_irq); |
| 246 | } | 340 | } |
| 247 | 341 | ||
| 248 | static irqreturn_t line_write_interrupt(int irq, void *data) | 342 | static irqreturn_t line_write_interrupt(int irq, void *data) |
| 249 | { | 343 | { |
| 250 | struct chan *chan = data; | 344 | struct chan *chan = data; |
| 251 | struct line *line = chan->line; | 345 | struct line *line = chan->line; |
| 252 | struct tty_struct *tty; | 346 | struct tty_struct *tty = line->tty; |
| 253 | int err; | 347 | int err; |
| 254 | 348 | ||
| 255 | /* | 349 | /* |
| 256 | * Interrupts are disabled here because genirq keep irqs disabled when | 350 | * Interrupts are disabled here because we registered the interrupt with |
| 257 | * calling the action handler. | 351 | * IRQF_DISABLED (see line_setup_irq). |
| 258 | */ | 352 | */ |
| 259 | 353 | ||
| 260 | spin_lock(&line->lock); | 354 | spin_lock(&line->lock); |
| 261 | err = flush_buffer(line); | 355 | err = flush_buffer(line); |
| 262 | if (err == 0) { | 356 | if (err == 0) { |
| 263 | spin_unlock(&line->lock); | ||
| 264 | return IRQ_NONE; | 357 | return IRQ_NONE; |
| 265 | } else if (err < 0) { | 358 | } else if (err < 0) { |
| 266 | line->head = line->buffer; | 359 | line->head = line->buffer; |
| @@ -268,103 +361,124 @@ static irqreturn_t line_write_interrupt(int irq, void *data) | |||
| 268 | } | 361 | } |
| 269 | spin_unlock(&line->lock); | 362 | spin_unlock(&line->lock); |
| 270 | 363 | ||
| 271 | tty = tty_port_tty_get(&line->port); | ||
| 272 | if (tty == NULL) | 364 | if (tty == NULL) |
| 273 | return IRQ_NONE; | 365 | return IRQ_NONE; |
| 274 | 366 | ||
| 275 | tty_wakeup(tty); | 367 | tty_wakeup(tty); |
| 276 | tty_kref_put(tty); | ||
| 277 | |||
| 278 | return IRQ_HANDLED; | 368 | return IRQ_HANDLED; |
| 279 | } | 369 | } |
| 280 | 370 | ||
| 281 | int line_setup_irq(int fd, int input, int output, struct line *line, void *data) | 371 | int line_setup_irq(int fd, int input, int output, struct line *line, void *data) |
| 282 | { | 372 | { |
| 283 | const struct line_driver *driver = line->driver; | 373 | const struct line_driver *driver = line->driver; |
| 284 | int err = 0; | 374 | int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM; |
| 285 | 375 | ||
| 286 | if (input) | 376 | if (input) |
| 287 | err = um_request_irq(driver->read_irq, fd, IRQ_READ, | 377 | err = um_request_irq(driver->read_irq, fd, IRQ_READ, |
| 288 | line_interrupt, IRQF_SHARED, | 378 | line_interrupt, flags, |
| 289 | driver->read_irq_name, data); | 379 | driver->read_irq_name, data); |
| 290 | if (err) | 380 | if (err) |
| 291 | return err; | 381 | return err; |
| 292 | if (output) | 382 | if (output) |
| 293 | err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, | 383 | err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, |
| 294 | line_write_interrupt, IRQF_SHARED, | 384 | line_write_interrupt, flags, |
| 295 | driver->write_irq_name, data); | 385 | driver->write_irq_name, data); |
| 386 | line->have_irq = 1; | ||
| 296 | return err; | 387 | return err; |
| 297 | } | 388 | } |
| 298 | 389 | ||
| 299 | static int line_activate(struct tty_port *port, struct tty_struct *tty) | 390 | /* |
| 391 | * Normally, a driver like this can rely mostly on the tty layer | ||
| 392 | * locking, particularly when it comes to the driver structure. | ||
| 393 | * However, in this case, mconsole requests can come in "from the | ||
| 394 | * side", and race with opens and closes. | ||
| 395 | * | ||
| 396 | * mconsole config requests will want to be sure the device isn't in | ||
| 397 | * use, and get_config, open, and close will want a stable | ||
| 398 | * configuration. The checking and modification of the configuration | ||
| 399 | * is done under a spinlock. Checking whether the device is in use is | ||
| 400 | * line->tty->count > 1, also under the spinlock. | ||
| 401 | * | ||
| 402 | * line->count serves to decide whether the device should be enabled or | ||
| 403 | * disabled on the host. If it's equal to 0, then we are doing the | ||
| 404 | * first open or last close. Otherwise, open and close just return. | ||
| 405 | */ | ||
| 406 | |||
| 407 | int line_open(struct line *lines, struct tty_struct *tty) | ||
| 300 | { | 408 | { |
| 301 | int ret; | 409 | struct line *line = &lines[tty->index]; |
| 302 | struct line *line = tty->driver_data; | 410 | int err = -ENODEV; |
| 411 | |||
| 412 | spin_lock(&line->count_lock); | ||
| 413 | if (!line->valid) | ||
| 414 | goto out_unlock; | ||
| 415 | |||
| 416 | err = 0; | ||
| 417 | if (line->count++) | ||
| 418 | goto out_unlock; | ||
| 419 | |||
| 420 | BUG_ON(tty->driver_data); | ||
| 421 | tty->driver_data = line; | ||
| 422 | line->tty = tty; | ||
| 423 | |||
| 424 | spin_unlock(&line->count_lock); | ||
| 425 | err = enable_chan(line); | ||
| 426 | if (err) /* line_close() will be called by our caller */ | ||
| 427 | return err; | ||
| 303 | 428 | ||
| 304 | ret = enable_chan(line); | 429 | INIT_DELAYED_WORK(&line->task, line_timer_cb); |
| 305 | if (ret) | ||
| 306 | return ret; | ||
| 307 | 430 | ||
| 308 | if (!line->sigio) { | 431 | if (!line->sigio) { |
| 309 | chan_enable_winch(line->chan_out, tty); | 432 | chan_enable_winch(&line->chan_list, tty); |
| 310 | line->sigio = 1; | 433 | line->sigio = 1; |
| 311 | } | 434 | } |
| 312 | 435 | ||
| 313 | chan_window_size(line, &tty->winsize.ws_row, | 436 | chan_window_size(&line->chan_list, &tty->winsize.ws_row, |
| 314 | &tty->winsize.ws_col); | 437 | &tty->winsize.ws_col); |
| 315 | 438 | ||
| 316 | return 0; | 439 | return 0; |
| 440 | |||
| 441 | out_unlock: | ||
| 442 | spin_unlock(&line->count_lock); | ||
| 443 | return err; | ||
| 317 | } | 444 | } |
| 318 | 445 | ||
| 319 | static const struct tty_port_operations line_port_ops = { | 446 | static void unregister_winch(struct tty_struct *tty); |
| 320 | .activate = line_activate, | ||
| 321 | }; | ||
| 322 | 447 | ||
| 323 | int line_open(struct tty_struct *tty, struct file *filp) | 448 | void line_close(struct tty_struct *tty, struct file * filp) |
| 324 | { | 449 | { |
| 325 | struct line *line = tty->driver_data; | 450 | struct line *line = tty->driver_data; |
| 326 | 451 | ||
| 327 | return tty_port_open(&line->port, tty, filp); | 452 | /* |
| 328 | } | 453 | * If line_open fails (and tty->driver_data is never set), |
| 454 | * tty_open will call line_close. So just return in this case. | ||
| 455 | */ | ||
| 456 | if (line == NULL) | ||
| 457 | return; | ||
| 329 | 458 | ||
| 330 | int line_install(struct tty_driver *driver, struct tty_struct *tty, | 459 | /* We ignore the error anyway! */ |
| 331 | struct line *line) | 460 | flush_buffer(line); |
| 332 | { | ||
| 333 | int ret; | ||
| 334 | 461 | ||
| 335 | ret = tty_standard_install(driver, tty); | 462 | spin_lock(&line->count_lock); |
| 336 | if (ret) | 463 | BUG_ON(!line->valid); |
| 337 | return ret; | ||
| 338 | 464 | ||
| 339 | tty->driver_data = line; | 465 | if (--line->count) |
| 466 | goto out_unlock; | ||
| 340 | 467 | ||
| 341 | return 0; | 468 | line->tty = NULL; |
| 342 | } | 469 | tty->driver_data = NULL; |
| 343 | 470 | ||
| 344 | static void unregister_winch(struct tty_struct *tty); | 471 | spin_unlock(&line->count_lock); |
| 345 | |||
| 346 | void line_cleanup(struct tty_struct *tty) | ||
| 347 | { | ||
| 348 | struct line *line = tty->driver_data; | ||
| 349 | 472 | ||
| 350 | if (line->sigio) { | 473 | if (line->sigio) { |
| 351 | unregister_winch(tty); | 474 | unregister_winch(tty); |
| 352 | line->sigio = 0; | 475 | line->sigio = 0; |
| 353 | } | 476 | } |
| 354 | } | ||
| 355 | |||
| 356 | void line_close(struct tty_struct *tty, struct file * filp) | ||
| 357 | { | ||
| 358 | struct line *line = tty->driver_data; | ||
| 359 | 477 | ||
| 360 | tty_port_close(&line->port, tty, filp); | 478 | return; |
| 361 | } | ||
| 362 | |||
| 363 | void line_hangup(struct tty_struct *tty) | ||
| 364 | { | ||
| 365 | struct line *line = tty->driver_data; | ||
| 366 | 479 | ||
| 367 | tty_port_hangup(&line->port); | 480 | out_unlock: |
| 481 | spin_unlock(&line->count_lock); | ||
| 368 | } | 482 | } |
| 369 | 483 | ||
| 370 | void close_lines(struct line *lines, int nlines) | 484 | void close_lines(struct line *lines, int nlines) |
| @@ -372,58 +486,34 @@ void close_lines(struct line *lines, int nlines) | |||
| 372 | int i; | 486 | int i; |
| 373 | 487 | ||
| 374 | for(i = 0; i < nlines; i++) | 488 | for(i = 0; i < nlines; i++) |
| 375 | close_chan(&lines[i]); | 489 | close_chan(&lines[i].chan_list, 0); |
| 376 | } | 490 | } |
| 377 | 491 | ||
| 378 | int setup_one_line(struct line *lines, int n, char *init, | 492 | static int setup_one_line(struct line *lines, int n, char *init, int init_prio, |
| 379 | const struct chan_opts *opts, char **error_out) | 493 | char **error_out) |
| 380 | { | 494 | { |
| 381 | struct line *line = &lines[n]; | 495 | struct line *line = &lines[n]; |
| 382 | struct tty_driver *driver = line->driver->driver; | ||
| 383 | int err = -EINVAL; | 496 | int err = -EINVAL; |
| 384 | 497 | ||
| 385 | if (line->port.count) { | 498 | spin_lock(&line->count_lock); |
| 499 | |||
| 500 | if (line->count) { | ||
| 386 | *error_out = "Device is already open"; | 501 | *error_out = "Device is already open"; |
| 387 | goto out; | 502 | goto out; |
| 388 | } | 503 | } |
| 389 | 504 | ||
| 390 | if (!strcmp(init, "none")) { | 505 | if (line->init_pri <= init_prio) { |
| 391 | if (line->valid) { | 506 | line->init_pri = init_prio; |
| 507 | if (!strcmp(init, "none")) | ||
| 392 | line->valid = 0; | 508 | line->valid = 0; |
| 393 | kfree(line->init_str); | 509 | else { |
| 394 | tty_unregister_device(driver, n); | 510 | line->init_str = init; |
| 395 | parse_chan_pair(NULL, line, n, opts, error_out); | 511 | line->valid = 1; |
| 396 | err = 0; | ||
| 397 | } | ||
| 398 | } else { | ||
| 399 | char *new = kstrdup(init, GFP_KERNEL); | ||
| 400 | if (!new) { | ||
| 401 | *error_out = "Failed to allocate memory"; | ||
| 402 | return -ENOMEM; | ||
| 403 | } | ||
| 404 | if (line->valid) { | ||
| 405 | tty_unregister_device(driver, n); | ||
| 406 | kfree(line->init_str); | ||
| 407 | } | ||
| 408 | line->init_str = new; | ||
| 409 | line->valid = 1; | ||
| 410 | err = parse_chan_pair(new, line, n, opts, error_out); | ||
| 411 | if (!err) { | ||
| 412 | struct device *d = tty_port_register_device(&line->port, | ||
| 413 | driver, n, NULL); | ||
| 414 | if (IS_ERR(d)) { | ||
| 415 | *error_out = "Failed to register device"; | ||
| 416 | err = PTR_ERR(d); | ||
| 417 | parse_chan_pair(NULL, line, n, opts, error_out); | ||
| 418 | } | ||
| 419 | } | ||
| 420 | if (err) { | ||
| 421 | line->init_str = NULL; | ||
| 422 | line->valid = 0; | ||
| 423 | kfree(new); | ||
| 424 | } | 512 | } |
| 425 | } | 513 | } |
| 514 | err = 0; | ||
| 426 | out: | 515 | out: |
| 516 | spin_unlock(&line->count_lock); | ||
| 427 | return err; | 517 | return err; |
| 428 | } | 518 | } |
| 429 | 519 | ||
| @@ -434,43 +524,54 @@ out: | |||
| 434 | * @error_out is an error string in the case of failure; | 524 | * @error_out is an error string in the case of failure; |
| 435 | */ | 525 | */ |
| 436 | 526 | ||
| 437 | int line_setup(char **conf, unsigned int num, char **def, | 527 | int line_setup(struct line *lines, unsigned int num, char *init, |
| 438 | char *init, char *name) | 528 | char **error_out) |
| 439 | { | 529 | { |
| 440 | char *error; | 530 | int i, n, err; |
| 531 | char *end; | ||
| 441 | 532 | ||
| 442 | if (*init == '=') { | 533 | if (*init == '=') { |
| 443 | /* | 534 | /* |
| 444 | * We said con=/ssl= instead of con#=, so we are configuring all | 535 | * We said con=/ssl= instead of con#=, so we are configuring all |
| 445 | * consoles at once. | 536 | * consoles at once. |
| 446 | */ | 537 | */ |
| 447 | *def = init + 1; | 538 | n = -1; |
| 448 | } else { | 539 | } |
| 449 | char *end; | 540 | else { |
| 450 | unsigned n = simple_strtoul(init, &end, 0); | 541 | n = simple_strtoul(init, &end, 0); |
| 451 | |||
| 452 | if (*end != '=') { | 542 | if (*end != '=') { |
| 453 | error = "Couldn't parse device number"; | 543 | *error_out = "Couldn't parse device number"; |
| 454 | goto out; | 544 | return -EINVAL; |
| 455 | } | ||
| 456 | if (n >= num) { | ||
| 457 | error = "Device number out of range"; | ||
| 458 | goto out; | ||
| 459 | } | 545 | } |
| 460 | conf[n] = end + 1; | 546 | init = end; |
| 461 | } | 547 | } |
| 462 | return 0; | 548 | init++; |
| 463 | 549 | ||
| 464 | out: | 550 | if (n >= (signed int) num) { |
| 465 | printk(KERN_ERR "Failed to set up %s with " | 551 | *error_out = "Device number out of range"; |
| 466 | "configuration string \"%s\" : %s\n", name, init, error); | 552 | return -EINVAL; |
| 467 | return -EINVAL; | 553 | } |
| 554 | else if (n >= 0) { | ||
| 555 | err = setup_one_line(lines, n, init, INIT_ONE, error_out); | ||
| 556 | if (err) | ||
| 557 | return err; | ||
| 558 | } | ||
| 559 | else { | ||
| 560 | for(i = 0; i < num; i++) { | ||
| 561 | err = setup_one_line(lines, i, init, INIT_ALL, | ||
| 562 | error_out); | ||
| 563 | if (err) | ||
| 564 | return err; | ||
| 565 | } | ||
| 566 | } | ||
| 567 | return n == -1 ? num : n; | ||
| 468 | } | 568 | } |
| 469 | 569 | ||
| 470 | int line_config(struct line *lines, unsigned int num, char *str, | 570 | int line_config(struct line *lines, unsigned int num, char *str, |
| 471 | const struct chan_opts *opts, char **error_out) | 571 | const struct chan_opts *opts, char **error_out) |
| 472 | { | 572 | { |
| 473 | char *end; | 573 | struct line *line; |
| 574 | char *new; | ||
| 474 | int n; | 575 | int n; |
| 475 | 576 | ||
| 476 | if (*str == '=') { | 577 | if (*str == '=') { |
| @@ -478,17 +579,17 @@ int line_config(struct line *lines, unsigned int num, char *str, | |||
| 478 | return -EINVAL; | 579 | return -EINVAL; |
| 479 | } | 580 | } |
| 480 | 581 | ||
| 481 | n = simple_strtoul(str, &end, 0); | 582 | new = kstrdup(str, GFP_KERNEL); |
| 482 | if (*end++ != '=') { | 583 | if (new == NULL) { |
| 483 | *error_out = "Couldn't parse device number"; | 584 | *error_out = "Failed to allocate memory"; |
| 484 | return -EINVAL; | 585 | return -ENOMEM; |
| 485 | } | ||
| 486 | if (n >= num) { | ||
| 487 | *error_out = "Device number out of range"; | ||
| 488 | return -EINVAL; | ||
| 489 | } | 586 | } |
| 587 | n = line_setup(lines, num, new, error_out); | ||
| 588 | if (n < 0) | ||
| 589 | return n; | ||
| 490 | 590 | ||
| 491 | return setup_one_line(lines, n, end, opts, error_out); | 591 | line = &lines[n]; |
| 592 | return parse_chan_pair(line->init_str, line, n, opts, error_out); | ||
| 492 | } | 593 | } |
| 493 | 594 | ||
| 494 | int line_get_config(char *name, struct line *lines, unsigned int num, char *str, | 595 | int line_get_config(char *name, struct line *lines, unsigned int num, char *str, |
| @@ -511,17 +612,13 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, | |||
| 511 | 612 | ||
| 512 | line = &lines[dev]; | 613 | line = &lines[dev]; |
| 513 | 614 | ||
| 615 | spin_lock(&line->count_lock); | ||
| 514 | if (!line->valid) | 616 | if (!line->valid) |
| 515 | CONFIG_CHUNK(str, size, n, "none", 1); | 617 | CONFIG_CHUNK(str, size, n, "none", 1); |
| 516 | else { | 618 | else if (line->tty == NULL) |
| 517 | struct tty_struct *tty = tty_port_tty_get(&line->port); | 619 | CONFIG_CHUNK(str, size, n, line->init_str, 1); |
| 518 | if (tty == NULL) { | 620 | else n = chan_config_string(&line->chan_list, str, size, error_out); |
| 519 | CONFIG_CHUNK(str, size, n, line->init_str, 1); | 621 | spin_unlock(&line->count_lock); |
| 520 | } else { | ||
| 521 | n = chan_config_string(line, str, size, error_out); | ||
| 522 | tty_kref_put(tty); | ||
| 523 | } | ||
| 524 | } | ||
| 525 | 622 | ||
| 526 | return n; | 623 | return n; |
| 527 | } | 624 | } |
| @@ -543,23 +640,25 @@ int line_id(char **str, int *start_out, int *end_out) | |||
| 543 | 640 | ||
| 544 | int line_remove(struct line *lines, unsigned int num, int n, char **error_out) | 641 | int line_remove(struct line *lines, unsigned int num, int n, char **error_out) |
| 545 | { | 642 | { |
| 546 | if (n >= num) { | 643 | int err; |
| 547 | *error_out = "Device number out of range"; | 644 | char config[sizeof("conxxxx=none\0")]; |
| 548 | return -EINVAL; | 645 | |
| 549 | } | 646 | sprintf(config, "%d=none", n); |
| 550 | return setup_one_line(lines, n, "none", NULL, error_out); | 647 | err = line_setup(lines, num, config, error_out); |
| 648 | if (err >= 0) | ||
| 649 | err = 0; | ||
| 650 | return err; | ||
| 551 | } | 651 | } |
| 552 | 652 | ||
| 553 | int register_lines(struct line_driver *line_driver, | 653 | struct tty_driver *register_lines(struct line_driver *line_driver, |
| 554 | const struct tty_operations *ops, | 654 | const struct tty_operations *ops, |
| 555 | struct line *lines, int nlines) | 655 | struct line *lines, int nlines) |
| 556 | { | 656 | { |
| 557 | struct tty_driver *driver = alloc_tty_driver(nlines); | ||
| 558 | int err; | ||
| 559 | int i; | 657 | int i; |
| 658 | struct tty_driver *driver = alloc_tty_driver(nlines); | ||
| 560 | 659 | ||
| 561 | if (!driver) | 660 | if (!driver) |
| 562 | return -ENOMEM; | 661 | return NULL; |
| 563 | 662 | ||
| 564 | driver->driver_name = line_driver->name; | 663 | driver->driver_name = line_driver->name; |
| 565 | driver->name = line_driver->device_name; | 664 | driver->name = line_driver->device_name; |
| @@ -567,36 +666,54 @@ int register_lines(struct line_driver *line_driver, | |||
| 567 | driver->minor_start = line_driver->minor_start; | 666 | driver->minor_start = line_driver->minor_start; |
| 568 | driver->type = line_driver->type; | 667 | driver->type = line_driver->type; |
| 569 | driver->subtype = line_driver->subtype; | 668 | driver->subtype = line_driver->subtype; |
| 570 | driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | 669 | driver->flags = TTY_DRIVER_REAL_RAW; |
| 571 | driver->init_termios = tty_std_termios; | 670 | driver->init_termios = tty_std_termios; |
| 572 | |||
| 573 | for (i = 0; i < nlines; i++) { | ||
| 574 | tty_port_init(&lines[i].port); | ||
| 575 | lines[i].port.ops = &line_port_ops; | ||
| 576 | spin_lock_init(&lines[i].lock); | ||
| 577 | lines[i].driver = line_driver; | ||
| 578 | INIT_LIST_HEAD(&lines[i].chan_list); | ||
| 579 | } | ||
| 580 | tty_set_operations(driver, ops); | 671 | tty_set_operations(driver, ops); |
| 581 | 672 | ||
| 582 | err = tty_register_driver(driver); | 673 | if (tty_register_driver(driver)) { |
| 583 | if (err) { | ||
| 584 | printk(KERN_ERR "register_lines : can't register %s driver\n", | 674 | printk(KERN_ERR "register_lines : can't register %s driver\n", |
| 585 | line_driver->name); | 675 | line_driver->name); |
| 586 | put_tty_driver(driver); | 676 | put_tty_driver(driver); |
| 587 | for (i = 0; i < nlines; i++) | 677 | return NULL; |
| 588 | tty_port_destroy(&lines[i].port); | 678 | } |
| 589 | return err; | 679 | |
| 680 | for(i = 0; i < nlines; i++) { | ||
| 681 | if (!lines[i].valid) | ||
| 682 | tty_unregister_device(driver, i); | ||
| 590 | } | 683 | } |
| 591 | 684 | ||
| 592 | line_driver->driver = driver; | ||
| 593 | mconsole_register_dev(&line_driver->mc); | 685 | mconsole_register_dev(&line_driver->mc); |
| 594 | return 0; | 686 | return driver; |
| 595 | } | 687 | } |
| 596 | 688 | ||
| 597 | static DEFINE_SPINLOCK(winch_handler_lock); | 689 | static DEFINE_SPINLOCK(winch_handler_lock); |
| 598 | static LIST_HEAD(winch_handlers); | 690 | static LIST_HEAD(winch_handlers); |
| 599 | 691 | ||
| 692 | void lines_init(struct line *lines, int nlines, struct chan_opts *opts) | ||
| 693 | { | ||
| 694 | struct line *line; | ||
| 695 | char *error; | ||
| 696 | int i; | ||
| 697 | |||
| 698 | for(i = 0; i < nlines; i++) { | ||
| 699 | line = &lines[i]; | ||
| 700 | INIT_LIST_HEAD(&line->chan_list); | ||
| 701 | |||
| 702 | if (line->init_str == NULL) | ||
| 703 | continue; | ||
| 704 | |||
| 705 | line->init_str = kstrdup(line->init_str, GFP_KERNEL); | ||
| 706 | if (line->init_str == NULL) | ||
| 707 | printk(KERN_ERR "lines_init - kstrdup returned NULL\n"); | ||
| 708 | |||
| 709 | if (parse_chan_pair(line->init_str, line, i, opts, &error)) { | ||
| 710 | printk(KERN_ERR "parse_chan_pair failed for " | ||
| 711 | "device %d : %s\n", i, error); | ||
| 712 | line->valid = 0; | ||
| 713 | } | ||
| 714 | } | ||
| 715 | } | ||
| 716 | |||
| 600 | struct winch { | 717 | struct winch { |
| 601 | struct list_head list; | 718 | struct list_head list; |
| 602 | int fd; | 719 | int fd; |
| @@ -610,7 +727,7 @@ struct winch { | |||
| 610 | static void __free_winch(struct work_struct *work) | 727 | static void __free_winch(struct work_struct *work) |
| 611 | { | 728 | { |
| 612 | struct winch *winch = container_of(work, struct winch, work); | 729 | struct winch *winch = container_of(work, struct winch, work); |
| 613 | um_free_irq(WINCH_IRQ, winch); | 730 | free_irq(WINCH_IRQ, winch); |
| 614 | 731 | ||
| 615 | if (winch->pid != -1) | 732 | if (winch->pid != -1) |
| 616 | os_kill_process(winch->pid, 1); | 733 | os_kill_process(winch->pid, 1); |
| @@ -660,7 +777,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) | |||
| 660 | if (tty != NULL) { | 777 | if (tty != NULL) { |
| 661 | line = tty->driver_data; | 778 | line = tty->driver_data; |
| 662 | if (line != NULL) { | 779 | if (line != NULL) { |
| 663 | chan_window_size(line, &tty->winsize.ws_row, | 780 | chan_window_size(&line->chan_list, &tty->winsize.ws_row, |
| 664 | &tty->winsize.ws_col); | 781 | &tty->winsize.ws_col); |
| 665 | kill_pgrp(tty->pgrp, SIGWINCH, 1); | 782 | kill_pgrp(tty->pgrp, SIGWINCH, 1); |
| 666 | } | 783 | } |
| @@ -690,7 +807,8 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, | |||
| 690 | .stack = stack }); | 807 | .stack = stack }); |
| 691 | 808 | ||
| 692 | if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, | 809 | if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, |
| 693 | IRQF_SHARED, "winch", winch) < 0) { | 810 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
| 811 | "winch", winch) < 0) { | ||
| 694 | printk(KERN_ERR "register_winch_irq - failed to register " | 812 | printk(KERN_ERR "register_winch_irq - failed to register " |
| 695 | "IRQ\n"); | 813 | "IRQ\n"); |
| 696 | goto out_free; | 814 | goto out_free; |
diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h deleted file mode 100644 index 138a14526d9..00000000000 --- a/arch/um/drivers/line.h +++ /dev/null | |||
| @@ -1,99 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __LINE_H__ | ||
| 7 | #define __LINE_H__ | ||
| 8 | |||
| 9 | #include <linux/list.h> | ||
| 10 | #include <linux/workqueue.h> | ||
| 11 | #include <linux/tty.h> | ||
| 12 | #include <linux/interrupt.h> | ||
| 13 | #include <linux/spinlock.h> | ||
| 14 | #include <linux/mutex.h> | ||
| 15 | #include "chan_user.h" | ||
| 16 | #include "mconsole_kern.h" | ||
| 17 | |||
| 18 | /* There's only two modifiable fields in this - .mc.list and .driver */ | ||
| 19 | struct line_driver { | ||
| 20 | const char *name; | ||
| 21 | const char *device_name; | ||
| 22 | const short major; | ||
| 23 | const short minor_start; | ||
| 24 | const short type; | ||
| 25 | const short subtype; | ||
| 26 | const int read_irq; | ||
| 27 | const char *read_irq_name; | ||
| 28 | const int write_irq; | ||
| 29 | const char *write_irq_name; | ||
| 30 | struct mc_device mc; | ||
| 31 | struct tty_driver *driver; | ||
| 32 | }; | ||
| 33 | |||
| 34 | struct line { | ||
| 35 | struct tty_port port; | ||
| 36 | int valid; | ||
| 37 | |||
| 38 | char *init_str; | ||
| 39 | struct list_head chan_list; | ||
| 40 | struct chan *chan_in, *chan_out; | ||
| 41 | |||
| 42 | /*This lock is actually, mostly, local to*/ | ||
| 43 | spinlock_t lock; | ||
| 44 | int throttled; | ||
| 45 | /* Yes, this is a real circular buffer. | ||
| 46 | * XXX: And this should become a struct kfifo! | ||
| 47 | * | ||
| 48 | * buffer points to a buffer allocated on demand, of length | ||
| 49 | * LINE_BUFSIZE, head to the start of the ring, tail to the end.*/ | ||
| 50 | char *buffer; | ||
| 51 | char *head; | ||
| 52 | char *tail; | ||
| 53 | |||
| 54 | int sigio; | ||
| 55 | struct delayed_work task; | ||
| 56 | const struct line_driver *driver; | ||
| 57 | }; | ||
| 58 | |||
| 59 | extern void line_close(struct tty_struct *tty, struct file * filp); | ||
| 60 | extern int line_open(struct tty_struct *tty, struct file *filp); | ||
| 61 | extern int line_install(struct tty_driver *driver, struct tty_struct *tty, | ||
| 62 | struct line *line); | ||
| 63 | extern void line_cleanup(struct tty_struct *tty); | ||
| 64 | extern void line_hangup(struct tty_struct *tty); | ||
| 65 | extern int line_setup(char **conf, unsigned nlines, char **def, | ||
| 66 | char *init, char *name); | ||
| 67 | extern int line_write(struct tty_struct *tty, const unsigned char *buf, | ||
| 68 | int len); | ||
| 69 | extern int line_put_char(struct tty_struct *tty, unsigned char ch); | ||
| 70 | extern void line_set_termios(struct tty_struct *tty, struct ktermios * old); | ||
| 71 | extern int line_chars_in_buffer(struct tty_struct *tty); | ||
| 72 | extern void line_flush_buffer(struct tty_struct *tty); | ||
| 73 | extern void line_flush_chars(struct tty_struct *tty); | ||
| 74 | extern int line_write_room(struct tty_struct *tty); | ||
| 75 | extern void line_throttle(struct tty_struct *tty); | ||
| 76 | extern void line_unthrottle(struct tty_struct *tty); | ||
| 77 | |||
| 78 | extern char *add_xterm_umid(char *base); | ||
| 79 | extern int line_setup_irq(int fd, int input, int output, struct line *line, | ||
| 80 | void *data); | ||
| 81 | extern void line_close_chan(struct line *line); | ||
| 82 | extern int register_lines(struct line_driver *line_driver, | ||
| 83 | const struct tty_operations *driver, | ||
| 84 | struct line *lines, int nlines); | ||
| 85 | extern int setup_one_line(struct line *lines, int n, char *init, | ||
| 86 | const struct chan_opts *opts, char **error_out); | ||
| 87 | extern void close_lines(struct line *lines, int nlines); | ||
| 88 | |||
| 89 | extern int line_config(struct line *lines, unsigned int sizeof_lines, | ||
| 90 | char *str, const struct chan_opts *opts, | ||
| 91 | char **error_out); | ||
| 92 | extern int line_id(char **str, int *start_out, int *end_out); | ||
| 93 | extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n, | ||
| 94 | char **error_out); | ||
| 95 | extern int line_get_config(char *dev, struct line *lines, | ||
| 96 | unsigned int sizeof_lines, char *str, | ||
| 97 | int size, char **error_out); | ||
| 98 | |||
| 99 | #endif | ||
diff --git a/arch/um/drivers/mconsole.h b/arch/um/drivers/mconsole.h deleted file mode 100644 index 8b22535c62c..00000000000 --- a/arch/um/drivers/mconsole.h +++ /dev/null | |||
| @@ -1,98 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) | ||
| 3 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
| 4 | * Licensed under the GPL | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef __MCONSOLE_H__ | ||
| 8 | #define __MCONSOLE_H__ | ||
| 9 | |||
| 10 | #ifndef __KERNEL__ | ||
| 11 | #include <stdint.h> | ||
| 12 | #define u32 uint32_t | ||
| 13 | #endif | ||
| 14 | |||
| 15 | #include <sysdep/ptrace.h> | ||
| 16 | |||
| 17 | #define MCONSOLE_MAGIC (0xcafebabe) | ||
| 18 | #define MCONSOLE_MAX_DATA (512) | ||
| 19 | #define MCONSOLE_VERSION 2 | ||
| 20 | |||
| 21 | struct mconsole_request { | ||
| 22 | u32 magic; | ||
| 23 | u32 version; | ||
| 24 | u32 len; | ||
| 25 | char data[MCONSOLE_MAX_DATA]; | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct mconsole_reply { | ||
| 29 | u32 err; | ||
| 30 | u32 more; | ||
| 31 | u32 len; | ||
| 32 | char data[MCONSOLE_MAX_DATA]; | ||
| 33 | }; | ||
| 34 | |||
| 35 | struct mconsole_notify { | ||
| 36 | u32 magic; | ||
| 37 | u32 version; | ||
| 38 | enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG, | ||
| 39 | MCONSOLE_USER_NOTIFY } type; | ||
| 40 | u32 len; | ||
| 41 | char data[MCONSOLE_MAX_DATA]; | ||
| 42 | }; | ||
| 43 | |||
| 44 | struct mc_request; | ||
| 45 | |||
| 46 | enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC }; | ||
| 47 | |||
| 48 | struct mconsole_command | ||
| 49 | { | ||
| 50 | char *command; | ||
| 51 | void (*handler)(struct mc_request *req); | ||
| 52 | enum mc_context context; | ||
| 53 | }; | ||
| 54 | |||
| 55 | struct mc_request | ||
| 56 | { | ||
| 57 | int len; | ||
| 58 | int as_interrupt; | ||
| 59 | |||
| 60 | int originating_fd; | ||
| 61 | unsigned int originlen; | ||
| 62 | unsigned char origin[128]; /* sockaddr_un */ | ||
| 63 | |||
| 64 | struct mconsole_request request; | ||
| 65 | struct mconsole_command *cmd; | ||
| 66 | struct uml_pt_regs regs; | ||
| 67 | }; | ||
| 68 | |||
| 69 | extern char mconsole_socket_name[]; | ||
| 70 | |||
| 71 | extern int mconsole_unlink_socket(void); | ||
| 72 | extern int mconsole_reply_len(struct mc_request *req, const char *reply, | ||
| 73 | int len, int err, int more); | ||
| 74 | extern int mconsole_reply(struct mc_request *req, const char *str, int err, | ||
| 75 | int more); | ||
| 76 | |||
| 77 | extern void mconsole_version(struct mc_request *req); | ||
| 78 | extern void mconsole_help(struct mc_request *req); | ||
| 79 | extern void mconsole_halt(struct mc_request *req); | ||
| 80 | extern void mconsole_reboot(struct mc_request *req); | ||
| 81 | extern void mconsole_config(struct mc_request *req); | ||
| 82 | extern void mconsole_remove(struct mc_request *req); | ||
| 83 | extern void mconsole_sysrq(struct mc_request *req); | ||
| 84 | extern void mconsole_cad(struct mc_request *req); | ||
| 85 | extern void mconsole_stop(struct mc_request *req); | ||
| 86 | extern void mconsole_go(struct mc_request *req); | ||
| 87 | extern void mconsole_log(struct mc_request *req); | ||
| 88 | extern void mconsole_proc(struct mc_request *req); | ||
| 89 | extern void mconsole_stack(struct mc_request *req); | ||
| 90 | |||
| 91 | extern int mconsole_get_request(int fd, struct mc_request *req); | ||
| 92 | extern int mconsole_notify(char *sock_name, int type, const void *data, | ||
| 93 | int len); | ||
| 94 | extern char *mconsole_notify_socket(void); | ||
| 95 | extern void lock_notify(void); | ||
| 96 | extern void unlock_notify(void); | ||
| 97 | |||
| 98 | #endif | ||
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 4bd82ac0210..c70e047eed7 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
| @@ -21,19 +21,15 @@ | |||
| 21 | #include <linux/un.h> | 21 | #include <linux/un.h> |
| 22 | #include <linux/workqueue.h> | 22 | #include <linux/workqueue.h> |
| 23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
| 24 | #include <linux/fs.h> | ||
| 25 | #include <linux/mount.h> | ||
| 26 | #include <linux/file.h> | ||
| 27 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
| 28 | #include <asm/switch_to.h> | ||
| 29 | 25 | ||
| 30 | #include <init.h> | 26 | #include "init.h" |
| 31 | #include <irq_kern.h> | 27 | #include "irq_kern.h" |
| 32 | #include <irq_user.h> | 28 | #include "irq_user.h" |
| 33 | #include <kern_util.h> | 29 | #include "kern_util.h" |
| 34 | #include "mconsole.h" | 30 | #include "mconsole.h" |
| 35 | #include "mconsole_kern.h" | 31 | #include "mconsole_kern.h" |
| 36 | #include <os.h> | 32 | #include "os.h" |
| 37 | 33 | ||
| 38 | static int do_unlink_socket(struct notifier_block *notifier, | 34 | static int do_unlink_socket(struct notifier_block *notifier, |
| 39 | unsigned long what, void *data) | 35 | unsigned long what, void *data) |
| @@ -121,14 +117,18 @@ void mconsole_log(struct mc_request *req) | |||
| 121 | mconsole_reply(req, "", 0, 0); | 117 | mconsole_reply(req, "", 0, 0); |
| 122 | } | 118 | } |
| 123 | 119 | ||
| 120 | /* This is a more convoluted version of mconsole_proc, which has some stability | ||
| 121 | * problems; however, we need it fixed, because it is expected that UML users | ||
| 122 | * mount HPPFS instead of procfs on /proc. And we want mconsole_proc to still | ||
| 123 | * show the real procfs content, not the ones from hppfs.*/ | ||
| 124 | #if 0 | ||
| 124 | void mconsole_proc(struct mc_request *req) | 125 | void mconsole_proc(struct mc_request *req) |
| 125 | { | 126 | { |
| 126 | struct vfsmount *mnt = task_active_pid_ns(current)->proc_mnt; | 127 | struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt; |
| 127 | char *buf; | ||
| 128 | int len; | ||
| 129 | struct file *file; | 128 | struct file *file; |
| 130 | int first_chunk = 1; | 129 | int n; |
| 131 | char *ptr = req->request.data; | 130 | char *ptr = req->request.data, *buf; |
| 131 | mm_segment_t old_fs = get_fs(); | ||
| 132 | 132 | ||
| 133 | ptr += strlen("proc"); | 133 | ptr += strlen("proc"); |
| 134 | ptr = skip_spaces(ptr); | 134 | ptr = skip_spaces(ptr); |
| @@ -136,7 +136,6 @@ void mconsole_proc(struct mc_request *req) | |||
| 136 | file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY); | 136 | file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY); |
| 137 | if (IS_ERR(file)) { | 137 | if (IS_ERR(file)) { |
| 138 | mconsole_reply(req, "Failed to open file", 1, 0); | 138 | mconsole_reply(req, "Failed to open file", 1, 0); |
| 139 | printk(KERN_ERR "open /proc/%s: %ld\n", ptr, PTR_ERR(file)); | ||
| 140 | goto out; | 139 | goto out; |
| 141 | } | 140 | } |
| 142 | 141 | ||
| @@ -146,13 +145,62 @@ void mconsole_proc(struct mc_request *req) | |||
| 146 | goto out_fput; | 145 | goto out_fput; |
| 147 | } | 146 | } |
| 148 | 147 | ||
| 149 | do { | 148 | if (file->f_op->read) { |
| 150 | loff_t pos; | 149 | do { |
| 151 | mm_segment_t old_fs = get_fs(); | 150 | loff_t pos; |
| 152 | set_fs(KERNEL_DS); | 151 | set_fs(KERNEL_DS); |
| 153 | len = vfs_read(file, buf, PAGE_SIZE - 1, &pos); | 152 | n = vfs_read(file, buf, PAGE_SIZE - 1, &pos); |
| 154 | set_fs(old_fs); | 153 | file_pos_write(file, pos); |
| 155 | file->f_pos = pos; | 154 | set_fs(old_fs); |
| 155 | if (n >= 0) { | ||
| 156 | buf[n] = '\0'; | ||
| 157 | mconsole_reply(req, buf, 0, (n > 0)); | ||
| 158 | } | ||
| 159 | else { | ||
| 160 | mconsole_reply(req, "Read of file failed", | ||
| 161 | 1, 0); | ||
| 162 | goto out_free; | ||
| 163 | } | ||
| 164 | } while (n > 0); | ||
| 165 | } | ||
| 166 | else mconsole_reply(req, "", 0, 0); | ||
| 167 | |||
| 168 | out_free: | ||
| 169 | kfree(buf); | ||
| 170 | out_fput: | ||
| 171 | fput(file); | ||
| 172 | out: ; | ||
| 173 | } | ||
| 174 | #endif | ||
| 175 | |||
| 176 | void mconsole_proc(struct mc_request *req) | ||
| 177 | { | ||
| 178 | char path[64]; | ||
| 179 | char *buf; | ||
| 180 | int len; | ||
| 181 | int fd; | ||
| 182 | int first_chunk = 1; | ||
| 183 | char *ptr = req->request.data; | ||
| 184 | |||
| 185 | ptr += strlen("proc"); | ||
| 186 | ptr = skip_spaces(ptr); | ||
| 187 | snprintf(path, sizeof(path), "/proc/%s", ptr); | ||
| 188 | |||
| 189 | fd = sys_open(path, 0, 0); | ||
| 190 | if (fd < 0) { | ||
| 191 | mconsole_reply(req, "Failed to open file", 1, 0); | ||
| 192 | printk(KERN_ERR "open %s: %d\n",path,fd); | ||
| 193 | goto out; | ||
| 194 | } | ||
| 195 | |||
| 196 | buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 197 | if (buf == NULL) { | ||
| 198 | mconsole_reply(req, "Failed to allocate buffer", 1, 0); | ||
| 199 | goto out_close; | ||
| 200 | } | ||
| 201 | |||
| 202 | for (;;) { | ||
| 203 | len = sys_read(fd, buf, PAGE_SIZE-1); | ||
| 156 | if (len < 0) { | 204 | if (len < 0) { |
| 157 | mconsole_reply(req, "Read of file failed", 1, 0); | 205 | mconsole_reply(req, "Read of file failed", 1, 0); |
| 158 | goto out_free; | 206 | goto out_free; |
| @@ -162,14 +210,22 @@ void mconsole_proc(struct mc_request *req) | |||
| 162 | mconsole_reply(req, "\n", 0, 1); | 210 | mconsole_reply(req, "\n", 0, 1); |
| 163 | first_chunk = 0; | 211 | first_chunk = 0; |
| 164 | } | 212 | } |
| 165 | buf[len] = '\0'; | 213 | if (len == PAGE_SIZE-1) { |
| 166 | mconsole_reply(req, buf, 0, (len > 0)); | 214 | buf[len] = '\0'; |
| 167 | } while (len > 0); | 215 | mconsole_reply(req, buf, 0, 1); |
| 216 | } else { | ||
| 217 | buf[len] = '\0'; | ||
| 218 | mconsole_reply(req, buf, 0, 0); | ||
| 219 | break; | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 168 | out_free: | 223 | out_free: |
| 169 | kfree(buf); | 224 | kfree(buf); |
| 170 | out_fput: | 225 | out_close: |
| 171 | fput(file); | 226 | sys_close(fd); |
| 172 | out: ; | 227 | out: |
| 228 | /* nothing */; | ||
| 173 | } | 229 | } |
| 174 | 230 | ||
| 175 | #define UML_MCONSOLE_HELPTEXT \ | 231 | #define UML_MCONSOLE_HELPTEXT \ |
| @@ -648,7 +704,6 @@ static void stack_proc(void *arg) | |||
| 648 | struct task_struct *from = current, *to = arg; | 704 | struct task_struct *from = current, *to = arg; |
| 649 | 705 | ||
| 650 | to->thread.saved_task = from; | 706 | to->thread.saved_task = from; |
| 651 | rcu_user_hooks_switch(from, to); | ||
| 652 | switch_to(from, to, from); | 707 | switch_to(from, to, from); |
| 653 | } | 708 | } |
| 654 | 709 | ||
| @@ -718,7 +773,8 @@ static int __init mconsole_init(void) | |||
| 718 | register_reboot_notifier(&reboot_notifier); | 773 | register_reboot_notifier(&reboot_notifier); |
| 719 | 774 | ||
| 720 | err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, | 775 | err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, |
| 721 | IRQF_SHARED, "mconsole", (void *)sock); | 776 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
| 777 | "mconsole", (void *)sock); | ||
| 722 | if (err) { | 778 | if (err) { |
| 723 | printk(KERN_ERR "Failed to get IRQ for management console\n"); | 779 | printk(KERN_ERR "Failed to get IRQ for management console\n"); |
| 724 | goto out; | 780 | goto out; |
diff --git a/arch/um/drivers/mconsole_kern.h b/arch/um/drivers/mconsole_kern.h deleted file mode 100644 index 7a0c6a1ad1d..00000000000 --- a/arch/um/drivers/mconsole_kern.h +++ /dev/null | |||
| @@ -1,52 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __MCONSOLE_KERN_H__ | ||
| 7 | #define __MCONSOLE_KERN_H__ | ||
| 8 | |||
| 9 | #include <linux/list.h> | ||
| 10 | #include "mconsole.h" | ||
| 11 | |||
| 12 | struct mconsole_entry { | ||
| 13 | struct list_head list; | ||
| 14 | struct mc_request request; | ||
| 15 | }; | ||
| 16 | |||
| 17 | /* All these methods are called in process context. */ | ||
| 18 | struct mc_device { | ||
| 19 | struct list_head list; | ||
| 20 | char *name; | ||
| 21 | int (*config)(char *, char **); | ||
| 22 | int (*get_config)(char *, char *, int, char **); | ||
| 23 | int (*id)(char **, int *, int *); | ||
| 24 | int (*remove)(int, char **); | ||
| 25 | }; | ||
| 26 | |||
| 27 | #define CONFIG_CHUNK(str, size, current, chunk, end) \ | ||
| 28 | do { \ | ||
| 29 | current += strlen(chunk); \ | ||
| 30 | if(current >= size) \ | ||
| 31 | str = NULL; \ | ||
| 32 | if(str != NULL){ \ | ||
| 33 | strcpy(str, chunk); \ | ||
| 34 | str += strlen(chunk); \ | ||
| 35 | } \ | ||
| 36 | if(end) \ | ||
| 37 | current++; \ | ||
| 38 | } while(0) | ||
| 39 | |||
| 40 | #ifdef CONFIG_MCONSOLE | ||
| 41 | |||
| 42 | extern void mconsole_register_dev(struct mc_device *new); | ||
| 43 | |||
| 44 | #else | ||
| 45 | |||
| 46 | static inline void mconsole_register_dev(struct mc_device *new) | ||
| 47 | { | ||
| 48 | } | ||
| 49 | |||
| 50 | #endif | ||
| 51 | |||
| 52 | #endif | ||
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index 99209826adb..f8cf4c8bede 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c | |||
| @@ -10,7 +10,9 @@ | |||
| 10 | #include <sys/socket.h> | 10 | #include <sys/socket.h> |
| 11 | #include <sys/uio.h> | 11 | #include <sys/uio.h> |
| 12 | #include <sys/un.h> | 12 | #include <sys/un.h> |
| 13 | #include "kern_constants.h" | ||
| 13 | #include "mconsole.h" | 14 | #include "mconsole.h" |
| 15 | #include "user.h" | ||
| 14 | 16 | ||
| 15 | static struct mconsole_command commands[] = { | 17 | static struct mconsole_command commands[] = { |
| 16 | /* | 18 | /* |
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index 62145c27616..c0ef803c7c7 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
| 19 | 19 | ||
| 20 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
| 21 | #include <mem_user.h> | 21 | #include "mem_user.h" |
| 22 | 22 | ||
| 23 | /* These are set in mmapper_init, which is called at boot time */ | 23 | /* These are set in mmapper_init, which is called at boot time */ |
| 24 | static unsigned long mmapper_size; | 24 | static unsigned long mmapper_size; |
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index b1314ebf1f7..22745b47c82 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c | |||
| @@ -18,12 +18,12 @@ | |||
| 18 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
| 19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 20 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
| 21 | #include <init.h> | 21 | #include "init.h" |
| 22 | #include <irq_kern.h> | 22 | #include "irq_kern.h" |
| 23 | #include <irq_user.h> | 23 | #include "irq_user.h" |
| 24 | #include "mconsole_kern.h" | 24 | #include "mconsole_kern.h" |
| 25 | #include <net_kern.h> | 25 | #include "net_kern.h" |
| 26 | #include <net_user.h> | 26 | #include "net_user.h" |
| 27 | 27 | ||
| 28 | #define DRIVER_NAME "uml-netdev" | 28 | #define DRIVER_NAME "uml-netdev" |
| 29 | 29 | ||
| @@ -161,7 +161,7 @@ static int uml_net_open(struct net_device *dev) | |||
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt, | 163 | err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt, |
| 164 | IRQF_SHARED, dev->name, dev); | 164 | IRQF_DISABLED | IRQF_SHARED, dev->name, dev); |
| 165 | if (err != 0) { | 165 | if (err != 0) { |
| 166 | printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); | 166 | printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); |
| 167 | err = -ENETUNREACH; | 167 | err = -ENETUNREACH; |
| @@ -195,7 +195,7 @@ static int uml_net_close(struct net_device *dev) | |||
| 195 | 195 | ||
| 196 | netif_stop_queue(dev); | 196 | netif_stop_queue(dev); |
| 197 | 197 | ||
| 198 | um_free_irq(dev->irq, dev); | 198 | free_irq(dev->irq, dev); |
| 199 | if (lp->close != NULL) | 199 | if (lp->close != NULL) |
| 200 | (*lp->close)(lp->fd, &lp->user); | 200 | (*lp->close)(lp->fd, &lp->user); |
| 201 | lp->fd = -1; | 201 | lp->fd = -1; |
| @@ -293,7 +293,7 @@ static void uml_net_user_timer_expire(unsigned long _conn) | |||
| 293 | #endif | 293 | #endif |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | static int setup_etheraddr(char *str, unsigned char *addr, char *name) | 296 | static void setup_etheraddr(char *str, unsigned char *addr, char *name) |
| 297 | { | 297 | { |
| 298 | char *end; | 298 | char *end; |
| 299 | int i; | 299 | int i; |
| @@ -334,13 +334,12 @@ static int setup_etheraddr(char *str, unsigned char *addr, char *name) | |||
| 334 | addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4], | 334 | addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4], |
| 335 | addr[5]); | 335 | addr[5]); |
| 336 | } | 336 | } |
| 337 | return 0; | 337 | return; |
| 338 | 338 | ||
| 339 | random: | 339 | random: |
| 340 | printk(KERN_INFO | 340 | printk(KERN_INFO |
| 341 | "Choosing a random ethernet address for device %s\n", name); | 341 | "Choosing a random ethernet address for device %s\n", name); |
| 342 | eth_random_addr(addr); | 342 | random_ether_addr(addr); |
| 343 | return 1; | ||
| 344 | } | 343 | } |
| 345 | 344 | ||
| 346 | static DEFINE_SPINLOCK(devices_lock); | 345 | static DEFINE_SPINLOCK(devices_lock); |
| @@ -369,7 +368,7 @@ static const struct net_device_ops uml_netdev_ops = { | |||
| 369 | .ndo_open = uml_net_open, | 368 | .ndo_open = uml_net_open, |
| 370 | .ndo_stop = uml_net_close, | 369 | .ndo_stop = uml_net_close, |
| 371 | .ndo_start_xmit = uml_net_start_xmit, | 370 | .ndo_start_xmit = uml_net_start_xmit, |
| 372 | .ndo_set_rx_mode = uml_net_set_multicast_list, | 371 | .ndo_set_multicast_list = uml_net_set_multicast_list, |
| 373 | .ndo_tx_timeout = uml_net_tx_timeout, | 372 | .ndo_tx_timeout = uml_net_tx_timeout, |
| 374 | .ndo_set_mac_address = eth_mac_addr, | 373 | .ndo_set_mac_address = eth_mac_addr, |
| 375 | .ndo_change_mtu = uml_net_change_mtu, | 374 | .ndo_change_mtu = uml_net_change_mtu, |
| @@ -392,7 +391,6 @@ static void eth_configure(int n, void *init, char *mac, | |||
| 392 | struct net_device *dev; | 391 | struct net_device *dev; |
| 393 | struct uml_net_private *lp; | 392 | struct uml_net_private *lp; |
| 394 | int err, size; | 393 | int err, size; |
| 395 | int random_mac; | ||
| 396 | 394 | ||
| 397 | size = transport->private_size + sizeof(struct uml_net_private); | 395 | size = transport->private_size + sizeof(struct uml_net_private); |
| 398 | 396 | ||
| @@ -419,7 +417,7 @@ static void eth_configure(int n, void *init, char *mac, | |||
| 419 | */ | 417 | */ |
| 420 | snprintf(dev->name, sizeof(dev->name), "eth%d", n); | 418 | snprintf(dev->name, sizeof(dev->name), "eth%d", n); |
| 421 | 419 | ||
| 422 | random_mac = setup_etheraddr(mac, device->mac, dev->name); | 420 | setup_etheraddr(mac, device->mac, dev->name); |
| 423 | 421 | ||
| 424 | printk(KERN_INFO "Netdevice %d (%pM) : ", n, device->mac); | 422 | printk(KERN_INFO "Netdevice %d (%pM) : ", n, device->mac); |
| 425 | 423 | ||
| @@ -476,9 +474,6 @@ static void eth_configure(int n, void *init, char *mac, | |||
| 476 | 474 | ||
| 477 | /* don't use eth_mac_addr, it will not work here */ | 475 | /* don't use eth_mac_addr, it will not work here */ |
| 478 | memcpy(dev->dev_addr, device->mac, ETH_ALEN); | 476 | memcpy(dev->dev_addr, device->mac, ETH_ALEN); |
| 479 | if (random_mac) | ||
| 480 | dev->addr_assign_type |= NET_ADDR_RANDOM; | ||
| 481 | |||
| 482 | dev->mtu = transport->user->mtu; | 477 | dev->mtu = transport->user->mtu; |
| 483 | dev->netdev_ops = ¨_netdev_ops; | 478 | dev->netdev_ops = ¨_netdev_ops; |
| 484 | dev->ethtool_ops = ¨_net_ethtool_ops; | 479 | dev->ethtool_ops = ¨_net_ethtool_ops; |
| @@ -835,7 +830,7 @@ static void close_devices(void) | |||
| 835 | spin_lock(&opened_lock); | 830 | spin_lock(&opened_lock); |
| 836 | list_for_each(ele, &opened) { | 831 | list_for_each(ele, &opened) { |
| 837 | lp = list_entry(ele, struct uml_net_private, list); | 832 | lp = list_entry(ele, struct uml_net_private, list); |
| 838 | um_free_irq(lp->dev->irq, lp->dev); | 833 | free_irq(lp->dev->irq, lp->dev); |
| 839 | if ((lp->close != NULL) && (lp->fd >= 0)) | 834 | if ((lp->close != NULL) && (lp->fd >= 0)) |
| 840 | (*lp->close)(lp->fd, &lp->user); | 835 | (*lp->close)(lp->fd, &lp->user); |
| 841 | if (lp->remove != NULL) | 836 | if (lp->remove != NULL) |
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index cd14157b556..520118888f1 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c | |||
| @@ -11,9 +11,11 @@ | |||
| 11 | #include <string.h> | 11 | #include <string.h> |
| 12 | #include <sys/socket.h> | 12 | #include <sys/socket.h> |
| 13 | #include <sys/wait.h> | 13 | #include <sys/wait.h> |
| 14 | #include <net_user.h> | 14 | #include "net_user.h" |
| 15 | #include <os.h> | 15 | #include "kern_constants.h" |
| 16 | #include <um_malloc.h> | 16 | #include "os.h" |
| 17 | #include "um_malloc.h" | ||
| 18 | #include "user.h" | ||
| 17 | 19 | ||
| 18 | int tap_open_common(void *dev, char *gate_addr) | 20 | int tap_open_common(void *dev, char *gate_addr) |
| 19 | { | 21 | { |
diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c index 10495747ce8..2b45a1446c8 100644 --- a/arch/um/drivers/null.c +++ b/arch/um/drivers/null.c | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <errno.h> | 7 | #include <errno.h> |
| 8 | #include <fcntl.h> | 8 | #include <fcntl.h> |
| 9 | #include "chan_user.h" | 9 | #include "chan_user.h" |
| 10 | #include <os.h> | 10 | #include "os.h" |
| 11 | 11 | ||
| 12 | /* This address is used only as a unique identifier */ | 12 | /* This address is used only as a unique identifier */ |
| 13 | static int null_chan; | 13 | static int null_chan; |
diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c index be0fb57bd1d..2860525f8ff 100644 --- a/arch/um/drivers/pcap_kern.c +++ b/arch/um/drivers/pcap_kern.c | |||
| @@ -3,9 +3,9 @@ | |||
| 3 | * Licensed under the GPL. | 3 | * Licensed under the GPL. |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/init.h> | 6 | #include "linux/init.h" |
| 7 | #include <linux/netdevice.h> | 7 | #include <linux/netdevice.h> |
| 8 | #include <net_kern.h> | 8 | #include "net_kern.h" |
| 9 | #include "pcap_user.h" | 9 | #include "pcap_user.h" |
| 10 | 10 | ||
| 11 | struct pcap_init { | 11 | struct pcap_init { |
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c index c07b9c752c8..5f903587d69 100644 --- a/arch/um/drivers/pcap_user.c +++ b/arch/um/drivers/pcap_user.c | |||
| @@ -7,9 +7,11 @@ | |||
| 7 | #include <pcap.h> | 7 | #include <pcap.h> |
| 8 | #include <string.h> | 8 | #include <string.h> |
| 9 | #include <asm/types.h> | 9 | #include <asm/types.h> |
| 10 | #include <net_user.h> | 10 | #include "net_user.h" |
| 11 | #include "pcap_user.h" | 11 | #include "pcap_user.h" |
| 12 | #include <um_malloc.h> | 12 | #include "kern_constants.h" |
| 13 | #include "um_malloc.h" | ||
| 14 | #include "user.h" | ||
| 13 | 15 | ||
| 14 | #define PCAP_FD(p) (*(int *)(p)) | 16 | #define PCAP_FD(p) (*(int *)(p)) |
| 15 | 17 | ||
diff --git a/arch/um/drivers/pcap_user.h b/arch/um/drivers/pcap_user.h index 1ca7c764cc6..d8ba6153f91 100644 --- a/arch/um/drivers/pcap_user.h +++ b/arch/um/drivers/pcap_user.h | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <net_user.h> | 6 | #include "net_user.h" |
| 7 | 7 | ||
| 8 | struct pcap_data { | 8 | struct pcap_data { |
| 9 | char *host_if; | 9 | char *host_if; |
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index 40ca5cc275e..a11573be096 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c | |||
| @@ -3,16 +3,16 @@ | |||
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/completion.h> | 6 | #include "linux/completion.h" |
| 7 | #include <linux/interrupt.h> | 7 | #include "linux/interrupt.h" |
| 8 | #include <linux/list.h> | 8 | #include "linux/list.h" |
| 9 | #include <linux/mutex.h> | 9 | #include "linux/mutex.h" |
| 10 | #include <linux/slab.h> | 10 | #include "linux/slab.h" |
| 11 | #include <linux/workqueue.h> | 11 | #include "linux/workqueue.h" |
| 12 | #include <asm/atomic.h> | 12 | #include "asm/atomic.h" |
| 13 | #include <init.h> | 13 | #include "init.h" |
| 14 | #include <irq_kern.h> | 14 | #include "irq_kern.h" |
| 15 | #include <os.h> | 15 | #include "os.h" |
| 16 | #include "port.h" | 16 | #include "port.h" |
| 17 | 17 | ||
| 18 | struct port_list { | 18 | struct port_list { |
| @@ -100,7 +100,8 @@ static int port_accept(struct port_list *port) | |||
| 100 | .port = port }); | 100 | .port = port }); |
| 101 | 101 | ||
| 102 | if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, | 102 | if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, |
| 103 | IRQF_SHARED, "telnetd", conn)) { | 103 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
| 104 | "telnetd", conn)) { | ||
| 104 | printk(KERN_ERR "port_accept : failed to get IRQ for " | 105 | printk(KERN_ERR "port_accept : failed to get IRQ for " |
| 105 | "telnetd\n"); | 106 | "telnetd\n"); |
| 106 | goto out_free; | 107 | goto out_free; |
| @@ -183,7 +184,8 @@ void *port_data(int port_num) | |||
| 183 | } | 184 | } |
| 184 | 185 | ||
| 185 | if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, | 186 | if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, |
| 186 | IRQF_SHARED, "port", port)) { | 187 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
| 188 | "port", port)) { | ||
| 187 | printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); | 189 | printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); |
| 188 | goto out_close; | 190 | goto out_close; |
| 189 | } | 191 | } |
| @@ -252,7 +254,7 @@ int port_wait(void *data) | |||
| 252 | * connection. Then we loop here throwing out failed | 254 | * connection. Then we loop here throwing out failed |
| 253 | * connections until a good one is found. | 255 | * connections until a good one is found. |
| 254 | */ | 256 | */ |
| 255 | um_free_irq(TELNETD_IRQ, conn); | 257 | free_irq(TELNETD_IRQ, conn); |
| 256 | 258 | ||
| 257 | if (conn->fd >= 0) | 259 | if (conn->fd >= 0) |
| 258 | break; | 260 | break; |
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index 9a8e1b64c22..b49bf56a56a 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c | |||
| @@ -10,9 +10,11 @@ | |||
| 10 | #include <unistd.h> | 10 | #include <unistd.h> |
| 11 | #include <netinet/in.h> | 11 | #include <netinet/in.h> |
| 12 | #include "chan_user.h" | 12 | #include "chan_user.h" |
| 13 | #include <os.h> | 13 | #include "kern_constants.h" |
| 14 | #include "os.h" | ||
| 14 | #include "port.h" | 15 | #include "port.h" |
| 15 | #include <um_malloc.h> | 16 | #include "um_malloc.h" |
| 17 | #include "user.h" | ||
| 16 | 18 | ||
| 17 | struct port_chan { | 19 | struct port_chan { |
| 18 | int raw; | 20 | int raw; |
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index f1fcc2cedb5..1113911dcb2 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c | |||
| @@ -12,8 +12,10 @@ | |||
| 12 | #include <termios.h> | 12 | #include <termios.h> |
| 13 | #include <sys/stat.h> | 13 | #include <sys/stat.h> |
| 14 | #include "chan_user.h" | 14 | #include "chan_user.h" |
| 15 | #include <os.h> | 15 | #include "kern_constants.h" |
| 16 | #include <um_malloc.h> | 16 | #include "os.h" |
| 17 | #include "um_malloc.h" | ||
| 18 | #include "user.h" | ||
| 17 | 19 | ||
| 18 | struct pty_chan { | 20 | struct pty_chan { |
| 19 | void (*announce)(char *dev_name, int dev); | 21 | void (*announce)(char *dev_name, int dev); |
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index 9e3a7220582..981085a93f3 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | #include <linux/miscdevice.h> | 13 | #include <linux/miscdevice.h> |
| 14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
| 15 | #include <asm/uaccess.h> | 15 | #include <asm/uaccess.h> |
| 16 | #include <irq_kern.h> | 16 | #include "irq_kern.h" |
| 17 | #include <os.h> | 17 | #include "os.h" |
| 18 | 18 | ||
| 19 | /* | 19 | /* |
| 20 | * core module and version information | 20 | * core module and version information |
| @@ -131,7 +131,8 @@ static int __init rng_init (void) | |||
| 131 | random_fd = err; | 131 | random_fd = err; |
| 132 | 132 | ||
| 133 | err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt, | 133 | err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt, |
| 134 | 0, "random", NULL); | 134 | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random", |
| 135 | NULL); | ||
| 135 | if (err) | 136 | if (err) |
| 136 | goto err_out_cleanup_hw; | 137 | goto err_out_cleanup_hw; |
| 137 | 138 | ||
diff --git a/arch/um/drivers/slip_common.c b/arch/um/drivers/slip_common.c index f597fa7c91d..e89cfc68fc3 100644 --- a/arch/um/drivers/slip_common.c +++ b/arch/um/drivers/slip_common.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | #include <string.h> | 1 | #include <string.h> |
| 2 | #include "slip_common.h" | 2 | #include "slip_common.h" |
| 3 | #include <net_user.h> | 3 | #include "net_user.h" |
| 4 | 4 | ||
| 5 | int slip_proto_read(int fd, void *buf, int len, struct slip_proto *slip) | 5 | int slip_proto_read(int fd, void *buf, int len, struct slip_proto *slip) |
| 6 | { | 6 | { |
diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c index ed5249fc057..dd2aadc14af 100644 --- a/arch/um/drivers/slip_kern.c +++ b/arch/um/drivers/slip_kern.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include <linux/if_arp.h> | 6 | #include <linux/if_arp.h> |
| 7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
| 8 | #include <linux/netdevice.h> | 8 | #include <linux/netdevice.h> |
| 9 | #include <net_kern.h> | 9 | #include "net_kern.h" |
| 10 | #include "slip.h" | 10 | #include "slip.h" |
| 11 | 11 | ||
| 12 | struct slip_init { | 12 | struct slip_init { |
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index 55c290d925f..cbacfc4e63e 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c | |||
| @@ -11,10 +11,12 @@ | |||
| 11 | #include <string.h> | 11 | #include <string.h> |
| 12 | #include <sys/termios.h> | 12 | #include <sys/termios.h> |
| 13 | #include <sys/wait.h> | 13 | #include <sys/wait.h> |
| 14 | #include <net_user.h> | 14 | #include "kern_constants.h" |
| 15 | #include <os.h> | 15 | #include "net_user.h" |
| 16 | #include "os.h" | ||
| 16 | #include "slip.h" | 17 | #include "slip.h" |
| 17 | #include <um_malloc.h> | 18 | #include "um_malloc.h" |
| 19 | #include "user.h" | ||
| 18 | 20 | ||
| 19 | static int slip_user_init(void *data, void *dev) | 21 | static int slip_user_init(void *data, void *dev) |
| 20 | { | 22 | { |
diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c index 4ef11ca7cac..e376284f0fb 100644 --- a/arch/um/drivers/slirp_kern.c +++ b/arch/um/drivers/slirp_kern.c | |||
| @@ -4,11 +4,11 @@ | |||
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/if_arp.h> | 6 | #include <linux/if_arp.h> |
| 7 | #include <linux/init.h> | 7 | #include "linux/init.h" |
| 8 | #include <linux/netdevice.h> | 8 | #include <linux/netdevice.h> |
| 9 | #include <linux/string.h> | 9 | #include <linux/string.h> |
| 10 | #include <net_kern.h> | 10 | #include "net_kern.h" |
| 11 | #include <net_user.h> | 11 | #include "net_user.h" |
| 12 | #include "slirp.h" | 12 | #include "slirp.h" |
| 13 | 13 | ||
| 14 | struct slirp_init { | 14 | struct slirp_init { |
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c index c999d187abb..a0ada8fec72 100644 --- a/arch/um/drivers/slirp_user.c +++ b/arch/um/drivers/slirp_user.c | |||
| @@ -7,9 +7,11 @@ | |||
| 7 | #include <errno.h> | 7 | #include <errno.h> |
| 8 | #include <string.h> | 8 | #include <string.h> |
| 9 | #include <sys/wait.h> | 9 | #include <sys/wait.h> |
| 10 | #include <net_user.h> | 10 | #include "kern_constants.h" |
| 11 | #include <os.h> | 11 | #include "net_user.h" |
| 12 | #include "os.h" | ||
| 12 | #include "slirp.h" | 13 | #include "slirp.h" |
| 14 | #include "user.h" | ||
| 13 | 15 | ||
| 14 | static int slirp_user_init(void *data, void *dev) | 16 | static int slirp_user_init(void *data, void *dev) |
| 15 | { | 17 | { |
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 16fdd0a0f9d..f1786e64607 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c | |||
| @@ -3,23 +3,31 @@ | |||
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/fs.h> | 6 | #include "linux/fs.h" |
| 7 | #include <linux/tty.h> | 7 | #include "linux/tty.h" |
| 8 | #include <linux/tty_driver.h> | 8 | #include "linux/tty_driver.h" |
| 9 | #include <linux/major.h> | 9 | #include "linux/major.h" |
| 10 | #include <linux/mm.h> | 10 | #include "linux/mm.h" |
| 11 | #include <linux/init.h> | 11 | #include "linux/init.h" |
| 12 | #include <linux/console.h> | 12 | #include "linux/console.h" |
| 13 | #include <asm/termbits.h> | 13 | #include "asm/termbits.h" |
| 14 | #include <asm/irq.h> | 14 | #include "asm/irq.h" |
| 15 | #include "line.h" | ||
| 15 | #include "ssl.h" | 16 | #include "ssl.h" |
| 16 | #include "chan.h" | 17 | #include "chan_kern.h" |
| 17 | #include <init.h> | 18 | #include "kern.h" |
| 18 | #include <irq_user.h> | 19 | #include "init.h" |
| 20 | #include "irq_user.h" | ||
| 19 | #include "mconsole_kern.h" | 21 | #include "mconsole_kern.h" |
| 20 | 22 | ||
| 21 | static const int ssl_version = 1; | 23 | static const int ssl_version = 1; |
| 22 | 24 | ||
| 25 | /* Referenced only by tty_driver below - presumably it's locked correctly | ||
| 26 | * by the tty driver. | ||
| 27 | */ | ||
| 28 | |||
| 29 | static struct tty_driver *ssl_driver; | ||
| 30 | |||
| 23 | #define NR_PORTS 64 | 31 | #define NR_PORTS 64 |
| 24 | 32 | ||
| 25 | static void ssl_announce(char *dev_name, int dev) | 33 | static void ssl_announce(char *dev_name, int dev) |
| @@ -65,9 +73,8 @@ static struct line_driver driver = { | |||
| 65 | /* The array is initialized by line_init, at initcall time. The | 73 | /* The array is initialized by line_init, at initcall time. The |
| 66 | * elements are locked individually as needed. | 74 | * elements are locked individually as needed. |
| 67 | */ | 75 | */ |
| 68 | static char *conf[NR_PORTS]; | 76 | static struct line serial_lines[NR_PORTS] = |
| 69 | static char *def_conf = CONFIG_SSL_CHAN; | 77 | { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) }; |
| 70 | static struct line serial_lines[NR_PORTS]; | ||
| 71 | 78 | ||
| 72 | static int ssl_config(char *str, char **error_out) | 79 | static int ssl_config(char *str, char **error_out) |
| 73 | { | 80 | { |
| @@ -87,13 +94,40 @@ static int ssl_remove(int n, char **error_out) | |||
| 87 | error_out); | 94 | error_out); |
| 88 | } | 95 | } |
| 89 | 96 | ||
| 90 | static int ssl_install(struct tty_driver *driver, struct tty_struct *tty) | 97 | static int ssl_open(struct tty_struct *tty, struct file *filp) |
| 98 | { | ||
| 99 | int err = line_open(serial_lines, tty); | ||
| 100 | |||
| 101 | if (err) | ||
| 102 | printk(KERN_ERR "Failed to open serial line %d, err = %d\n", | ||
| 103 | tty->index, err); | ||
| 104 | |||
| 105 | return err; | ||
| 106 | } | ||
| 107 | |||
| 108 | #if 0 | ||
| 109 | static void ssl_flush_buffer(struct tty_struct *tty) | ||
| 110 | { | ||
| 111 | return; | ||
| 112 | } | ||
| 113 | |||
| 114 | static void ssl_stop(struct tty_struct *tty) | ||
| 115 | { | ||
| 116 | printk(KERN_ERR "Someone should implement ssl_stop\n"); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void ssl_start(struct tty_struct *tty) | ||
| 91 | { | 120 | { |
| 92 | return line_install(driver, tty, &serial_lines[tty->index]); | 121 | printk(KERN_ERR "Someone should implement ssl_start\n"); |
| 93 | } | 122 | } |
| 94 | 123 | ||
| 124 | void ssl_hangup(struct tty_struct *tty) | ||
| 125 | { | ||
| 126 | } | ||
| 127 | #endif | ||
| 128 | |||
| 95 | static const struct tty_operations ssl_ops = { | 129 | static const struct tty_operations ssl_ops = { |
| 96 | .open = line_open, | 130 | .open = ssl_open, |
| 97 | .close = line_close, | 131 | .close = line_close, |
| 98 | .write = line_write, | 132 | .write = line_write, |
| 99 | .put_char = line_put_char, | 133 | .put_char = line_put_char, |
| @@ -102,11 +136,14 @@ static const struct tty_operations ssl_ops = { | |||
| 102 | .flush_buffer = line_flush_buffer, | 136 | .flush_buffer = line_flush_buffer, |
| 103 | .flush_chars = line_flush_chars, | 137 | .flush_chars = line_flush_chars, |
| 104 | .set_termios = line_set_termios, | 138 | .set_termios = line_set_termios, |
| 139 | .ioctl = line_ioctl, | ||
| 105 | .throttle = line_throttle, | 140 | .throttle = line_throttle, |
| 106 | .unthrottle = line_unthrottle, | 141 | .unthrottle = line_unthrottle, |
| 107 | .install = ssl_install, | 142 | #if 0 |
| 108 | .cleanup = line_cleanup, | 143 | .stop = ssl_stop, |
| 109 | .hangup = line_hangup, | 144 | .start = ssl_start, |
| 145 | .hangup = ssl_hangup, | ||
| 146 | #endif | ||
| 110 | }; | 147 | }; |
| 111 | 148 | ||
| 112 | /* Changed by ssl_init and referenced by ssl_exit, which are both serialized | 149 | /* Changed by ssl_init and referenced by ssl_exit, which are both serialized |
| @@ -121,14 +158,14 @@ static void ssl_console_write(struct console *c, const char *string, | |||
| 121 | unsigned long flags; | 158 | unsigned long flags; |
| 122 | 159 | ||
| 123 | spin_lock_irqsave(&line->lock, flags); | 160 | spin_lock_irqsave(&line->lock, flags); |
| 124 | console_write_chan(line->chan_out, string, len); | 161 | console_write_chan(&line->chan_list, string, len); |
| 125 | spin_unlock_irqrestore(&line->lock, flags); | 162 | spin_unlock_irqrestore(&line->lock, flags); |
| 126 | } | 163 | } |
| 127 | 164 | ||
| 128 | static struct tty_driver *ssl_console_device(struct console *c, int *index) | 165 | static struct tty_driver *ssl_console_device(struct console *c, int *index) |
| 129 | { | 166 | { |
| 130 | *index = c->index; | 167 | *index = c->index; |
| 131 | return driver.driver; | 168 | return ssl_driver; |
| 132 | } | 169 | } |
| 133 | 170 | ||
| 134 | static int ssl_console_setup(struct console *co, char *options) | 171 | static int ssl_console_setup(struct console *co, char *options) |
| @@ -151,30 +188,17 @@ static struct console ssl_cons = { | |||
| 151 | static int ssl_init(void) | 188 | static int ssl_init(void) |
| 152 | { | 189 | { |
| 153 | char *new_title; | 190 | char *new_title; |
| 154 | int err; | ||
| 155 | int i; | ||
| 156 | 191 | ||
| 157 | printk(KERN_INFO "Initializing software serial port version %d\n", | 192 | printk(KERN_INFO "Initializing software serial port version %d\n", |
| 158 | ssl_version); | 193 | ssl_version); |
| 159 | 194 | ssl_driver = register_lines(&driver, &ssl_ops, serial_lines, | |
| 160 | err = register_lines(&driver, &ssl_ops, serial_lines, | ||
| 161 | ARRAY_SIZE(serial_lines)); | 195 | ARRAY_SIZE(serial_lines)); |
| 162 | if (err) | ||
| 163 | return err; | ||
| 164 | 196 | ||
| 165 | new_title = add_xterm_umid(opts.xterm_title); | 197 | new_title = add_xterm_umid(opts.xterm_title); |
| 166 | if (new_title != NULL) | 198 | if (new_title != NULL) |
| 167 | opts.xterm_title = new_title; | 199 | opts.xterm_title = new_title; |
| 168 | 200 | ||
| 169 | for (i = 0; i < NR_PORTS; i++) { | 201 | lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts); |
| 170 | char *error; | ||
| 171 | char *s = conf[i]; | ||
| 172 | if (!s) | ||
| 173 | s = def_conf; | ||
| 174 | if (setup_one_line(serial_lines, i, s, &opts, &error)) | ||
| 175 | printk(KERN_ERR "setup_one_line failed for " | ||
| 176 | "device %d : %s\n", i, error); | ||
| 177 | } | ||
| 178 | 202 | ||
| 179 | ssl_init_done = 1; | 203 | ssl_init_done = 1; |
| 180 | register_console(&ssl_cons); | 204 | register_console(&ssl_cons); |
| @@ -192,7 +216,14 @@ __uml_exitcall(ssl_exit); | |||
| 192 | 216 | ||
| 193 | static int ssl_chan_setup(char *str) | 217 | static int ssl_chan_setup(char *str) |
| 194 | { | 218 | { |
| 195 | line_setup(conf, NR_PORTS, &def_conf, str, "serial line"); | 219 | char *error; |
| 220 | int ret; | ||
| 221 | |||
| 222 | ret = line_setup(serial_lines, ARRAY_SIZE(serial_lines), str, &error); | ||
| 223 | if(ret < 0) | ||
| 224 | printk(KERN_ERR "Failed to set up serial line with " | ||
| 225 | "configuration string \"%s\" : %s\n", str, error); | ||
| 226 | |||
| 196 | return 1; | 227 | return 1; |
| 197 | } | 228 | } |
| 198 | 229 | ||
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 827777af3f6..49266f6108c 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c | |||
| @@ -3,30 +3,37 @@ | |||
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/posix_types.h> | 6 | #include "linux/posix_types.h" |
| 7 | #include <linux/tty.h> | 7 | #include "linux/tty.h" |
| 8 | #include <linux/tty_flip.h> | 8 | #include "linux/tty_flip.h" |
| 9 | #include <linux/types.h> | 9 | #include "linux/types.h" |
| 10 | #include <linux/major.h> | 10 | #include "linux/major.h" |
| 11 | #include <linux/kdev_t.h> | 11 | #include "linux/kdev_t.h" |
| 12 | #include <linux/console.h> | 12 | #include "linux/console.h" |
| 13 | #include <linux/string.h> | 13 | #include "linux/string.h" |
| 14 | #include <linux/sched.h> | 14 | #include "linux/sched.h" |
| 15 | #include <linux/list.h> | 15 | #include "linux/list.h" |
| 16 | #include <linux/init.h> | 16 | #include "linux/init.h" |
| 17 | #include <linux/interrupt.h> | 17 | #include "linux/interrupt.h" |
| 18 | #include <linux/slab.h> | 18 | #include "linux/slab.h" |
| 19 | #include <linux/hardirq.h> | 19 | #include "linux/hardirq.h" |
| 20 | #include <asm/current.h> | 20 | #include "asm/current.h" |
| 21 | #include <asm/irq.h> | 21 | #include "asm/irq.h" |
| 22 | #include "stdio_console.h" | 22 | #include "stdio_console.h" |
| 23 | #include "chan.h" | 23 | #include "line.h" |
| 24 | #include <irq_user.h> | 24 | #include "chan_kern.h" |
| 25 | #include "irq_user.h" | ||
| 25 | #include "mconsole_kern.h" | 26 | #include "mconsole_kern.h" |
| 26 | #include <init.h> | 27 | #include "init.h" |
| 27 | 28 | ||
| 28 | #define MAX_TTYS (16) | 29 | #define MAX_TTYS (16) |
| 29 | 30 | ||
| 31 | /* Referenced only by tty_driver below - presumably it's locked correctly | ||
| 32 | * by the tty driver. | ||
| 33 | */ | ||
| 34 | |||
| 35 | static struct tty_driver *console_driver; | ||
| 36 | |||
| 30 | static void stdio_announce(char *dev_name, int dev) | 37 | static void stdio_announce(char *dev_name, int dev) |
| 31 | { | 38 | { |
| 32 | printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev, | 39 | printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev, |
| @@ -70,9 +77,9 @@ static struct line_driver driver = { | |||
| 70 | /* The array is initialized by line_init, at initcall time. The | 77 | /* The array is initialized by line_init, at initcall time. The |
| 71 | * elements are locked individually as needed. | 78 | * elements are locked individually as needed. |
| 72 | */ | 79 | */ |
| 73 | static char *vt_conf[MAX_TTYS]; | 80 | static struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), |
| 74 | static char *def_conf; | 81 | [ 1 ... MAX_TTYS - 1 ] = |
| 75 | static struct line vts[MAX_TTYS]; | 82 | LINE_INIT(CONFIG_CON_CHAN, &driver) }; |
| 76 | 83 | ||
| 77 | static int con_config(char *str, char **error_out) | 84 | static int con_config(char *str, char **error_out) |
| 78 | { | 85 | { |
| @@ -89,17 +96,21 @@ static int con_remove(int n, char **error_out) | |||
| 89 | return line_remove(vts, ARRAY_SIZE(vts), n, error_out); | 96 | return line_remove(vts, ARRAY_SIZE(vts), n, error_out); |
| 90 | } | 97 | } |
| 91 | 98 | ||
| 92 | /* Set in an initcall, checked in an exitcall */ | 99 | static int con_open(struct tty_struct *tty, struct file *filp) |
| 93 | static int con_init_done = 0; | ||
| 94 | |||
| 95 | static int con_install(struct tty_driver *driver, struct tty_struct *tty) | ||
| 96 | { | 100 | { |
| 97 | return line_install(driver, tty, &vts[tty->index]); | 101 | int err = line_open(vts, tty); |
| 102 | if (err) | ||
| 103 | printk(KERN_ERR "Failed to open console %d, err = %d\n", | ||
| 104 | tty->index, err); | ||
| 105 | |||
| 106 | return err; | ||
| 98 | } | 107 | } |
| 99 | 108 | ||
| 109 | /* Set in an initcall, checked in an exitcall */ | ||
| 110 | static int con_init_done = 0; | ||
| 111 | |||
| 100 | static const struct tty_operations console_ops = { | 112 | static const struct tty_operations console_ops = { |
| 101 | .open = line_open, | 113 | .open = con_open, |
| 102 | .install = con_install, | ||
| 103 | .close = line_close, | 114 | .close = line_close, |
| 104 | .write = line_write, | 115 | .write = line_write, |
| 105 | .put_char = line_put_char, | 116 | .put_char = line_put_char, |
| @@ -108,10 +119,9 @@ static const struct tty_operations console_ops = { | |||
| 108 | .flush_buffer = line_flush_buffer, | 119 | .flush_buffer = line_flush_buffer, |
| 109 | .flush_chars = line_flush_chars, | 120 | .flush_chars = line_flush_chars, |
| 110 | .set_termios = line_set_termios, | 121 | .set_termios = line_set_termios, |
| 122 | .ioctl = line_ioctl, | ||
| 111 | .throttle = line_throttle, | 123 | .throttle = line_throttle, |
| 112 | .unthrottle = line_unthrottle, | 124 | .unthrottle = line_unthrottle, |
| 113 | .cleanup = line_cleanup, | ||
| 114 | .hangup = line_hangup, | ||
| 115 | }; | 125 | }; |
| 116 | 126 | ||
| 117 | static void uml_console_write(struct console *console, const char *string, | 127 | static void uml_console_write(struct console *console, const char *string, |
| @@ -121,14 +131,14 @@ static void uml_console_write(struct console *console, const char *string, | |||
| 121 | unsigned long flags; | 131 | unsigned long flags; |
| 122 | 132 | ||
| 123 | spin_lock_irqsave(&line->lock, flags); | 133 | spin_lock_irqsave(&line->lock, flags); |
| 124 | console_write_chan(line->chan_out, string, len); | 134 | console_write_chan(&line->chan_list, string, len); |
| 125 | spin_unlock_irqrestore(&line->lock, flags); | 135 | spin_unlock_irqrestore(&line->lock, flags); |
| 126 | } | 136 | } |
| 127 | 137 | ||
| 128 | static struct tty_driver *uml_console_device(struct console *c, int *index) | 138 | static struct tty_driver *uml_console_device(struct console *c, int *index) |
| 129 | { | 139 | { |
| 130 | *index = c->index; | 140 | *index = c->index; |
| 131 | return driver.driver; | 141 | return console_driver; |
| 132 | } | 142 | } |
| 133 | 143 | ||
| 134 | static int uml_console_setup(struct console *co, char *options) | 144 | static int uml_console_setup(struct console *co, char *options) |
| @@ -151,31 +161,18 @@ static struct console stdiocons = { | |||
| 151 | static int stdio_init(void) | 161 | static int stdio_init(void) |
| 152 | { | 162 | { |
| 153 | char *new_title; | 163 | char *new_title; |
| 154 | int err; | ||
| 155 | int i; | ||
| 156 | 164 | ||
| 157 | err = register_lines(&driver, &console_ops, vts, | 165 | console_driver = register_lines(&driver, &console_ops, vts, |
| 158 | ARRAY_SIZE(vts)); | 166 | ARRAY_SIZE(vts)); |
| 159 | if (err) | 167 | if (console_driver == NULL) |
| 160 | return err; | 168 | return -1; |
| 161 | |||
| 162 | printk(KERN_INFO "Initialized stdio console driver\n"); | 169 | printk(KERN_INFO "Initialized stdio console driver\n"); |
| 163 | 170 | ||
| 164 | new_title = add_xterm_umid(opts.xterm_title); | 171 | new_title = add_xterm_umid(opts.xterm_title); |
| 165 | if(new_title != NULL) | 172 | if(new_title != NULL) |
| 166 | opts.xterm_title = new_title; | 173 | opts.xterm_title = new_title; |
| 167 | 174 | ||
| 168 | for (i = 0; i < MAX_TTYS; i++) { | 175 | lines_init(vts, ARRAY_SIZE(vts), &opts); |
| 169 | char *error; | ||
| 170 | char *s = vt_conf[i]; | ||
| 171 | if (!s) | ||
| 172 | s = def_conf; | ||
| 173 | if (!s) | ||
| 174 | s = i ? CONFIG_CON_CHAN : CONFIG_CON_ZERO_CHAN; | ||
| 175 | if (setup_one_line(vts, i, s, &opts, &error)) | ||
| 176 | printk(KERN_ERR "setup_one_line failed for " | ||
| 177 | "device %d : %s\n", i, error); | ||
| 178 | } | ||
| 179 | 176 | ||
| 180 | con_init_done = 1; | 177 | con_init_done = 1; |
| 181 | register_console(&stdiocons); | 178 | register_console(&stdiocons); |
| @@ -193,7 +190,14 @@ __uml_exitcall(console_exit); | |||
| 193 | 190 | ||
| 194 | static int console_chan_setup(char *str) | 191 | static int console_chan_setup(char *str) |
| 195 | { | 192 | { |
| 196 | line_setup(vt_conf, MAX_TTYS, &def_conf, str, "console"); | 193 | char *error; |
| 194 | int ret; | ||
| 195 | |||
| 196 | ret = line_setup(vts, ARRAY_SIZE(vts), str, &error); | ||
| 197 | if(ret < 0) | ||
| 198 | printk(KERN_ERR "Failed to set up console with " | ||
| 199 | "configuration string \"%s\" : %s\n", str, error); | ||
| 200 | |||
| 197 | return 1; | 201 | return 1; |
| 198 | } | 202 | } |
| 199 | __setup("con", console_chan_setup); | 203 | __setup("con", console_chan_setup); |
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index eaa201bca5e..495858a090e 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c | |||
| @@ -7,8 +7,10 @@ | |||
| 7 | #include <fcntl.h> | 7 | #include <fcntl.h> |
| 8 | #include <termios.h> | 8 | #include <termios.h> |
| 9 | #include "chan_user.h" | 9 | #include "chan_user.h" |
| 10 | #include <os.h> | 10 | #include "kern_constants.h" |
| 11 | #include <um_malloc.h> | 11 | #include "os.h" |
| 12 | #include "um_malloc.h" | ||
| 13 | #include "user.h" | ||
| 12 | 14 | ||
| 13 | struct tty_chan { | 15 | struct tty_chan { |
| 14 | char *dev; | 16 | char *dev; |
diff --git a/arch/um/drivers/ubd.h b/arch/um/drivers/ubd.h deleted file mode 100644 index 3845051f1b1..00000000000 --- a/arch/um/drivers/ubd.h +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | ||
| 3 | * Copyright (C) 2001 RidgeRun, Inc (glonnon@ridgerun.com) | ||
| 4 | * Licensed under the GPL | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef __UM_UBD_USER_H | ||
| 8 | #define __UM_UBD_USER_H | ||
| 9 | |||
| 10 | extern void ignore_sigwinch_sig(void); | ||
| 11 | extern int start_io_thread(unsigned long sp, int *fds_out); | ||
| 12 | extern int io_thread(void *arg); | ||
| 13 | extern int kernel_fd; | ||
| 14 | |||
| 15 | #endif | ||
| 16 | |||
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 41bf72073cc..0491e40d696 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
| @@ -19,26 +19,42 @@ | |||
| 19 | 19 | ||
| 20 | #define UBD_SHIFT 4 | 20 | #define UBD_SHIFT 4 |
| 21 | 21 | ||
| 22 | #include <linux/module.h> | 22 | #include "linux/kernel.h" |
| 23 | #include <linux/init.h> | 23 | #include "linux/module.h" |
| 24 | #include <linux/blkdev.h> | 24 | #include "linux/blkdev.h" |
| 25 | #include <linux/ata.h> | 25 | #include "linux/ata.h" |
| 26 | #include <linux/hdreg.h> | 26 | #include "linux/hdreg.h" |
| 27 | #include <linux/cdrom.h> | 27 | #include "linux/init.h" |
| 28 | #include <linux/proc_fs.h> | 28 | #include "linux/cdrom.h" |
| 29 | #include <linux/seq_file.h> | 29 | #include "linux/proc_fs.h" |
| 30 | #include <linux/ctype.h> | 30 | #include "linux/seq_file.h" |
| 31 | #include <linux/slab.h> | 31 | #include "linux/ctype.h" |
| 32 | #include <linux/vmalloc.h> | 32 | #include "linux/capability.h" |
| 33 | #include <linux/platform_device.h> | 33 | #include "linux/mm.h" |
| 34 | #include <linux/scatterlist.h> | 34 | #include "linux/slab.h" |
| 35 | #include <asm/tlbflush.h> | 35 | #include "linux/vmalloc.h" |
| 36 | #include <kern_util.h> | 36 | #include "linux/mutex.h" |
| 37 | #include "linux/blkpg.h" | ||
| 38 | #include "linux/genhd.h" | ||
| 39 | #include "linux/spinlock.h" | ||
| 40 | #include "linux/platform_device.h" | ||
| 41 | #include "linux/scatterlist.h" | ||
| 42 | #include "asm/segment.h" | ||
| 43 | #include "asm/uaccess.h" | ||
| 44 | #include "asm/irq.h" | ||
| 45 | #include "asm/types.h" | ||
| 46 | #include "asm/tlbflush.h" | ||
| 47 | #include "mem_user.h" | ||
| 48 | #include "kern_util.h" | ||
| 49 | #include "kern.h" | ||
| 37 | #include "mconsole_kern.h" | 50 | #include "mconsole_kern.h" |
| 38 | #include <init.h> | 51 | #include "init.h" |
| 39 | #include <irq_kern.h> | 52 | #include "irq_user.h" |
| 40 | #include "ubd.h" | 53 | #include "irq_kern.h" |
| 41 | #include <os.h> | 54 | #include "ubd_user.h" |
| 55 | #include "os.h" | ||
| 56 | #include "mem.h" | ||
| 57 | #include "mem_kern.h" | ||
| 42 | #include "cow.h" | 58 | #include "cow.h" |
| 43 | 59 | ||
| 44 | enum ubd_req { UBD_READ, UBD_WRITE }; | 60 | enum ubd_req { UBD_READ, UBD_WRITE }; |
| @@ -514,7 +530,7 @@ static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) | |||
| 514 | goto out; | 530 | goto out; |
| 515 | } | 531 | } |
| 516 | 532 | ||
| 517 | fd = os_open_file(ubd_dev->file, of_read(OPENFLAGS()), 0); | 533 | fd = os_open_file(ubd_dev->file, global_openflags, 0); |
| 518 | if (fd < 0) | 534 | if (fd < 0) |
| 519 | return fd; | 535 | return fd; |
| 520 | 536 | ||
| @@ -1101,7 +1117,7 @@ static int __init ubd_driver_init(void){ | |||
| 1101 | return 0; | 1117 | return 0; |
| 1102 | } | 1118 | } |
| 1103 | err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, | 1119 | err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, |
| 1104 | 0, "ubd", ubd_devs); | 1120 | IRQF_DISABLED, "ubd", ubd_devs); |
| 1105 | if(err != 0) | 1121 | if(err != 0) |
| 1106 | printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); | 1122 | printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); |
| 1107 | return 0; | 1123 | return 0; |
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c index a703e45d8aa..b591bb9c41d 100644 --- a/arch/um/drivers/ubd_user.c +++ b/arch/um/drivers/ubd_user.c | |||
| @@ -15,12 +15,15 @@ | |||
| 15 | #include <sys/socket.h> | 15 | #include <sys/socket.h> |
| 16 | #include <sys/mman.h> | 16 | #include <sys/mman.h> |
| 17 | #include <sys/param.h> | 17 | #include <sys/param.h> |
| 18 | #include "asm/types.h" | ||
| 19 | #include "user.h" | ||
| 20 | #include "ubd_user.h" | ||
| 21 | #include "os.h" | ||
| 22 | #include "cow.h" | ||
| 23 | |||
| 18 | #include <endian.h> | 24 | #include <endian.h> |
| 19 | #include <byteswap.h> | 25 | #include <byteswap.h> |
| 20 | 26 | ||
| 21 | #include "ubd.h" | ||
| 22 | #include <os.h> | ||
| 23 | |||
| 24 | void ignore_sigwinch_sig(void) | 27 | void ignore_sigwinch_sig(void) |
| 25 | { | 28 | { |
| 26 | signal(SIGWINCH, SIG_IGN); | 29 | signal(SIGWINCH, SIG_IGN); |
diff --git a/arch/um/drivers/umcast.h b/arch/um/drivers/umcast.h index c190c644091..6f8c0fe890f 100644 --- a/arch/um/drivers/umcast.h +++ b/arch/um/drivers/umcast.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #ifndef __DRIVERS_UMCAST_H | 6 | #ifndef __DRIVERS_UMCAST_H |
| 7 | #define __DRIVERS_UMCAST_H | 7 | #define __DRIVERS_UMCAST_H |
| 8 | 8 | ||
| 9 | #include <net_user.h> | 9 | #include "net_user.h" |
| 10 | 10 | ||
| 11 | struct umcast_data { | 11 | struct umcast_data { |
| 12 | char *addr; | 12 | char *addr; |
diff --git a/arch/um/drivers/umcast_kern.c b/arch/um/drivers/umcast_kern.c index f5ba6e37791..42dab11d2ec 100644 --- a/arch/um/drivers/umcast_kern.c +++ b/arch/um/drivers/umcast_kern.c | |||
| @@ -11,10 +11,10 @@ | |||
| 11 | * Licensed under the GPL. | 11 | * Licensed under the GPL. |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/init.h> | 14 | #include "linux/init.h" |
| 15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
| 16 | #include "umcast.h" | 16 | #include "umcast.h" |
| 17 | #include <net_kern.h> | 17 | #include "net_kern.h" |
| 18 | 18 | ||
| 19 | struct umcast_init { | 19 | struct umcast_init { |
| 20 | char *addr; | 20 | char *addr; |
diff --git a/arch/um/drivers/umcast_user.c b/arch/um/drivers/umcast_user.c index 6074184bb51..59c56fd6f52 100644 --- a/arch/um/drivers/umcast_user.c +++ b/arch/um/drivers/umcast_user.c | |||
| @@ -15,9 +15,11 @@ | |||
| 15 | #include <unistd.h> | 15 | #include <unistd.h> |
| 16 | #include <errno.h> | 16 | #include <errno.h> |
| 17 | #include <netinet/in.h> | 17 | #include <netinet/in.h> |
| 18 | #include "kern_constants.h" | ||
| 18 | #include "umcast.h" | 19 | #include "umcast.h" |
| 19 | #include <net_user.h> | 20 | #include "net_user.h" |
| 20 | #include <um_malloc.h> | 21 | #include "um_malloc.h" |
| 22 | #include "user.h" | ||
| 21 | 23 | ||
| 22 | static struct sockaddr_in *new_addr(char *addr, unsigned short port) | 24 | static struct sockaddr_in *new_addr(char *addr, unsigned short port) |
| 23 | { | 25 | { |
diff --git a/arch/um/drivers/vde_kern.c b/arch/um/drivers/vde_kern.c index 6a365fadc7c..1b852bffdeb 100644 --- a/arch/um/drivers/vde_kern.c +++ b/arch/um/drivers/vde_kern.c | |||
| @@ -7,10 +7,10 @@ | |||
| 7 | * | 7 | * |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/init.h> | 10 | #include "linux/init.h" |
| 11 | #include <linux/netdevice.h> | 11 | #include <linux/netdevice.h> |
| 12 | #include <net_kern.h> | 12 | #include "net_kern.h" |
| 13 | #include <net_user.h> | 13 | #include "net_user.h" |
| 14 | #include "vde.h" | 14 | #include "vde.h" |
| 15 | 15 | ||
| 16 | static void vde_init(struct net_device *dev, void *data) | 16 | static void vde_init(struct net_device *dev, void *data) |
diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c index 64cb630d115..c5c43253e6c 100644 --- a/arch/um/drivers/vde_user.c +++ b/arch/um/drivers/vde_user.c | |||
| @@ -6,8 +6,10 @@ | |||
| 6 | #include <stddef.h> | 6 | #include <stddef.h> |
| 7 | #include <errno.h> | 7 | #include <errno.h> |
| 8 | #include <libvdeplug.h> | 8 | #include <libvdeplug.h> |
| 9 | #include <net_user.h> | 9 | #include "kern_constants.h" |
| 10 | #include <um_malloc.h> | 10 | #include "net_user.h" |
| 11 | #include "um_malloc.h" | ||
| 12 | #include "user.h" | ||
| 11 | #include "vde.h" | 13 | #include "vde.h" |
| 12 | 14 | ||
| 13 | static int vde_user_init(void *data, void *dev) | 15 | static int vde_user_init(void *data, void *dev) |
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 20e30be4479..2e1de572860 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c | |||
| @@ -11,8 +11,10 @@ | |||
| 11 | #include <string.h> | 11 | #include <string.h> |
| 12 | #include <termios.h> | 12 | #include <termios.h> |
| 13 | #include "chan_user.h" | 13 | #include "chan_user.h" |
| 14 | #include <os.h> | 14 | #include "kern_constants.h" |
| 15 | #include <um_malloc.h> | 15 | #include "os.h" |
| 16 | #include "um_malloc.h" | ||
| 17 | #include "user.h" | ||
| 16 | #include "xterm.h" | 18 | #include "xterm.h" |
| 17 | 19 | ||
| 18 | struct xterm_chan { | 20 | struct xterm_chan { |
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c index e8f9957bfbf..b646bccef37 100644 --- a/arch/um/drivers/xterm_kern.c +++ b/arch/um/drivers/xterm_kern.c | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | #include <linux/completion.h> | 7 | #include <linux/completion.h> |
| 8 | #include <linux/irqreturn.h> | 8 | #include <linux/irqreturn.h> |
| 9 | #include <asm/irq.h> | 9 | #include <asm/irq.h> |
| 10 | #include <irq_kern.h> | 10 | #include "irq_kern.h" |
| 11 | #include <os.h> | 11 | #include "os.h" |
| 12 | 12 | ||
| 13 | struct xterm_wait { | 13 | struct xterm_wait { |
| 14 | struct completion ready; | 14 | struct completion ready; |
| @@ -50,7 +50,8 @@ int xterm_fd(int socket, int *pid_out) | |||
| 50 | init_completion(&data->ready); | 50 | init_completion(&data->ready); |
| 51 | 51 | ||
| 52 | err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, | 52 | err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, |
| 53 | IRQF_SHARED, "xterm", data); | 53 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
| 54 | "xterm", data); | ||
| 54 | if (err) { | 55 | if (err) { |
| 55 | printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, " | 56 | printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, " |
| 56 | "err = %d\n", err); | 57 | "err = %d\n", err); |
| @@ -64,7 +65,7 @@ int xterm_fd(int socket, int *pid_out) | |||
| 64 | * isn't set) this will hang... */ | 65 | * isn't set) this will hang... */ |
| 65 | wait_for_completion(&data->ready); | 66 | wait_for_completion(&data->ready); |
| 66 | 67 | ||
| 67 | um_free_irq(XTERM_IRQ, data); | 68 | free_irq(XTERM_IRQ, data); |
| 68 | 69 | ||
| 69 | ret = data->new_fd; | 70 | ret = data->new_fd; |
| 70 | *pid_out = data->pid; | 71 | *pid_out = data->pid; |
