diff options
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/drivers/line.c | 54 |
1 files changed, 24 insertions, 30 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index a3c39373adb9..46ceb25a9959 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
@@ -774,55 +774,49 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) | |||
774 | printk("register_winch_irq - failed to register IRQ\n"); | 774 | printk("register_winch_irq - failed to register IRQ\n"); |
775 | } | 775 | } |
776 | 776 | ||
777 | static void free_winch(struct winch *winch) | ||
778 | { | ||
779 | list_del(&winch->list); | ||
780 | |||
781 | if(winch->pid != -1) | ||
782 | os_kill_process(winch->pid, 1); | ||
783 | if(winch->fd != -1) | ||
784 | os_close_file(winch->fd); | ||
785 | |||
786 | free_irq(WINCH_IRQ, winch); | ||
787 | kfree(winch); | ||
788 | } | ||
789 | |||
777 | static void unregister_winch(struct tty_struct *tty) | 790 | static void unregister_winch(struct tty_struct *tty) |
778 | { | 791 | { |
779 | struct list_head *ele; | 792 | struct list_head *ele; |
780 | struct winch *winch, *found = NULL; | 793 | struct winch *winch; |
781 | 794 | ||
782 | spin_lock(&winch_handler_lock); | 795 | spin_lock(&winch_handler_lock); |
796 | |||
783 | list_for_each(ele, &winch_handlers){ | 797 | list_for_each(ele, &winch_handlers){ |
784 | winch = list_entry(ele, struct winch, list); | 798 | winch = list_entry(ele, struct winch, list); |
785 | if(winch->tty == tty){ | 799 | if(winch->tty == tty){ |
786 | found = winch; | 800 | free_winch(winch); |
787 | break; | 801 | break; |
788 | } | 802 | } |
789 | } | 803 | } |
790 | if(found == NULL) | ||
791 | goto err; | ||
792 | |||
793 | list_del(&winch->list); | ||
794 | spin_unlock(&winch_handler_lock); | ||
795 | |||
796 | if(winch->pid != -1) | ||
797 | os_kill_process(winch->pid, 1); | ||
798 | |||
799 | free_irq(WINCH_IRQ, winch); | ||
800 | kfree(winch); | ||
801 | |||
802 | return; | ||
803 | err: | ||
804 | spin_unlock(&winch_handler_lock); | 804 | spin_unlock(&winch_handler_lock); |
805 | } | 805 | } |
806 | 806 | ||
807 | /* XXX: No lock as it's an exitcall... is this valid? Depending on cleanup | ||
808 | * order... are we sure that nothing else is done on the list? */ | ||
809 | static void winch_cleanup(void) | 807 | static void winch_cleanup(void) |
810 | { | 808 | { |
811 | struct list_head *ele; | 809 | struct list_head *ele, *next; |
812 | struct winch *winch; | 810 | struct winch *winch; |
813 | 811 | ||
814 | list_for_each(ele, &winch_handlers){ | 812 | spin_lock(&winch_handler_lock); |
813 | |||
814 | list_for_each_safe(ele, next, &winch_handlers){ | ||
815 | winch = list_entry(ele, struct winch, list); | 815 | winch = list_entry(ele, struct winch, list); |
816 | if(winch->fd != -1){ | 816 | free_winch(winch); |
817 | /* Why is this different from the above free_irq(), | ||
818 | * which deactivates SIGIO? This searches the FD | ||
819 | * somewhere else and removes it from the list... */ | ||
820 | deactivate_fd(winch->fd, WINCH_IRQ); | ||
821 | os_close_file(winch->fd); | ||
822 | } | ||
823 | if(winch->pid != -1) | ||
824 | os_kill_process(winch->pid, 1); | ||
825 | } | 817 | } |
818 | |||
819 | spin_unlock(&winch_handler_lock); | ||
826 | } | 820 | } |
827 | __uml_exitcall(winch_cleanup); | 821 | __uml_exitcall(winch_cleanup); |
828 | 822 | ||