diff options
Diffstat (limited to 'arch/um/drivers/line.c')
-rw-r--r-- | arch/um/drivers/line.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index d0f97127adf6..025d3be8aca4 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
@@ -462,12 +462,15 @@ out: | |||
462 | return err; | 462 | return err; |
463 | } | 463 | } |
464 | 464 | ||
465 | static void unregister_winch(struct tty_struct *tty); | ||
466 | |||
465 | void line_close(struct tty_struct *tty, struct file * filp) | 467 | void line_close(struct tty_struct *tty, struct file * filp) |
466 | { | 468 | { |
467 | struct line *line = tty->driver_data; | 469 | struct line *line = tty->driver_data; |
468 | 470 | ||
469 | /* XXX: I assume this should be called in process context, not with interrupt | 471 | /* XXX: I assume this should be called in process context, not with |
470 | * disabled!*/ | 472 | * interrupts disabled! |
473 | */ | ||
471 | spin_lock_irq(&line->lock); | 474 | spin_lock_irq(&line->lock); |
472 | 475 | ||
473 | /* We ignore the error anyway! */ | 476 | /* We ignore the error anyway! */ |
@@ -478,6 +481,12 @@ void line_close(struct tty_struct *tty, struct file * filp) | |||
478 | line_disable(tty, -1); | 481 | line_disable(tty, -1); |
479 | tty->driver_data = NULL; | 482 | tty->driver_data = NULL; |
480 | } | 483 | } |
484 | |||
485 | if((line->count == 0) && line->sigio){ | ||
486 | unregister_winch(tty); | ||
487 | line->sigio = 0; | ||
488 | } | ||
489 | |||
481 | spin_unlock_irq(&line->lock); | 490 | spin_unlock_irq(&line->lock); |
482 | } | 491 | } |
483 | 492 | ||
@@ -729,6 +738,34 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) | |||
729 | up(&winch_handler_sem); | 738 | up(&winch_handler_sem); |
730 | } | 739 | } |
731 | 740 | ||
741 | static void unregister_winch(struct tty_struct *tty) | ||
742 | { | ||
743 | struct list_head *ele; | ||
744 | struct winch *winch, *found = NULL; | ||
745 | |||
746 | down(&winch_handler_sem); | ||
747 | list_for_each(ele, &winch_handlers){ | ||
748 | winch = list_entry(ele, struct winch, list); | ||
749 | if(winch->tty == tty){ | ||
750 | found = winch; | ||
751 | break; | ||
752 | } | ||
753 | } | ||
754 | |||
755 | if(found == NULL) | ||
756 | goto out; | ||
757 | |||
758 | if(winch->pid != -1) | ||
759 | os_kill_process(winch->pid, 1); | ||
760 | |||
761 | free_irq_by_irq_and_dev(WINCH_IRQ, winch); | ||
762 | free_irq(WINCH_IRQ, winch); | ||
763 | list_del(&winch->list); | ||
764 | kfree(winch); | ||
765 | out: | ||
766 | up(&winch_handler_sem); | ||
767 | } | ||
768 | |||
732 | static void winch_cleanup(void) | 769 | static void winch_cleanup(void) |
733 | { | 770 | { |
734 | struct list_head *ele; | 771 | struct list_head *ele; |