aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/drivers/chan_kern.c111
-rw-r--r--arch/um/drivers/line.c116
-rw-r--r--arch/um/include/chan_kern.h9
-rw-r--r--arch/um/include/irq_user.h13
-rw-r--r--arch/um/include/line.h6
-rw-r--r--arch/um/kernel/irq_user.c48
6 files changed, 137 insertions, 166 deletions
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 31b69c4ea800..1bb920c0d77a 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -240,20 +240,65 @@ void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
240 } 240 }
241} 241}
242 242
243void enable_chan(struct list_head *chans, struct tty_struct *tty) 243void enable_chan(struct line *line)
244{ 244{
245 struct list_head *ele; 245 struct list_head *ele;
246 struct chan *chan; 246 struct chan *chan;
247 247
248 list_for_each(ele, chans){ 248 list_for_each(ele, &line->chan_list){
249 chan = list_entry(ele, struct chan, list); 249 chan = list_entry(ele, struct chan, list);
250 if(!chan->opened) continue; 250 if(open_one_chan(chan))
251 continue;
252
253 if(chan->enabled)
254 continue;
255 line_setup_irq(chan->fd, chan->input, chan->output, line,
256 chan);
257 chan->enabled = 1;
258 }
259}
260
261static LIST_HEAD(irqs_to_free);
262
263void free_irqs(void)
264{
265 struct chan *chan;
266
267 while(!list_empty(&irqs_to_free)){
268 chan = list_entry(irqs_to_free.next, struct chan, free_list);
269 list_del(&chan->free_list);
270
271 if(chan->input)
272 free_irq(chan->line->driver->read_irq, chan);
273 if(chan->output)
274 free_irq(chan->line->driver->write_irq, chan);
275 chan->enabled = 0;
276 }
277}
278
279static void close_one_chan(struct chan *chan, int delay_free_irq)
280{
281 if(!chan->opened)
282 return;
251 283
252 line_setup_irq(chan->fd, chan->input, chan->output, tty); 284 if(delay_free_irq){
285 list_add(&chan->free_list, &irqs_to_free);
286 }
287 else {
288 if(chan->input)
289 free_irq(chan->line->driver->read_irq, chan);
290 if(chan->output)
291 free_irq(chan->line->driver->write_irq, chan);
292 chan->enabled = 0;
253 } 293 }
294 if(chan->ops->close != NULL)
295 (*chan->ops->close)(chan->fd, chan->data);
296
297 chan->opened = 0;
298 chan->fd = -1;
254} 299}
255 300
256void close_chan(struct list_head *chans) 301void close_chan(struct list_head *chans, int delay_free_irq)
257{ 302{
258 struct chan *chan; 303 struct chan *chan;
259 304
@@ -263,11 +308,7 @@ void close_chan(struct list_head *chans)
263 * so it must be the last closed. 308 * so it must be the last closed.
264 */ 309 */
265 list_for_each_entry_reverse(chan, chans, list) { 310 list_for_each_entry_reverse(chan, chans, list) {
266 if(!chan->opened) continue; 311 close_one_chan(chan, delay_free_irq);
267 if(chan->ops->close != NULL)
268 (*chan->ops->close)(chan->fd, chan->data);
269 chan->opened = 0;
270 chan->fd = -1;
271 } 312 }
272} 313}
273 314
@@ -339,24 +380,27 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out,
339 return 0; 380 return 0;
340} 381}
341 382
342void free_one_chan(struct chan *chan) 383void free_one_chan(struct chan *chan, int delay_free_irq)
343{ 384{
344 list_del(&chan->list); 385 list_del(&chan->list);
386
387 close_one_chan(chan, delay_free_irq);
388
345 if(chan->ops->free != NULL) 389 if(chan->ops->free != NULL)
346 (*chan->ops->free)(chan->data); 390 (*chan->ops->free)(chan->data);
347 free_irq_by_fd(chan->fd); 391
348 if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); 392 if(chan->primary && chan->output) ignore_sigio_fd(chan->fd);
349 kfree(chan); 393 kfree(chan);
350} 394}
351 395
352void free_chan(struct list_head *chans) 396void free_chan(struct list_head *chans, int delay_free_irq)
353{ 397{
354 struct list_head *ele, *next; 398 struct list_head *ele, *next;
355 struct chan *chan; 399 struct chan *chan;
356 400
357 list_for_each_safe(ele, next, chans){ 401 list_for_each_safe(ele, next, chans){
358 chan = list_entry(ele, struct chan, list); 402 chan = list_entry(ele, struct chan, list);
359 free_one_chan(chan); 403 free_one_chan(chan, delay_free_irq);
360 } 404 }
361} 405}
362 406
@@ -466,7 +510,8 @@ struct chan_type chan_table[] = {
466#endif 510#endif
467}; 511};
468 512
469static struct chan *parse_chan(char *str, int device, struct chan_opts *opts) 513static struct chan *parse_chan(struct line *line, char *str, int device,
514 struct chan_opts *opts)
470{ 515{
471 struct chan_type *entry; 516 struct chan_type *entry;
472 struct chan_ops *ops; 517 struct chan_ops *ops;
@@ -499,25 +544,30 @@ static struct chan *parse_chan(char *str, int device, struct chan_opts *opts)
499 if(chan == NULL) 544 if(chan == NULL)
500 return NULL; 545 return NULL;
501 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), 546 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list),
547 .free_list =
548 LIST_HEAD_INIT(chan->free_list),
549 .line = line,
502 .primary = 1, 550 .primary = 1,
503 .input = 0, 551 .input = 0,
504 .output = 0, 552 .output = 0,
505 .opened = 0, 553 .opened = 0,
554 .enabled = 0,
506 .fd = -1, 555 .fd = -1,
507 .ops = ops, 556 .ops = ops,
508 .data = data }); 557 .data = data });
509 return chan; 558 return chan;
510} 559}
511 560
512int parse_chan_pair(char *str, struct list_head *chans, int device, 561int parse_chan_pair(char *str, struct line *line, int device,
513 struct chan_opts *opts) 562 struct chan_opts *opts)
514{ 563{
564 struct list_head *chans = &line->chan_list;
515 struct chan *new, *chan; 565 struct chan *new, *chan;
516 char *in, *out; 566 char *in, *out;
517 567
518 if(!list_empty(chans)){ 568 if(!list_empty(chans)){
519 chan = list_entry(chans->next, struct chan, list); 569 chan = list_entry(chans->next, struct chan, list);
520 free_chan(chans); 570 free_chan(chans, 0);
521 INIT_LIST_HEAD(chans); 571 INIT_LIST_HEAD(chans);
522 } 572 }
523 573
@@ -526,14 +576,14 @@ int parse_chan_pair(char *str, struct list_head *chans, int device,
526 in = str; 576 in = str;
527 *out = '\0'; 577 *out = '\0';
528 out++; 578 out++;
529 new = parse_chan(in, device, opts); 579 new = parse_chan(line, in, device, opts);
530 if(new == NULL) 580 if(new == NULL)
531 return -1; 581 return -1;
532 582
533 new->input = 1; 583 new->input = 1;
534 list_add(&new->list, chans); 584 list_add(&new->list, chans);
535 585
536 new = parse_chan(out, device, opts); 586 new = parse_chan(line, out, device, opts);
537 if(new == NULL) 587 if(new == NULL)
538 return -1; 588 return -1;
539 589
@@ -541,7 +591,7 @@ int parse_chan_pair(char *str, struct list_head *chans, int device,
541 new->output = 1; 591 new->output = 1;
542 } 592 }
543 else { 593 else {
544 new = parse_chan(str, device, opts); 594 new = parse_chan(line, str, device, opts);
545 if(new == NULL) 595 if(new == NULL)
546 return -1; 596 return -1;
547 597
@@ -592,27 +642,12 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
592 if(chan->primary){ 642 if(chan->primary){
593 if(tty != NULL) 643 if(tty != NULL)
594 tty_hangup(tty); 644 tty_hangup(tty);
595 line_disable(tty, irq); 645 close_chan(chans, 1);
596 close_chan(chans);
597 return; 646 return;
598 } 647 }
599 else { 648 else close_one_chan(chan, 1);
600 if(chan->ops->close != NULL)
601 chan->ops->close(chan->fd, chan->data);
602 }
603 } 649 }
604 } 650 }
605 out: 651 out:
606 if(tty) tty_flip_buffer_push(tty); 652 if(tty) tty_flip_buffer_push(tty);
607} 653}
608
609/*
610 * Overrides for Emacs so that we follow Linus's tabbing style.
611 * Emacs will notice this stuff at the end of the file and automatically
612 * adjust the settings for this buffer only. This must remain at the end
613 * of the file.
614 * ---------------------------------------------------------------------------
615 * Local variables:
616 * c-file-style: "linux"
617 * End:
618 */
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index da81d22ec04a..851a7c8caae5 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -23,8 +23,9 @@
23 23
24static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused) 24static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
25{ 25{
26 struct tty_struct *tty = data; 26 struct chan *chan = data;
27 struct line *line = tty->driver_data; 27 struct line *line = chan->line;
28 struct tty_struct *tty = line->tty;
28 29
29 if (line) 30 if (line)
30 chan_interrupt(&line->chan_list, &line->task, tty, irq); 31 chan_interrupt(&line->chan_list, &line->task, tty, irq);
@@ -33,10 +34,10 @@ static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
33 34
34static void line_timer_cb(void *arg) 35static void line_timer_cb(void *arg)
35{ 36{
36 struct tty_struct *tty = arg; 37 struct line *line = arg;
37 struct line *line = tty->driver_data;
38 38
39 line_interrupt(line->driver->read_irq, arg, NULL); 39 chan_interrupt(&line->chan_list, &line->task, line->tty,
40 line->driver->read_irq);
40} 41}
41 42
42/* Returns the free space inside the ring buffer of this line. 43/* Returns the free space inside the ring buffer of this line.
@@ -342,8 +343,9 @@ int line_ioctl(struct tty_struct *tty, struct file * file,
342static irqreturn_t line_write_interrupt(int irq, void *data, 343static irqreturn_t line_write_interrupt(int irq, void *data,
343 struct pt_regs *unused) 344 struct pt_regs *unused)
344{ 345{
345 struct tty_struct *tty = data; 346 struct chan *chan = data;
346 struct line *line = tty->driver_data; 347 struct line *line = chan->line;
348 struct tty_struct *tty = line->tty;
347 int err; 349 int err;
348 350
349 /* Interrupts are enabled here because we registered the interrupt with 351 /* Interrupts are enabled here because we registered the interrupt with
@@ -365,7 +367,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
365 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && 367 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
366 (tty->ldisc.write_wakeup != NULL)) 368 (tty->ldisc.write_wakeup != NULL))
367 (tty->ldisc.write_wakeup)(tty); 369 (tty->ldisc.write_wakeup)(tty);
368 370
369 /* BLOCKING mode 371 /* BLOCKING mode
370 * In blocking mode, everything sleeps on tty->write_wait. 372 * In blocking mode, everything sleeps on tty->write_wait.
371 * Sleeping in the console driver would break non-blocking 373 * Sleeping in the console driver would break non-blocking
@@ -377,52 +379,29 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
377 return IRQ_HANDLED; 379 return IRQ_HANDLED;
378} 380}
379 381
380int line_setup_irq(int fd, int input, int output, struct tty_struct *tty) 382int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
381{ 383{
382 struct line *line = tty->driver_data;
383 struct line_driver *driver = line->driver; 384 struct line_driver *driver = line->driver;
384 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; 385 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM;
385 386
386 if (input) 387 if (input)
387 err = um_request_irq(driver->read_irq, fd, IRQ_READ, 388 err = um_request_irq(driver->read_irq, fd, IRQ_READ,
388 line_interrupt, flags, 389 line_interrupt, flags,
389 driver->read_irq_name, tty); 390 driver->read_irq_name, data);
390 if (err) 391 if (err)
391 return err; 392 return err;
392 if (output) 393 if (output)
393 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, 394 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
394 line_write_interrupt, flags, 395 line_write_interrupt, flags,
395 driver->write_irq_name, tty); 396 driver->write_irq_name, data);
396 line->have_irq = 1; 397 line->have_irq = 1;
397 return err; 398 return err;
398} 399}
399 400
400void line_disable(struct tty_struct *tty, int current_irq)
401{
402 struct line *line = tty->driver_data;
403
404 if(!line->have_irq)
405 return;
406
407 if(line->driver->read_irq == current_irq)
408 free_irq_later(line->driver->read_irq, tty);
409 else {
410 free_irq(line->driver->read_irq, tty);
411 }
412
413 if(line->driver->write_irq == current_irq)
414 free_irq_later(line->driver->write_irq, tty);
415 else {
416 free_irq(line->driver->write_irq, tty);
417 }
418
419 line->have_irq = 0;
420}
421
422int line_open(struct line *lines, struct tty_struct *tty) 401int line_open(struct line *lines, struct tty_struct *tty)
423{ 402{
424 struct line *line; 403 struct line *line;
425 int err = 0; 404 int err = -ENODEV;
426 405
427 line = &lines[tty->index]; 406 line = &lines[tty->index];
428 tty->driver_data = line; 407 tty->driver_data = line;
@@ -430,29 +409,29 @@ int line_open(struct line *lines, struct tty_struct *tty)
430 /* The IRQ which takes this lock is not yet enabled and won't be run 409 /* The IRQ which takes this lock is not yet enabled and won't be run
431 * before the end, so we don't need to use spin_lock_irq.*/ 410 * before the end, so we don't need to use spin_lock_irq.*/
432 spin_lock(&line->lock); 411 spin_lock(&line->lock);
433 if (tty->count == 1) {
434 if (!line->valid) {
435 err = -ENODEV;
436 goto out;
437 }
438 412
439 err = open_chan(&line->chan_list); 413 tty->driver_data = line;
440 if(err) 414 line->tty = tty;
441 goto out; 415 if(!line->valid)
442 416 goto out;
443 /* Here the interrupt is registered.*/ 417
444 enable_chan(&line->chan_list, tty); 418 if(tty->count == 1){
445 INIT_WORK(&line->task, line_timer_cb, tty); 419 /* Here the device is opened, if necessary, and interrupt
446 } 420 * is registered.
421 */
422 enable_chan(line);
423 INIT_WORK(&line->task, line_timer_cb, line);
424
425 if(!line->sigio){
426 chan_enable_winch(&line->chan_list, tty);
427 line->sigio = 1;
428 }
447 429
448 if(!line->sigio){ 430 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
449 chan_enable_winch(&line->chan_list, tty); 431 &tty->winsize.ws_col);
450 line->sigio = 1;
451 } 432 }
452 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
453 &tty->winsize.ws_col);
454 line->count++;
455 433
434 err = 0;
456out: 435out:
457 spin_unlock(&line->lock); 436 spin_unlock(&line->lock);
458 return err; 437 return err;
@@ -472,15 +451,14 @@ void line_close(struct tty_struct *tty, struct file * filp)
472 /* We ignore the error anyway! */ 451 /* We ignore the error anyway! */
473 flush_buffer(line); 452 flush_buffer(line);
474 453
475 line->count--; 454 if(tty->count == 1){
476 if (tty->count == 1) { 455 line->tty = NULL;
477 line_disable(tty, -1);
478 tty->driver_data = NULL; 456 tty->driver_data = NULL;
479 }
480 457
481 if((line->count == 0) && line->sigio){ 458 if(line->sigio){
482 unregister_winch(tty); 459 unregister_winch(tty);
483 line->sigio = 0; 460 line->sigio = 0;
461 }
484 } 462 }
485 463
486 spin_unlock_irq(&line->lock); 464 spin_unlock_irq(&line->lock);
@@ -491,7 +469,7 @@ void close_lines(struct line *lines, int nlines)
491 int i; 469 int i;
492 470
493 for(i = 0; i < nlines; i++) 471 for(i = 0; i < nlines; i++)
494 close_chan(&lines[i].chan_list); 472 close_chan(&lines[i].chan_list, 0);
495} 473}
496 474
497/* Common setup code for both startup command line and mconsole initialization. 475/* Common setup code for both startup command line and mconsole initialization.
@@ -526,7 +504,7 @@ int line_setup(struct line *lines, unsigned int num, char *init)
526 return 0; 504 return 0;
527 } 505 }
528 else if (n >= 0){ 506 else if (n >= 0){
529 if (lines[n].count > 0) { 507 if (lines[n].tty != NULL) {
530 printk("line_setup - device %d is open\n", n); 508 printk("line_setup - device %d is open\n", n);
531 return 0; 509 return 0;
532 } 510 }
@@ -537,7 +515,7 @@ int line_setup(struct line *lines, unsigned int num, char *init)
537 else { 515 else {
538 lines[n].init_str = init; 516 lines[n].init_str = init;
539 lines[n].valid = 1; 517 lines[n].valid = 1;
540 } 518 }
541 } 519 }
542 } 520 }
543 else { 521 else {
@@ -578,7 +556,7 @@ int line_config(struct line *lines, unsigned int num, char *str,
578 return 1; 556 return 1;
579 557
580 line = &lines[n]; 558 line = &lines[n];
581 return parse_chan_pair(line->init_str, &line->chan_list, n, opts); 559 return parse_chan_pair(line->init_str, line, n, opts);
582} 560}
583 561
584int line_get_config(char *name, struct line *lines, unsigned int num, char *str, 562int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
@@ -604,7 +582,7 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
604 spin_lock(&line->lock); 582 spin_lock(&line->lock);
605 if(!line->valid) 583 if(!line->valid)
606 CONFIG_CHUNK(str, size, n, "none", 1); 584 CONFIG_CHUNK(str, size, n, "none", 1);
607 else if(line->count == 0) 585 else if(line->tty == NULL)
608 CONFIG_CHUNK(str, size, n, line->init_str, 1); 586 CONFIG_CHUNK(str, size, n, line->init_str, 1);
609 else n = chan_config_string(&line->chan_list, str, size, error_out); 587 else n = chan_config_string(&line->chan_list, str, size, error_out);
610 spin_unlock(&line->lock); 588 spin_unlock(&line->lock);
@@ -696,7 +674,7 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
696 if(line->init_str == NULL) 674 if(line->init_str == NULL)
697 printk("lines_init - kstrdup returned NULL\n"); 675 printk("lines_init - kstrdup returned NULL\n");
698 676
699 if(parse_chan_pair(line->init_str, &line->chan_list, i, opts)){ 677 if(parse_chan_pair(line->init_str, line, i, opts)){
700 printk("parse_chan_pair failed for device %d\n", i); 678 printk("parse_chan_pair failed for device %d\n", i);
701 line->valid = 0; 679 line->valid = 0;
702 } 680 }
@@ -831,7 +809,7 @@ char *add_xterm_umid(char *base)
831 umid = get_umid(1); 809 umid = get_umid(1);
832 if(umid == NULL) 810 if(umid == NULL)
833 return base; 811 return base;
834 812
835 len = strlen(base) + strlen(" ()") + strlen(umid) + 1; 813 len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
836 title = kmalloc(len, GFP_KERNEL); 814 title = kmalloc(len, GFP_KERNEL);
837 if(title == NULL){ 815 if(title == NULL){
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index 22bf3a73437c..84d1f64f9795 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -14,11 +14,14 @@
14 14
15struct chan { 15struct chan {
16 struct list_head list; 16 struct list_head list;
17 struct list_head free_list;
18 struct line *line;
17 char *dev; 19 char *dev;
18 unsigned int primary:1; 20 unsigned int primary:1;
19 unsigned int input:1; 21 unsigned int input:1;
20 unsigned int output:1; 22 unsigned int output:1;
21 unsigned int opened:1; 23 unsigned int opened:1;
24 unsigned int enabled:1;
22 int fd; 25 int fd;
23 struct chan_ops *ops; 26 struct chan_ops *ops;
24 void *data; 27 void *data;
@@ -26,7 +29,7 @@ struct chan {
26 29
27extern void chan_interrupt(struct list_head *chans, struct work_struct *task, 30extern void chan_interrupt(struct list_head *chans, struct work_struct *task,
28 struct tty_struct *tty, int irq); 31 struct tty_struct *tty, int irq);
29extern int parse_chan_pair(char *str, struct list_head *chans, int device, 32extern int parse_chan_pair(char *str, struct line *line, int device,
30 struct chan_opts *opts); 33 struct chan_opts *opts);
31extern int open_chan(struct list_head *chans); 34extern int open_chan(struct list_head *chans);
32extern int write_chan(struct list_head *chans, const char *buf, int len, 35extern int write_chan(struct list_head *chans, const char *buf, int len,
@@ -35,9 +38,9 @@ extern int console_write_chan(struct list_head *chans, const char *buf,
35 int len); 38 int len);
36extern int console_open_chan(struct line *line, struct console *co, 39extern int console_open_chan(struct line *line, struct console *co,
37 struct chan_opts *opts); 40 struct chan_opts *opts);
38extern void close_chan(struct list_head *chans);
39extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); 41extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
40extern void enable_chan(struct list_head *chans, struct tty_struct *tty); 42extern void enable_chan(struct line *line);
43extern void close_chan(struct list_head *chans, int delay_free_irq);
41extern int chan_window_size(struct list_head *chans, 44extern int chan_window_size(struct list_head *chans,
42 unsigned short *rows_out, 45 unsigned short *rows_out,
43 unsigned short *cols_out); 46 unsigned short *cols_out);
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index f724b717213f..b61deb8b362a 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -18,19 +18,8 @@ extern int deactivate_all_fds(void);
18extern void forward_interrupts(int pid); 18extern void forward_interrupts(int pid);
19extern void init_irq_signals(int on_sigstack); 19extern void init_irq_signals(int on_sigstack);
20extern void forward_ipi(int fd, int pid); 20extern void forward_ipi(int fd, int pid);
21extern void free_irq_later(int irq, void *dev_id);
22extern int activate_ipi(int fd, int pid); 21extern int activate_ipi(int fd, int pid);
23extern unsigned long irq_lock(void); 22extern unsigned long irq_lock(void);
24extern void irq_unlock(unsigned long flags); 23extern void irq_unlock(unsigned long flags);
25#endif
26 24
27/* 25#endif
28 * Overrides for Emacs so that we follow Linus's tabbing style.
29 * Emacs will notice this stuff at the end of the file and automatically
30 * adjust the settings for this buffer only. This must remain at the end
31 * of the file.
32 * ---------------------------------------------------------------------------
33 * Local variables:
34 * c-file-style: "linux"
35 * End:
36 */
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 474398ba1207..e6cc3abfd4db 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -32,6 +32,7 @@ struct line_driver {
32}; 32};
33 33
34struct line { 34struct line {
35 struct tty_struct *tty;
35 char *init_str; 36 char *init_str;
36 int init_pri; 37 int init_pri;
37 struct list_head chan_list; 38 struct list_head chan_list;
@@ -89,10 +90,9 @@ extern int line_ioctl(struct tty_struct *tty, struct file * file,
89 unsigned int cmd, unsigned long arg); 90 unsigned int cmd, unsigned long arg);
90 91
91extern char *add_xterm_umid(char *base); 92extern char *add_xterm_umid(char *base);
92extern int line_setup_irq(int fd, int input, int output, 93extern int line_setup_irq(int fd, int input, int output, struct line *line,
93 struct tty_struct *tty); 94 void *data);
94extern void line_close_chan(struct line *line); 95extern void line_close_chan(struct line *line);
95extern void line_disable(struct tty_struct *tty, int current_irq);
96extern struct tty_driver * line_register_devfs(struct lines *set, 96extern struct tty_driver * line_register_devfs(struct lines *set,
97 struct line_driver *line_driver, 97 struct line_driver *line_driver,
98 struct tty_operations *driver, 98 struct tty_operations *driver,
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index c3ccaf24f3e0..50a2aa35cda9 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -29,7 +29,6 @@ struct irq_fd {
29 int pid; 29 int pid;
30 int events; 30 int events;
31 int current_events; 31 int current_events;
32 int freed;
33}; 32};
34 33
35static struct irq_fd *active_fds = NULL; 34static struct irq_fd *active_fds = NULL;
@@ -41,9 +40,11 @@ static int pollfds_size = 0;
41 40
42extern int io_count, intr_count; 41extern int io_count, intr_count;
43 42
43extern void free_irqs(void);
44
44void sigio_handler(int sig, union uml_pt_regs *regs) 45void sigio_handler(int sig, union uml_pt_regs *regs)
45{ 46{
46 struct irq_fd *irq_fd, *next; 47 struct irq_fd *irq_fd;
47 int i, n; 48 int i, n;
48 49
49 if(smp_sigio_handler()) return; 50 if(smp_sigio_handler()) return;
@@ -66,29 +67,15 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
66 irq_fd = irq_fd->next; 67 irq_fd = irq_fd->next;
67 } 68 }
68 69
69 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ 70 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
70 next = irq_fd->next;
71 if(irq_fd->current_events != 0){ 71 if(irq_fd->current_events != 0){
72 irq_fd->current_events = 0; 72 irq_fd->current_events = 0;
73 do_IRQ(irq_fd->irq, regs); 73 do_IRQ(irq_fd->irq, regs);
74
75 /* This is here because the next irq may be
76 * freed in the handler. If a console goes
77 * away, both the read and write irqs will be
78 * freed. After do_IRQ, ->next will point to
79 * a good IRQ.
80 * Irqs can't be freed inside their handlers,
81 * so the next best thing is to have them
82 * marked as needing freeing, so that they
83 * can be freed here.
84 */
85 next = irq_fd->next;
86 if(irq_fd->freed){
87 free_irq(irq_fd->irq, irq_fd->id);
88 }
89 } 74 }
90 } 75 }
91 } 76 }
77
78 free_irqs();
92} 79}
93 80
94int activate_ipi(int fd, int pid) 81int activate_ipi(int fd, int pid)
@@ -136,8 +123,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
136 .irq = irq, 123 .irq = irq,
137 .pid = pid, 124 .pid = pid,
138 .events = events, 125 .events = events,
139 .current_events = 0, 126 .current_events = 0 } );
140 .freed = 0 } );
141 127
142 /* Critical section - locked by a spinlock because this stuff can 128 /* Critical section - locked by a spinlock because this stuff can
143 * be changed from interrupt handlers. The stuff above is done 129 * be changed from interrupt handlers. The stuff above is done
@@ -313,26 +299,6 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
313 return(irq); 299 return(irq);
314} 300}
315 301
316void free_irq_later(int irq, void *dev_id)
317{
318 struct irq_fd *irq_fd;
319 unsigned long flags;
320
321 flags = irq_lock();
322 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
323 if((irq_fd->irq == irq) && (irq_fd->id == dev_id))
324 break;
325 }
326 if(irq_fd == NULL){
327 printk("free_irq_later found no irq, irq = %d, "
328 "dev_id = 0x%p\n", irq, dev_id);
329 goto out;
330 }
331 irq_fd->freed = 1;
332 out:
333 irq_unlock(flags);
334}
335
336void reactivate_fd(int fd, int irqnum) 302void reactivate_fd(int fd, int irqnum)
337{ 303{
338 struct irq_fd *irq; 304 struct irq_fd *irq;